mirror of
https://github.com/immich-app/immich.git
synced 2026-06-24 07:28:30 -07:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d74a11f979 | |||
| fb0d356ea7 | |||
| 9d6c219276 | |||
| f29f86542c | |||
| 5165cf1d2f | |||
| f4c8459484 | |||
| 22ec449e43 | |||
| 0b1019c344 | |||
| 06f3b4f259 | |||
| 99f94a363d | |||
| c3092b1c2c | |||
| 0656e7e231 | |||
| 1692b81b7c | |||
| ff2028c4c8 | |||
| f22836e1bf |
@@ -85,7 +85,7 @@ services:
|
||||
container_name: immich_prometheus
|
||||
ports:
|
||||
- 9090:9090
|
||||
image: prom/prometheus@sha256:69f5241418838263316593f7274a304b095c40bcf22e57272865da91bd60a8ac
|
||||
image: prom/prometheus@sha256:a75c5a35bc21d7afe69551eefa3cb1e1fb1775fe759408007a66b54ec3de1f29
|
||||
volumes:
|
||||
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- prometheus-data:/prometheus
|
||||
|
||||
+35
-4
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"about": "حول",
|
||||
"account": "حساب",
|
||||
"account": "الحساب",
|
||||
"account_settings": "إعدادات الحساب",
|
||||
"acknowledge": "أُدرك ذلك",
|
||||
"action": "إجراء",
|
||||
"action": "الإجراء",
|
||||
"action_common_update": "تحديث",
|
||||
"action_description": "مجموعة إجراءات لتنفيذها على المحتويات المصفاة",
|
||||
"actions": "عمليات",
|
||||
@@ -189,13 +189,25 @@
|
||||
"machine_learning_smart_search_enabled": "تفعيل البحث الذكي",
|
||||
"machine_learning_smart_search_enabled_description": "إذا تم تعطيله، فلن يتم ترميز الصور للبحث الذكي.",
|
||||
"machine_learning_url_description": "عنوان URL لخادم التعلم الآلي. إذا تم توفير أكثر من عنوان URL واحد، سيتم محاولة الاتصال بكل خادم على حدة حتى يستجيب أحدهم بنجاح، بدءًا من الأول إلى الأخير. سيتم تجاهل الخوادم التي لا تستجيب مؤقتًا حتى تعود للعمل.",
|
||||
"maintenance_backup_management": "إدارة النسخ الاحتياطي",
|
||||
"maintenance_delete_backup": "حذف النسخ الاحتياطي",
|
||||
"maintenance_delete_backup_description": "هذا الملف سيتم حذفه بشكل لا رجعه فيه.",
|
||||
"maintenance_delete_error": "فشل حذف النسخ الاحتياطي.",
|
||||
"maintenance_integrity_check": "تحقق",
|
||||
"maintenance_integrity_check_all": "تحديد الكل",
|
||||
"maintenance_integrity_checksum_mismatch": "عدم تطابق رمز التحقق",
|
||||
"maintenance_integrity_checksum_mismatch_description": "الملفات التي لا يتطابق المجموع التدقيقي لها على القرص مع المجموع التدقيقي المخزن في قاعدة بيانات Immich.",
|
||||
"maintenance_integrity_checksum_mismatch_job": "التحقق من عدم تطابق المجموع التدقيقي",
|
||||
"maintenance_integrity_checksum_mismatch_refresh_job": "تحديث تقارير عدم تطابق المجموع التدقيقي",
|
||||
"maintenance_integrity_missing_file": "الملفات المفقودة",
|
||||
"maintenance_integrity_missing_file_description": "الملفات التي يتتبعها Immich في قاعدة بياناته ولكنها غير موجودة في نظام الملفات.",
|
||||
"maintenance_integrity_missing_file_job": "التحقق من الملفات المفقودة",
|
||||
"maintenance_integrity_missing_file_refresh_job": "تحديث تقارير الملفات المفقودة",
|
||||
"maintenance_integrity_report": "تقرير السلامة",
|
||||
"maintenance_integrity_untracked_file": "الملفات غير المتتبعة",
|
||||
"maintenance_integrity_untracked_file_description": "الملفات الموجودة في مجلدات Immich بدون وجود سجلات لها.",
|
||||
"maintenance_integrity_untracked_file_job": "التحقق من الملفات غير المتتبعة",
|
||||
"maintenance_integrity_untracked_file_refresh_job": "تحديث تقارير الملفات غير المتتبعة",
|
||||
"maintenance_restore_backup": "استعادة النسخ الاحتياطي",
|
||||
"maintenance_restore_backup_description": "سيتم مسح بيانات Immich واستعادتها من النسخة الاحتياطي المختار. سيتم إنشاء نسخة احتياطية قبل المتابعة.",
|
||||
"maintenance_restore_backup_different_version": "هذا النسخ الاحتياطي تم انشائه باستخدام اصدار مختلف من Immich!",
|
||||
@@ -575,6 +587,7 @@
|
||||
"asset_added_to_album": "تمت إضافته إلى الألبوم",
|
||||
"asset_adding_to_album": "جارٍ الإضافة إلى الألبوم…",
|
||||
"asset_created": "انشئ اصل",
|
||||
"asset_day_count": "{date}: {count, plural, zero {لا توجد ملفات} one {ملف واحد} two {ملفان} few {# ملفات} many {# ملفًا} other {# ملف}}",
|
||||
"asset_description_updated": "تم تحديث وصف المحتوى",
|
||||
"asset_filename_is_offline": "الأصل {filename} غير متصل",
|
||||
"asset_has_unassigned_faces": "يحتوي الأصل على وجوه غير مخصصة",
|
||||
@@ -704,6 +717,7 @@
|
||||
"backup_settings_subtitle": "إدارة إعدادات التحميل",
|
||||
"backup_upload_details_page_more_details": "اضغط لتفاصيل اضافية",
|
||||
"backward": "الى الوراء",
|
||||
"battery_optimization_backup_reliability": "إيقاف تحسين البطارية يزيد من استقرار النسخ الاحتياطي في الخلفية",
|
||||
"biometric_auth_enabled": "المصادقة البايومترية مفعله",
|
||||
"biometric_locked_out": "لقد قفلت عنك المصادقة البيومترية",
|
||||
"biometric_no_options": "لا توجد خيارات بايومترية متوفرة",
|
||||
@@ -918,6 +932,8 @@
|
||||
"deduplicate_all": "إلغاء تكرار الكل",
|
||||
"default_locale": "الإعدادات المحلية الافتراضية",
|
||||
"default_locale_description": "تنسيق التواريخ والأرقام بناءً على الإعدادات المحلية للمتصفح",
|
||||
"default_quality_subtitle": "الجودة المستخدمة عند الضغط على \"مشاركة\". اضغط مطولاً على زر المشاركة لاختيار الجودة في كل مرة.",
|
||||
"default_share_quality": "جودة المشاركة الافتراضية",
|
||||
"delete": "حذف",
|
||||
"delete_action_confirmation_message": "هل انت متأكد من حذف هذا الملف؟ هذا سؤدي الى نقل الملف الى سلة مهملات الخادم وسيتم اشعارك ان كنت تريد حذفه على الجهاز",
|
||||
"delete_action_prompt": "تم حذف {count}",
|
||||
@@ -1227,6 +1243,7 @@
|
||||
"failed": "فشل",
|
||||
"failed_count": "فشل: {count}",
|
||||
"failed_to_authenticate": "فشل في المصادقة",
|
||||
"failed_to_delete_file": "فشل حذف الملف",
|
||||
"failed_to_load_assets": "فشل تحميل الأصول",
|
||||
"failed_to_load_folder": "فشل تحميل المجلد",
|
||||
"favorite": "مفضل",
|
||||
@@ -1357,6 +1374,7 @@
|
||||
"individual_share": "حصة فردية",
|
||||
"individual_shares": "المشاركات الفردية",
|
||||
"info": "معلومات",
|
||||
"integrity_checks": "فحوصات السلامة",
|
||||
"interval": {
|
||||
"day_at_onepm": "كل يوم الساعة الواحدة ظهرا",
|
||||
"hours": "كل {hours, plural, one {ساعة} other {{hours, number} ساعة}}",
|
||||
@@ -1404,6 +1422,7 @@
|
||||
"leave": "مغادرة",
|
||||
"leave_album": "اترك الالبوم",
|
||||
"lens_model": "نموذج العدسات",
|
||||
"less": "أقل",
|
||||
"let_others_respond": "دع الآخرين يستجيبون",
|
||||
"level": "المستوى",
|
||||
"library": "مكتبة",
|
||||
@@ -1428,6 +1447,7 @@
|
||||
"linked_oauth_account": "حساب مرتبط بـ OAuth",
|
||||
"list": "قائمة",
|
||||
"live": "حي",
|
||||
"load_more": "تحميل المزيد",
|
||||
"loading": "تحميل",
|
||||
"loading_search_results_failed": "فشل تحميل نتائج البحث",
|
||||
"local": "محلّي",
|
||||
@@ -1528,7 +1548,6 @@
|
||||
"map_location_picker_page_use_location": "استخدم هذا الموقع",
|
||||
"map_location_service_disabled_content": "يجب تمكين خدمة الموقع لعرض الأصول من موقعك الحالي.هل تريد تمكينه الآن؟",
|
||||
"map_location_service_disabled_title": "خدمة الموقع معطل",
|
||||
"map_marker_for_images": "علامة الخريطة للصور الملتقطة في {city}، {country}",
|
||||
"map_marker_with_image": "علامة الخريطة مع الصورة",
|
||||
"map_no_location_permission_content": "هناك حاجة إلى إذن الموقع لعرض الأصول من موقعك الحالي.هل تريد السماح به الآن؟",
|
||||
"map_no_location_permission_title": "تم رفض إذن الموقع",
|
||||
@@ -1597,6 +1616,8 @@
|
||||
"merge_people_prompt": "هل تريد دمج هؤلاء الناس؟ هذا الإجراء لا رجعة فيه.",
|
||||
"merge_people_successfully": "تم دمج الأشخاص بنجاح",
|
||||
"merged_people_count": "دمج {count, plural, one {شخص واحد} other {# أشخاص}}",
|
||||
"minFaces": "الحد الأدنى للوجوه",
|
||||
"minFaces_description": "الحد الأدنى لعدد الوجوه المتعرف عليها لكي يتم عرض الشخص",
|
||||
"minimize": "تصغير",
|
||||
"minute": "دقيقة",
|
||||
"minutes": "دقائق",
|
||||
@@ -1692,6 +1713,7 @@
|
||||
"not_selected": "لم يختار",
|
||||
"notes": "ملاحظات",
|
||||
"nothing_here_yet": "لا يوجد شيء هنا بعد",
|
||||
"notification_backup_reliability": "فعل الإشعارات للزيادة من استقرار النسخ الاحتياطي في الخلفية",
|
||||
"notification_permission_dialog_content": "لتمكين الإخطارات ، انتقل إلى الإعدادات و اختار السماح.",
|
||||
"notification_permission_list_tile_content": "منح إذن لتمكين الإخطارات.",
|
||||
"notification_permission_list_tile_enable_button": "تمكين الإخطارات",
|
||||
@@ -2083,6 +2105,7 @@
|
||||
"select_person": "اختر شخص",
|
||||
"select_person_to_tag": "اختر شخص لوضع علامة",
|
||||
"select_photos": "تحديد الصور",
|
||||
"select_quality": "تحديد الدقة",
|
||||
"select_trash_all": "تحديد حذف الكلِ",
|
||||
"select_user_for_sharing_page_err_album": "فشل في إنشاء ألبوم",
|
||||
"selected": "التحديد",
|
||||
@@ -2146,6 +2169,8 @@
|
||||
"share_assets_selected": "اختيار {count}",
|
||||
"share_dialog_preparing": "تحضير...",
|
||||
"share_link": "مشاركة رابط",
|
||||
"share_original": "استخدام الملف الأصلي",
|
||||
"share_preview": "استخدام الصورة المصغرة",
|
||||
"shared": "مُشتَرك",
|
||||
"shared_album_activities_input_disable": "التعليق معطل",
|
||||
"shared_album_activity_remove_content": "هل تريد حذف هذا النشاط؟",
|
||||
@@ -2247,6 +2272,7 @@
|
||||
"slideshow_repeat_description": "العودة إلى البداية عند انتهاء عرض الشرائح",
|
||||
"slideshow_settings": "إعدادات عرض الشرائح",
|
||||
"smart_album": "ألبوم ذكي",
|
||||
"some_assets_already_have_a_location_warning": "بعض الملفات المحددة تحتوي بالفعل على موقع جغرافي",
|
||||
"sort_albums_by": "رتب الألبومات حسب...",
|
||||
"sort_created": "تاريخ الإنشاء",
|
||||
"sort_items": "عدد العناصر",
|
||||
@@ -2367,11 +2393,13 @@
|
||||
"trash_page_title": "سلة المهملات ({count})",
|
||||
"trashed_items_will_be_permanently_deleted_after": "سيتم حذفُ العناصر المحذوفة نِهائيًا بعد {days, plural, one {# يوم} other {# أيام }}.",
|
||||
"trigger": "مفعِل",
|
||||
"trigger_asset_metadata_extraction": "استخراج البيانات الوصفية للملفات",
|
||||
"trigger_asset_metadata_extraction_description": "يتم تفعيله عند استخراج البيانات الوصفية (EXIF) للملف",
|
||||
"trigger_asset_uploaded": "رفع الاصل",
|
||||
"trigger_asset_uploaded_description": "يتم تفعيله عند تحميل أصل جديد",
|
||||
"trigger_description": "حدث يبدأ سير العمل",
|
||||
"trigger_person_recognized": "تم التعرف على شخص",
|
||||
"trigger_person_recognized_description": "يتم تفعيله عند اكتشاف شخص",
|
||||
"trigger_person_recognized_description": "يتم تفعيله عند التعرف على شخص",
|
||||
"trigger_type": "نوع المفعل",
|
||||
"troubleshoot": "استكشاف المشاكل",
|
||||
"type": "النوع",
|
||||
@@ -2413,6 +2441,7 @@
|
||||
"updated_password": "تم تحديث كلمة المرور",
|
||||
"upload": "رفع",
|
||||
"upload_concurrency": "الرفع المتزامن",
|
||||
"upload_day_count": "{date}: {count, plural, one {# رفع الملف} other {# رفع الملفات}}",
|
||||
"upload_details": "تفاصيل الرفع",
|
||||
"upload_dialog_info": "هل تريد النسخ الاحتياطي للأصول (الأصول) المحددة إلى الخادم؟",
|
||||
"upload_dialog_title": "تحميل الأصول",
|
||||
@@ -2428,6 +2457,8 @@
|
||||
"upload_to_immich": "الرفع الىImmich ({count})",
|
||||
"uploading": "جاري الرفع",
|
||||
"uploading_media": "رفع الوسائط",
|
||||
"uploads": "عمليات الرفع",
|
||||
"uploads_count": "{count, plural, one {# رفع الملف} other {# رفع الملفات}}",
|
||||
"url": "عنوان URL",
|
||||
"usage": "الاستخدام",
|
||||
"use_biometric": "استخدم البايومتري",
|
||||
|
||||
@@ -1520,7 +1520,6 @@
|
||||
"map_location_picker_page_use_location": "Выкарыстаць гэта месцазнаходжанне",
|
||||
"map_location_service_disabled_content": "Каб паказваць аб’екты з вашага бягучага месцазнаходжання, трэба ўключыць службу геалакацыі. Жадаеце ўключыць яе зараз?",
|
||||
"map_location_service_disabled_title": "Служба геалакацыі адключана",
|
||||
"map_marker_for_images": "Маркер на карце для відарысаў, зробленых у {city}, {country}",
|
||||
"map_marker_with_image": "Маркер на карце з відарысам",
|
||||
"map_no_location_permission_content": "Каб паказваць аб’екты з вашага бягучага месцазнаходжання, патрэбен дазвол на геалакацыю. Дазволіць зараз?",
|
||||
"map_no_location_permission_title": "Адмоўлена ў дазволе на геалакацыю",
|
||||
|
||||
+1
-1
@@ -1548,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Използвай това местоположение",
|
||||
"map_location_service_disabled_content": "За да се показват обектите от текущото място, трябва да бъде включена услугата за местоположение. Искате ли да я включите сега?",
|
||||
"map_location_service_disabled_title": "Услугата за местоположение е изключена",
|
||||
"map_marker_for_images": "Маркери на картата за снимки направени в {city}, {country}",
|
||||
"map_marker_for_image": "Маркер на картата за снимка, направена в {city}, {country}",
|
||||
"map_marker_with_image": "Маркер на картата с изображение",
|
||||
"map_no_location_permission_content": "За да се показват обектите от текущото място, трябва разрешение за определяне на местоположението. Искате ли да предоставите разрешение сега?",
|
||||
"map_no_location_permission_title": "Отказан достъп до местоположение",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"add_partner": "অংশীদার যোগ করুন",
|
||||
"add_path": "পাথ যুক্ত করুন",
|
||||
"add_photos": "ছবি যুক্ত করুন",
|
||||
"add_step": "ধাপ যোগ করুন",
|
||||
"add_tag": "ট্যাগ যুক্ত করুন",
|
||||
"add_to": "যুক্ত করুন…",
|
||||
"add_to_album": "এলবাম এ যোগ করুন",
|
||||
@@ -78,6 +79,7 @@
|
||||
"cron_expression_description": "Cron ফরম্যাট ব্যবহার করে স্ক্যানিং ইন্টারভ্যাল নির্ধারণ করুন। আরও তথ্যের জন্য দয়া করে <link>Crontab Guru</link> দেখুন",
|
||||
"cron_expression_presets": "Cron এক্সপ্রেশন প্রিসেট",
|
||||
"disable_login": "লগইন অক্ষম করুন",
|
||||
"download_csv": "CSV ডাউনলোড করুন",
|
||||
"duplicate_detection_job_description": "সদৃশ ছবি শনাক্ত করতে অ্যাসেটগুলোর উপর মেশিন লার্নিং চালান। এটি Smart Search-এর উপর নির্ভর করে",
|
||||
"exclusion_pattern_description": "এক্সক্লুশন প্যাটার্ন ব্যবহার করে লাইব্রেরি স্ক্যান করার সময় নির্দিষ্ট ফাইল ও ফোল্ডার উপেক্ষা করা যায়। এটি তখনই উপকারী যখন কিছু ফোল্ডারে এমন ফাইল থাকে যা আপনি ইমপোর্ট করতে চান না, যেমন RAW ফাইল।",
|
||||
"export_config_as_json_description": "বর্তমান সিস্টেম কনফিগারেশনটিকে একটি JSON ফাইল হিসেবে ডাউনলোড করুন",
|
||||
@@ -187,9 +189,11 @@
|
||||
"machine_learning_smart_search_enabled": "স্মার্ট সার্চ সক্ষম করুন",
|
||||
"machine_learning_smart_search_enabled_description": "নিষ্ক্রিয় থাকলে, স্মার্ট সার্চের জন্য ছবিগুলো এনকোড (encode) করা হবে না।",
|
||||
"machine_learning_url_description": "মেশিন লার্নিং সার্ভারের URL। যদি একের বেশি URL প্রদান করা হয়, তবে একটি সফলভাবে সাড়া না দেওয়া পর্যন্ত প্রতিটি সার্ভারে এক এক করে চেষ্টা করা হবে (প্রথম থেকে শেষ ক্রমানুসারে)। যে সার্ভারগুলো সাড়া দেবে না, সেগুলো পুনরায় সচল হওয়া পর্যন্ত সাময়িকভাবে উপেক্ষা করা হবে।",
|
||||
"maintenance_backup_management": "ব্যাকআপ ব্যবস্থাপনা",
|
||||
"maintenance_delete_backup": "ব্যাকআপ (Backup)মুছুন",
|
||||
"maintenance_delete_backup_description": "এই ফাইলটি চিরতরে মুছে ফেলা হবে।",
|
||||
"maintenance_delete_error": "ব্যাকআপ মুছে ফেলতে ব্যর্থ হয়েছে।",
|
||||
"maintenance_integrity_check": "যাচাই",
|
||||
"maintenance_restore_backup": "ব্যাকআপ পুনরুদ্ধার(Restore) করুন",
|
||||
"maintenance_restore_backup_description": "Immich মুছে ফেলা হবে এবং নির্বাচিত ব্যাকআপ থেকে পুনরুদ্ধার করা হবে। কার্যক্রম চালিয়ে যাওয়ার আগে একটি ব্যাকআপ তৈরি করা হবে।",
|
||||
"maintenance_restore_backup_different_version": "এই ব্যাকআপটি Immich-এর একটি ভিন্ন সংস্করণের মাধ্যমে তৈরি করা হয়েছিল!",
|
||||
|
||||
+7
-2
@@ -189,18 +189,23 @@
|
||||
"machine_learning_smart_search_enabled": "Activa la cerca intel·ligent",
|
||||
"machine_learning_smart_search_enabled_description": "Si està desactivada, les imatges no es codificaran per la cerca intel·ligent.",
|
||||
"machine_learning_url_description": "L'URL del servidor d'aprenentatge automàtic. Si es proporciona més d'un URL, s'intentarà accedir a cada servidor en ordre fins que un d'ells respongui correctament.",
|
||||
"maintenance_backup_management": "Gestió de còpies de seguretat",
|
||||
"maintenance_delete_backup": "Elimina la còpia de seguretat",
|
||||
"maintenance_delete_backup_description": "Aquest fitxer s'eliminarà de forma permanent.",
|
||||
"maintenance_delete_error": "No s'ha pogut suprimir la còpia de seguretat.",
|
||||
"maintenance_integrity_check": "Verificació",
|
||||
"maintenance_integrity_check_all": "Verificar tot",
|
||||
"maintenance_integrity_checksum_mismatch": "Checksum incorrecte",
|
||||
"maintenance_integrity_checksum_mismatch_description": "Fitxers els quals la suma de verificació al disc no coincideix amb la que Immich té emmagatzemada a la base de dades.",
|
||||
"maintenance_integrity_checksum_mismatch_job": "Comprovar checksums",
|
||||
"maintenance_integrity_checksum_mismatch_refresh_job": "Actualitzar errors de checksums",
|
||||
"maintenance_integrity_missing_file": "Manquen fitxers",
|
||||
"maintenance_integrity_missing_file_description": "Fitxers que l'Immich té registrats a la seva base de dades però que no existeixen al sistema de fitxers.",
|
||||
"maintenance_integrity_missing_file_job": "Verificar fitxers que falten",
|
||||
"maintenance_integrity_missing_file_refresh_job": "Refrescar informe de fitxers desapareguts",
|
||||
"maintenance_integrity_report": "Informe Integritat",
|
||||
"maintenance_integrity_untracked_file": "Arxius no rastrejats",
|
||||
"maintenance_integrity_untracked_file_description": "Fitxers presents als directoris d'Immich que Immich no en té cap registre.",
|
||||
"maintenance_integrity_untracked_file_job": "Consulta de fitxers no rastrejats",
|
||||
"maintenance_integrity_untracked_file_refresh_job": "Actualitza els informes de fitxers no rastrejats",
|
||||
"maintenance_restore_backup": "Restaura la còpia de seguretat",
|
||||
@@ -483,7 +488,7 @@
|
||||
"advanced_settings_prefer_remote_title": "Prefereix imatges remotes",
|
||||
"advanced_settings_proxy_headers_subtitle": "Definiu les capçaleres de proxy que Immich per enviar amb cada sol·licitud de xarxa",
|
||||
"advanced_settings_proxy_headers_title": "Capçaleres de proxy particulars [EXPERIMENTAL]",
|
||||
"advanced_settings_readonly_mode_subtitle": "Habilita el només de lectura mode on les fotos poden ser només vist, a coses els agrada seleccionant imatges múltiples, compartint, càsting, elimina és tot discapacitat. Habilita/Desactiva només de lectura via avatar d'usuari des de la pantalla major",
|
||||
"advanced_settings_readonly_mode_subtitle": "Activa el mode de només lectura, en què les fotos només es poden veure. Accions com seleccionar múltiples imatges, compartir, enviar a un dispositiu o eliminar queden desactivades. Activa o desactiva el mode de només lectura des de l’avatar d’usuari de la pantalla principal",
|
||||
"advanced_settings_readonly_mode_title": "Mode de només lectura",
|
||||
"advanced_settings_self_signed_ssl_subtitle": "Omet la verificació del certificat SSL del servidor. Requerit per a certificats autosignats.",
|
||||
"advanced_settings_self_signed_ssl_title": "Permet certificats SSL autosignats [EXPERIMENTAL]",
|
||||
@@ -1543,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Utilitzar aquesta ubicació",
|
||||
"map_location_service_disabled_content": "El servei de localització s'ha d'activar per mostrar els elements de la teva ubicació actual. Vols activar-lo ara?",
|
||||
"map_location_service_disabled_title": "Servei de localització desactivat",
|
||||
"map_marker_for_images": "Marcador de mapa per a imatges fetes a {city}, {country}",
|
||||
"map_marker_for_image": "Marcador de mapa per a imatge obtinguda a {city}, {country}",
|
||||
"map_marker_with_image": "Marcador de mapa amb imatge",
|
||||
"map_no_location_permission_content": "Es necessita el permís de localització per mostrar els elements de la teva ubicació actual. Vols permetre-ho ara?",
|
||||
"map_no_location_permission_title": "Permís de localització denegat",
|
||||
|
||||
+1
-1
@@ -1548,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Použít tuto polohu",
|
||||
"map_location_service_disabled_content": "Pro zobrazení fotek z vaší aktuální polohy musí být povolena služba určování polohy. Chcete ji nyní povolit?",
|
||||
"map_location_service_disabled_title": "Služba určování polohy je zakázána",
|
||||
"map_marker_for_images": "Značka na mapě pro snímky pořízené v {city}, {country}",
|
||||
"map_marker_for_image": "Značka na mapě pro obrázek pořízený ve městě {city}, {country}",
|
||||
"map_marker_with_image": "Značka mapy s obrázkem",
|
||||
"map_no_location_permission_content": "Oprávnění polohy je nutné pro zobrazení fotek z vaší aktuální polohy. Chcete oprávnění nyní povolit?",
|
||||
"map_no_location_permission_title": "Oprávnění polohy zamítnuto",
|
||||
|
||||
@@ -70,7 +70,6 @@
|
||||
"feature_photo_updated": "Уйрӑм сӑнӳкерчӗк ҫӗнетнӗ",
|
||||
"manage_sharing_with_partners": "Партнерсемпе пайланассине йӗркелесе пырӑр",
|
||||
"map": "Карттӑ",
|
||||
"map_marker_for_images": "{city}, {country} ҫинче ӳкернӗ ӳкерчӗксем валли карттӑ маркерӗ",
|
||||
"map_marker_with_image": "Карттӑ маркерӗ ӳкерчӗкпе",
|
||||
"map_settings": "Карттӑ ĕнерленĕвĕ",
|
||||
"no_explore_results_message": "Хӑвӑр коллекципе киленмешкӗн сӑнӳкерчӗксем ытларах тийӗр.",
|
||||
|
||||
@@ -1526,7 +1526,6 @@
|
||||
"map_location_picker_page_use_location": "Brug denne placering",
|
||||
"map_location_service_disabled_content": "Placeringstjenesten skal aktiveres for at vise elementer fra din nuværende placering. Vil du aktivere den nu?",
|
||||
"map_location_service_disabled_title": "Placeringstjenesten er deaktiveret",
|
||||
"map_marker_for_images": "Kortmarkør for billeder taget i {city}, {country}",
|
||||
"map_marker_with_image": "Kortmarkør med billede",
|
||||
"map_no_location_permission_content": "Der kræves tilladelse til placeringen for at vise elementer fra din nuværende placering. Vil du give tilladelse?",
|
||||
"map_no_location_permission_title": "Placeringstilladelse blev afvist",
|
||||
|
||||
+1
-1
@@ -1548,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Diesen Standort verwenden",
|
||||
"map_location_service_disabled_content": "Ortungsdienste müssen aktiviert sein, um Inhalte am aktuellen Standort anzuzeigen. Willst du die Ortungsdienste jetzt aktivieren?",
|
||||
"map_location_service_disabled_title": "Ortungsdienste deaktiviert",
|
||||
"map_marker_for_images": "Kartenmarkierung für Bilder, die in {city}, {country} aufgenommen wurden",
|
||||
"map_marker_for_image": "Kartenmarkierung für in {city}, {country} aufgenommenes Bild",
|
||||
"map_marker_with_image": "Kartenmarkierung mit Bild",
|
||||
"map_no_location_permission_content": "Ortungsdienste müssen aktiviert sein, um Inhalte am aktuellen Standort anzuzeigen. Willst du die Ortungsdienste jetzt aktivieren?",
|
||||
"map_no_location_permission_title": "Kein Zugriff auf den Standort",
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
"cron_expression_description": "Setze das Scanintervall im Cron-Format. Für mehr Informationen, siehe z. B. <link>Crontab Guru</link>",
|
||||
"cron_expression_presets": "Vorlagen für Cron-Ausdrücke",
|
||||
"disable_login": "Login deaktivierä",
|
||||
"download_csv": "CSV herunterladen",
|
||||
"duplicate_detection_job_description": "Verwendet maschinelles Lernen auf den Dateien, um Duplikate zu finden. Baut auf der intelligenten Suche auf",
|
||||
"exclusion_pattern_description": "Mit Ausschlussmustern können Dateien und Ordner beim Scannen deiner Bibliothek ignoriert werden. Dies ist nützlich, wenn du Ordner hast, die Dateien enthalten, die du nicht importieren möchtest, wie z. B. RAW-Dateien.",
|
||||
"export_config_as_json_description": "Aktuelle Systemkonfiguration als JSON-Datei herunterladen",
|
||||
|
||||
@@ -1495,7 +1495,6 @@
|
||||
"map_location_picker_page_use_location": "Χρησιμοποιήστε αυτήν την τοποθεσία",
|
||||
"map_location_service_disabled_content": "Η υπηρεσία τοποθεσίας πρέπει να είναι ενεργοποιημένη για την εμφάνιση στοιχείων από την τρέχουσα τοποθεσία σας. Θέλετε να το ενεργοποιήσετε τώρα;",
|
||||
"map_location_service_disabled_title": "Η υπηρεσία τοποθεσίας απενεργοποιήθηκε",
|
||||
"map_marker_for_images": "Δείκτης χάρτη για εικόνες που τραβήχτηκαν σε {city}, {country}",
|
||||
"map_marker_with_image": "Χάρτης δείκτη με εικόνα",
|
||||
"map_no_location_permission_content": "Απαιτείται άδεια τοποθεσίας για την εμφάνιση στοιχείων από την τρέχουσα τοποθεσία σας. Θέλετε να το επιτρέψετε τώρα;",
|
||||
"map_no_location_permission_title": "Η άδεια τοποθεσίας απορρίφθηκε",
|
||||
|
||||
+4
-315
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1548,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Use this location",
|
||||
"map_location_service_disabled_content": "Location service needs to be enabled to display assets from your current location. Do you want to enable it now?",
|
||||
"map_location_service_disabled_title": "Location Service disabled",
|
||||
"map_marker_for_images": "Map marker for images taken in {city}, {country}",
|
||||
"map_marker_for_image": "Map marker for image taken in {city}, {country}",
|
||||
"map_marker_with_image": "Map marker with image",
|
||||
"map_no_location_permission_content": "Location permission is needed to display assets from your current location. Do you want to allow it now?",
|
||||
"map_no_location_permission_title": "Location Permission denied",
|
||||
|
||||
+99
-2
@@ -199,6 +199,15 @@
|
||||
"maintenance_integrity_checksum_mismatch_description": "Dosieroj pri kiuj la kontrolsumo stokita sur disko ne kongruas kun tiu en la datumbazo de Immich.",
|
||||
"maintenance_integrity_checksum_mismatch_job": "Kontroli pri nekongruaj kontrolsumoj",
|
||||
"maintenance_integrity_checksum_mismatch_refresh_job": "Refreŝigi la raporton pri nekongruaj kontrolsumoj",
|
||||
"maintenance_integrity_missing_file": "Dosieroj mankantaj",
|
||||
"maintenance_integrity_missing_file_description": "Dosieroj menciitaj en la datumbazo de Immich, sed kiuj ne (plu) ekzistas en la dosiersistemo.",
|
||||
"maintenance_integrity_missing_file_job": "Detekti mankantajn dosierojn",
|
||||
"maintenance_integrity_missing_file_refresh_job": "Refreŝigi raporton pri mankantaj dosieroj",
|
||||
"maintenance_integrity_report": "Raporto pri integreco",
|
||||
"maintenance_integrity_untracked_file": "Senspuraj dosieroj",
|
||||
"maintenance_integrity_untracked_file_description": "Dosieroj en la dosierujoj de Immich, sed pri kiuj Immich havas neniun spuron.",
|
||||
"maintenance_integrity_untracked_file_job": "Detekti senspurajn dosierojn",
|
||||
"maintenance_integrity_untracked_file_refresh_job": "Refreŝigi raporton pri senspuraj dosieroj",
|
||||
"maintenance_restore_backup": "Restaŭri savkopion",
|
||||
"maintenance_restore_backup_description": "Immich estos forigita kaj reinstalita de la elektita savkopio. Nova savkopio estos kreita antaŭe.",
|
||||
"maintenance_restore_backup_different_version": "Tiu ĉi savkopio estis kreita per alia versio de Immich!",
|
||||
@@ -740,7 +749,7 @@
|
||||
"cache_settings_title": "Agordoj pri kaŝmemoro",
|
||||
"camera": "Fotilo",
|
||||
"camera_brand": "Fabrikanto de fotilo",
|
||||
"camera_model": "Modelo de fotilo",
|
||||
"camera_model": "Tipo de fotilo",
|
||||
"cancel": "Nuligi",
|
||||
"cancel_search": "Nuligi serĉon",
|
||||
"canceled": "Nuligita",
|
||||
@@ -1454,6 +1463,7 @@
|
||||
"log_out_all_devices": "Elsalutigi ĉiujn aparatojn",
|
||||
"logged_in_as": "Ensalutita kiel {user}",
|
||||
"logged_out_all_devices": "Ĉiuj aparatoj elsalutigitaj",
|
||||
"logged_out_device": "Elsalutigita aparato",
|
||||
"login": "Ensaluti",
|
||||
"login_disabled": "Ensalutado malebligita",
|
||||
"login_form_api_exception": "Eraro de API. Bonvolu kontroli la URL-on de la servilo, kaj reprovi.",
|
||||
@@ -1529,7 +1539,6 @@
|
||||
"map_location_picker_page_use_location": "Uzi tiun ĉi lokon",
|
||||
"map_location_service_disabled_content": "Vi devas ŝalti la lokadan servon de via aparato por vidi elementojn de via aktuala loko. Ĉu vi volas nun ŝalti tion?",
|
||||
"map_location_service_disabled_title": "Servo de lokado malŝaltita",
|
||||
"map_marker_for_images": "Map-markilo por fotoj faritaj en {city}, {country}",
|
||||
"map_marker_with_image": "Map-markilo kun bildo",
|
||||
"map_no_location_permission_content": "Vi devas permesi al la apo detekti vian aktualan lokon por vidi tieajn elementojn. Ĉu vi volas nun permesi tion?",
|
||||
"map_no_location_permission_title": "Detektado de loko ne permesita",
|
||||
@@ -1638,6 +1647,9 @@
|
||||
"navigate_to_time": "Navigi al dato/horo",
|
||||
"network_requirement_photos_upload": "Uzi datumojn de poŝtelefona reto por savkopii fotojn",
|
||||
"network_requirement_videos_upload": "Uzi datumojn de poŝtelefona reto por savkopii videojn",
|
||||
"network_requirements": "Retaj postuloj",
|
||||
"network_requirements_updated": "Retaj postuloj ŝanĝiĝis, savkopia vico restarigita",
|
||||
"networking_settings": "Retkonektoj",
|
||||
"networking_subtitle": "Administri agordojn pri finpunktoj de la servilo",
|
||||
"never": "Neniam",
|
||||
"new_album": "Nova albumo",
|
||||
@@ -1888,6 +1900,13 @@
|
||||
"readonly_mode_disabled": "Nurlega reĝimo malŝaltita",
|
||||
"readonly_mode_enabled": "Nurlega reĝimo ŝaltita",
|
||||
"ready_for_upload": "Preta por alŝuto",
|
||||
"reassign": "Reatribui",
|
||||
"reassigned_assets_to_existing_person": "Reatribuis {count, plural, one {# elementon} other {# elementojn}} al {name, select, null {ekzistanta homo} other {{name}}}",
|
||||
"reassigned_assets_to_new_person": "Reatribuis {count, plural, one {# elementon} other {# elementojn}} al nova homo",
|
||||
"reassing_hint": "Reatribuis elektitajn elementojn al ekzistanta homo",
|
||||
"recent": "Lastatempa(j)",
|
||||
"recent_albums": "Lastatempaj albumoj",
|
||||
"recent_searches": "Lastatempaj serĉoj",
|
||||
"recently_added": "Lastatempe aldonita(j)",
|
||||
"recently_added_page_title": "Lastatempe aldonita(j)",
|
||||
"recently_taken": "Lastatempe fotita(j)",
|
||||
@@ -1911,21 +1930,73 @@
|
||||
"remove_assets_shared_link_confirmation": "Ĉu vi certas, ke vi volas forigi {count, plural, one {# elementon} other {# elementojn}} de tiu dividita ligilo?",
|
||||
"remove_assets_title": "Ĉu forigi elementojn?",
|
||||
"remove_custom_date_range": "Forigi la dat-intervalon",
|
||||
"remove_filter": "Forigi filtron",
|
||||
"remove_from_album": "Forpreni de albumo",
|
||||
"remove_from_album_action_prompt": "{count} forprenitaj de la albumo",
|
||||
"remove_from_favorites": "Forigi el preferataĵoj",
|
||||
"remove_from_lock_folder_action_prompt": "{count} forprenitaj de la ŝlosita dosierujo",
|
||||
"remove_from_locked_folder": "Forpreni de la ŝlosita dosierujo",
|
||||
"remove_from_locked_folder_confirmation": "Ĉu vi certas, ke vi volas forpreni tiujn fotojn/videojn el la ŝlosita dosierujo? Ili poste estos videblaj en via biblioteko.",
|
||||
"remove_from_shared_link": "Forigi el dividita ligilo",
|
||||
"remove_memory": "Forigi memoraĵon",
|
||||
"remove_photo_from_memory": "Forpreni foton el tiu memoraĵo",
|
||||
"remove_tag": "Forigi etikedon",
|
||||
"remove_url": "Forigi URL-on",
|
||||
"remove_user": "Forigi uzanton",
|
||||
"removed_api_key": "Forigita API-ŝlosilo: {name}",
|
||||
"removed_from_archive": "Forigita de la arĥivo",
|
||||
"removed_from_favorites": "Forigita(j) el preferataĵoj",
|
||||
"removed_from_favorites_count": "{count, plural, other {Forigis #}} el Preferataĵoj",
|
||||
"removed_memory": "Memoraĵo forigita",
|
||||
"removed_photo_from_memory": "Forprenis foton de la memoraĵo",
|
||||
"removed_tagged_assets": "Forigis etikedon de {count, plural, one {# elemento} other {# elementoj}}",
|
||||
"rename": "Renomi",
|
||||
"repair": "Ripari",
|
||||
"repair_no_results_message": "Senspuraj kaj mankantaj dosieroj aperas ĉi tie",
|
||||
"replace_with_upload": "Anstataŭigi per alŝutaĵo",
|
||||
"repository": "Deponejo",
|
||||
"require_password": "Postuli pasvorton",
|
||||
"require_user_to_change_password_on_first_login": "Devigi al uzanto ŝanĝi pasvorton je unua ensaluto",
|
||||
"rescan": "Reanalizi",
|
||||
"reset": "Restartigi",
|
||||
"reset_password": "Restarigi pasvorton",
|
||||
"reset_people_visibility": "Restarigi videblecon de homoj",
|
||||
"reset_pin_code": "Restarigi PIN-kodon",
|
||||
"reset_pin_code_description": "Se vi forgesis vian PIN-kodon, vi povas kontakti la administranto de via servilo por restarigi ĝin",
|
||||
"reset_pin_code_success": "Sukcese restarigis PIN-kodon",
|
||||
"reset_pin_code_with_password": "Vi povas restarigi vian PIN-kodon pere de via pasvorto",
|
||||
"reset_sqlite": "Restarigi la SQLite-datumbazon",
|
||||
"reset_sqlite_clear_app_data": "Forviŝi datumojn",
|
||||
"reset_sqlite_confirmation": "Ĉu vi certas, ke vi volas forviŝi la datumojn de la apo? Tio forigos ĉiujn agordojn kaj elsalutigos vin.",
|
||||
"reset_sqlite_confirmation_note": "Noto: vi devos relanĉi la apon por la forviŝo.",
|
||||
"reset_sqlite_done": "Datumoj de la apo estas forviŝitaj. Bonvolu relanĉi Immich kaj ensalutu denove.",
|
||||
"reset_sqlite_success": "Sukcese restarigis la SQLite-datumbazon",
|
||||
"reset_to_default": "Restarigi la defaŭltojn",
|
||||
"resolution": "Distingivo",
|
||||
"resolve_duplicates": "Solvi duoblaĵojn",
|
||||
"resolved_all_duplicates": "Solvis ĉiujn duoblaĵojn",
|
||||
"restore": "Restaŭri",
|
||||
"restore_all": "Restaŭri ĉiujn",
|
||||
"restore_trash_action_prompt": "{count} restaŭrita(j) el rubujo",
|
||||
"restore_user": "Restaŭri uzanton",
|
||||
"restored_asset": "Restaŭri elementon",
|
||||
"resume": "Daŭrigi",
|
||||
"resume_paused_jobs": "Daŭrigi {count, plural, one {# paŭzitan taskon} other {# paŭzitajn taskojn}}",
|
||||
"retry_upload": "Reprovi alŝuton",
|
||||
"review_duplicates": "Kontroli duoblaĵojn",
|
||||
"review_large_files": "Kontroli grandajn dosierojn",
|
||||
"role": "Rolo",
|
||||
"role_editor": "Redaktanto",
|
||||
"role_viewer": "Spektanto",
|
||||
"running": "Aktuale plenumata(j)",
|
||||
"save": "Konservi",
|
||||
"save_to_gallery": "Konservi en galerio",
|
||||
"saved": "Konservita(j)",
|
||||
"saved_api_key": "Konservis API-ŝlosilon",
|
||||
"saved_profile": "Konservis profilon",
|
||||
"saved_settings": "Konservis agordojn",
|
||||
"say_something": "Skribu ion",
|
||||
"scaffold_body_error_occurred": "Eraro okazis",
|
||||
"scaffold_body_error_unrecoverable": "Neriparebla eraro okazis. Bonvolu sendi al ni la eraron kaj la stakspuron per Discord aŭ per Github por ke ni povu helpi. Vi povas forviŝi la ĉi-subajn datumojn de la apo se vi volas.",
|
||||
"scan": "Analizi",
|
||||
"scan_all_libraries": "Analizi ĉiujn bibliotekojn",
|
||||
@@ -1933,7 +2004,33 @@
|
||||
"scan_settings": "Agordoj pri analizado",
|
||||
"scanning": "Analizado",
|
||||
"scanning_for_album": "Serĉado de albumo...",
|
||||
"screencast_mode_description": "Montri indikilojn surekrane pri tuŝoj de klavaro kaj muso",
|
||||
"screencast_mode_title": "Baskuligi reĝimon de elsendo",
|
||||
"search": "Serĉi",
|
||||
"search_albums": "Serĉi albumojn",
|
||||
"search_by_context": "Serĉi laŭ kunteksto",
|
||||
"search_by_description": "Serĉi laŭ priskribo",
|
||||
"search_by_description_example": "Promenado en Poznań",
|
||||
"search_by_filename": "Serĉi laŭ dosiernomo aŭ sufikso",
|
||||
"search_by_filename_example": "ekz. IMG_1234.jpg aŭ png",
|
||||
"search_by_full_path": "Serĉi laŭ dosier-vojo aŭ dosierujo",
|
||||
"search_by_full_path_example": "/Silvja/Projektoj/3D_Printado/2026-07-01 - vi povas serĉi 'Projektoj', '3D', 'Printado', '2026', ktp.",
|
||||
"search_by_ocr": "Serĉi per optika signo-rekono",
|
||||
"search_by_ocr_example": "Invitilo",
|
||||
"search_camera_lens_model": "Serĉi tipon de objektivo...",
|
||||
"search_camera_make": "Serĉi fabrikanton de fotilo...",
|
||||
"search_camera_model": "Serĉi tipon de fotilo...",
|
||||
"search_city": "Serĉi urbon...",
|
||||
"search_country": "Serĉi landon...",
|
||||
"search_filter_apply": "Apliki filtrilon",
|
||||
"search_filter_camera_title": "Elektu tipon de fotilo",
|
||||
"search_filter_date": "Dato",
|
||||
"search_filter_date_interval": "de {start} ĝis {end}",
|
||||
"search_filter_date_title": "Elektu intervalon de datoj",
|
||||
"search_filter_display_option_not_in_album": "Ne en albumo",
|
||||
"search_filter_display_options": "Agordoj pri aranĝo sur ekrano",
|
||||
"search_filter_filename": "Serĉi laŭ dosiernomo",
|
||||
"search_filter_location": "Loko",
|
||||
"search_suggestion_list_smart_search_hint_1": "Inteligenta serĉado defaŭlte estas ŝaltita. Por serĉi metadatumojn, uzu sintakson tiel ",
|
||||
"select_user_for_sharing_page_err_album": "Malsukcesis krei albumon",
|
||||
"server_privacy": "Privateco de servilo",
|
||||
|
||||
+2
-2
@@ -59,7 +59,7 @@
|
||||
"backup_onboarding_1_description": "Copia en un lugar externo, en la nube u otra ubicación física.",
|
||||
"backup_onboarding_2_description": "copias locales en diferentes dispositivos. Incluye los archivos principales y una copia de seguridad local de dichos archivos.",
|
||||
"backup_onboarding_3_description": "copias totales de tu data, incluyendo los archivos originales. Incluye 1 copia fuera de sitio y 2 copias locales.",
|
||||
"backup_onboarding_description": "Se recomienda una <backblaze-link>estrategia de copia de seguridad 3-2-1</backblaze-link> para proteger tus datos. Deberías mantener copias de las fotos y vídeos que subas, así como de la base de datos de Immich, para contar con una solución de copia de seguridad completa.",
|
||||
"backup_onboarding_description": "Una <backblaze-link>estrategia de copia de seguridad 3-2-1</backblaze-link> es recomendada para proteger tus datos. Deberías mantener copias de las fotos y vídeos que subas, así como de la base de datos de Immich, para contar con una solución de copia de seguridad completa.",
|
||||
"backup_onboarding_footer": "Para obtener más información sobre cómo hacer una copia de seguridad de Immich, consulta la <link>documentación</link>.",
|
||||
"backup_onboarding_parts_title": "Una copia de seguridad 3-2-1 incluye:",
|
||||
"backup_onboarding_title": "Copias de seguridad",
|
||||
@@ -1548,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Usar esta ubicación",
|
||||
"map_location_service_disabled_content": "Los servicios de ubicación deben estar activados para mostrar recursos de tu ubicación actual. ¿Deseas activarlos ahora?",
|
||||
"map_location_service_disabled_title": "Servicios de ubicación desactivados",
|
||||
"map_marker_for_images": "Marcador de mapa para imágenes tomadas en {city}, {country}",
|
||||
"map_marker_for_image": "Marcador del mapa para la imagen tomada en {city}, {country}",
|
||||
"map_marker_with_image": "Marcador de mapa con imagen",
|
||||
"map_no_location_permission_content": "Se necesitan permisos de ubicación para mostrar recursos de tu ubicación actual. ¿Deseas activarlos ahora?",
|
||||
"map_no_location_permission_title": "Permisos de ubicación denegados",
|
||||
|
||||
+11
-1
@@ -189,11 +189,17 @@
|
||||
"machine_learning_smart_search_enabled": "Luba nutiotsing",
|
||||
"machine_learning_smart_search_enabled_description": "Kui keelatud, siis ei kodeerita pilte nutiotsingu jaoks.",
|
||||
"machine_learning_url_description": "Masinõppe serveri URL. Kui ette on antud rohkem kui üks URL, proovitakse neid järjest ükshaaval, kuni üks edukalt vastab. Servereid, mis ei vasta, ignoreeritakse ajutiselt, kuni ühendus taastub.",
|
||||
"maintenance_backup_management": "Varunduse haldus",
|
||||
"maintenance_delete_backup": "Kustuta varukoopia",
|
||||
"maintenance_delete_backup_description": "See fail kustutatakse jäädavalt.",
|
||||
"maintenance_delete_error": "Varukoopia kustutamine ebaõnnestus.",
|
||||
"maintenance_integrity_check_all": "Märgi kõik",
|
||||
"maintenance_integrity_checksum_mismatch": "Kontrollsumma ebakõla",
|
||||
"maintenance_integrity_checksum_mismatch_description": "Failid, mille kontrollsumma ei klapi sellega, mis on Immich'i andmebaasis.",
|
||||
"maintenance_integrity_checksum_mismatch_job": "Otsi kontrollsumma ebakõlasid",
|
||||
"maintenance_integrity_checksum_mismatch_refresh_job": "Värskenda kontrollsumma ebakõlade aruanne",
|
||||
"maintenance_integrity_missing_file": "Puuduvad failid",
|
||||
"maintenance_integrity_missing_file_description": "Failid, mida Immich jälgib andmebaasis, kuid mida ei eksisteeri failisüsteemis.",
|
||||
"maintenance_integrity_missing_file_job": "Otsi puuduvaid faile",
|
||||
"maintenance_integrity_missing_file_refresh_job": "Värskenda puuduvate failide aruanne",
|
||||
"maintenance_integrity_untracked_file": "Mittejälgitavad failid",
|
||||
@@ -923,6 +929,8 @@
|
||||
"deduplicate_all": "Dedubleeri kõik",
|
||||
"default_locale": "Vaikimisi lokaat",
|
||||
"default_locale_description": "Vorminda kuupäevad ja arvud vastavalt brauseri lokaadile",
|
||||
"default_quality_subtitle": "Kvaliteet, mida jagamisel kasutada. Hoia jagamise nuppu all, et iga kord valida.",
|
||||
"default_share_quality": "Vaikimisi jagamise kvaliteet",
|
||||
"delete": "Kustuta",
|
||||
"delete_action_confirmation_message": "Kas oled kindel, et soovid selle üksuse kustutada? See toiming liigutab üksuse serveri prügikasti ja küsib, kas soovid selle lokaalselt kustutada",
|
||||
"delete_action_prompt": "{count} kustutatud",
|
||||
@@ -1535,7 +1543,7 @@
|
||||
"map_location_picker_page_use_location": "Kasuta seda asukohta",
|
||||
"map_location_service_disabled_content": "Praeguse asukoha üksuste kuvamiseks tuleb lubada asukoha teenus. Kas soovid seda praegu lubada?",
|
||||
"map_location_service_disabled_title": "Asukoha teenus keelatud",
|
||||
"map_marker_for_images": "Kaardimarker kohas {city}, {country} tehtud piltide jaoks",
|
||||
"map_marker_for_image": "Kaardimarker pildile, mis on tehtud kohas {city}, {country}",
|
||||
"map_marker_with_image": "Kaardimarker pildiga",
|
||||
"map_no_location_permission_content": "Praeguse asukoha üksuste kuvamiseks on vaja asukoha luba. Kas soovid seda praegu lubada?",
|
||||
"map_no_location_permission_title": "Asukoha luba keelatud",
|
||||
@@ -2376,6 +2384,8 @@
|
||||
"trash_page_title": "Prügikast ({count})",
|
||||
"trashed_items_will_be_permanently_deleted_after": "Prügikasti tõstetud üksused kustutatakse jäädavalt {days, plural, one {# päeva} other {# päeva}} pärast.",
|
||||
"trigger": "Päästik",
|
||||
"trigger_asset_metadata_extraction": "Üksuste metaandmete eraldamine",
|
||||
"trigger_asset_metadata_extraction_description": "Käivitub, kui üksusest eraldatakse EXIF metaandmed",
|
||||
"trigger_asset_uploaded": "Üksuse üleslaadimine",
|
||||
"trigger_asset_uploaded_description": "Käivitub uue üksuse üleslaadimisel",
|
||||
"trigger_description": "Sündmus, mis käivitab töövoo",
|
||||
|
||||
+1231
-12
File diff suppressed because it is too large
Load Diff
@@ -605,7 +605,6 @@
|
||||
"map_location_picker_page_use_location": "استفاده از این موقعیت مکانی",
|
||||
"map_location_service_disabled_content": "برای نمایش داراییها بر اساس موقعیت مکانی، نیاز به فعالسازی سرویس مکانیابی دارید. میخواهید همین حالا فعال شود؟",
|
||||
"map_location_service_disabled_title": "سرویس مکانیابی غیرفعال است",
|
||||
"map_marker_for_images": "نشانگر روی نقشه برای عکسهای گرفتهشده در {city}, {country}",
|
||||
"map_marker_with_image": "علامتگذاری نقشه با عکس",
|
||||
"map_no_location_permission_content": "برای نمایش عکسهای اطرافتان، برنامه نیاز به دسترسی به موقعیت مکانی دارد. اجازه دسترسی میدهید؟",
|
||||
"map_no_location_permission_title": "دسترسی به موقعیت شما فعال نیست",
|
||||
|
||||
@@ -1504,7 +1504,6 @@
|
||||
"map_location_picker_page_use_location": "Käytä tätä sijaintia",
|
||||
"map_location_service_disabled_content": "Paikannuspalvelun pitää olla kytkettynä päälle, jotta nykyisen sijaintisi kohteita voidaan näyttää. Haluatko kytkeä sen päälle nyt?",
|
||||
"map_location_service_disabled_title": "Paikannuspalvelu pois päältä",
|
||||
"map_marker_for_images": "Karttamarkerointi kuville, jotka on otettu kaupungissa {city}, maassa {country}",
|
||||
"map_marker_with_image": "Karttamarkerointi kuvalla",
|
||||
"map_no_location_permission_content": "Paikannuslupa tarvitaan, jotta nykyisen sijainnin kohteita voidaan näyttää. Haluatko sallia pääsyn sijaintiin?",
|
||||
"map_no_location_permission_title": "Paikannuslupa estetty",
|
||||
|
||||
@@ -15,29 +15,36 @@
|
||||
"add_a_location": "Dagdagan ng lugar",
|
||||
"add_a_name": "Dagdagan ng pangalan",
|
||||
"add_a_title": "Dagdagan ng pamagat",
|
||||
"add_action": "Magdagdag ng aksyon",
|
||||
"add_assets": "Dagdagan ng asset",
|
||||
"add_birthday": "Maglagay ng kaarawan",
|
||||
"add_endpoint": "Dagdagan ng dulo",
|
||||
"add_exclusion_pattern": "Magdagdag ng exlusion pattern",
|
||||
"add_location": "Magdagdag ng lugar",
|
||||
"add_more_users": "Magdagdag ng mga user",
|
||||
"add_partner": "Magdagdag ng kasangga",
|
||||
"add_path": "Magdagdag ng path",
|
||||
"add_photos": "Magdagdag ng litrato",
|
||||
"add_step": "Magdagdag ng step",
|
||||
"add_tag": "Magdagdag ng tag",
|
||||
"add_to": "Idagdag sa…",
|
||||
"add_to_album": "Idagdag sa album",
|
||||
"add_to_album_bottom_sheet_added": "Naidagdag sa {album}",
|
||||
"add_to_album_bottom_sheet_already_exists": "Nasa {album} na",
|
||||
"add_to_album_bottom_sheet_some_local_assets": "May ilang mga local assets ang hindi maidagdag sa album",
|
||||
"add_to_album_toggle": "Toggle selection para sa {album}",
|
||||
"add_to_albums": "Idagdag sa mga album",
|
||||
"add_to_albums_count": "Idagdag sa mga album ({count})",
|
||||
"add_to_bottom_bar": "Idagdag sa",
|
||||
"add_to_shared_album": "Idagdag sa shared album",
|
||||
"add_upload_to_stack": "Magdagdag ng upload para ma-stack",
|
||||
"add_url": "Magdagdag ng URL",
|
||||
"added_to_archive": "Naidagdag sa archive",
|
||||
"added_to_favorites": "Naidagdag sa mga paborito",
|
||||
"added_to_favorites_count": "Naidagdag ang {count, number} sa mga paborito",
|
||||
"admin": {
|
||||
"add_exclusion_pattern_description": "Dagdagan ng pattern para maibukod. Supportado ang pag-tutugma gamit ang *, **, at ?. Para hindi maisama ang mga file sa direktoryo na may pangalang \"Raw\", gamitin ang \"**/Raw/**\". Para hindi maisama ang lahat ng mga file na nagtatapos sa \".tif\", gamitin ang \"**/*.tif\". Para hindi maisama ang isang tiyak na folder, gamitin ang \"/path/to/ignore/**\".",
|
||||
"admin_user": "Admin User",
|
||||
"asset_offline_description": "Ang external library asset na ito ay hindi na makikita sa disk at nailipat na sa basurahan. Kung ang file ay nailipat sa loob ng library, tignan ang iyong timeline para sa kaukulang asset. Para maibalik ang asset na ito, siguraduhin na ang file ay maa-access ng Immich at muling i-scan ang library.",
|
||||
"authentication_settings": "Setting ng mga Pagkakakilanlan",
|
||||
"authentication_settings_description": "Pamahalaan ang password, OAuth, and iba pang setting ng pagkakakilanlan",
|
||||
@@ -68,6 +75,7 @@
|
||||
"disable_login": "I-disable ang login",
|
||||
"duplicate_detection_job_description": "Hanapin ang mga magkakatulad na imahe gamit ang machine learning. Umaasa sa Smart Search",
|
||||
"exclusion_pattern_description": "Maaaring gamitin ang mga pattern na pangbukod para hindi pansinin ang ilang file o folder habang binabasa ang iyong library. Mainam itong solusyon para sa mga folder na may file na ayaw niyong ma-import, tulad ng mga RAW na file.",
|
||||
"face_detection": "Face detection",
|
||||
"force_delete_user_warning": "BABALA: Tatanggalin itong user at lahat ng asset nila, Hindi ito mababawi at ang kanilang files ay hindi na mababalik",
|
||||
"image_format": "Format",
|
||||
"note_cannot_be_changed_later": "TANDAAN: Hindi na ito pwede baguhin sa susunod!",
|
||||
|
||||
+1
-1
@@ -1548,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Utiliser ma position",
|
||||
"map_location_service_disabled_content": "Le service de localisation doit être activé pour afficher les médias de votre emplacement actuel. Souhaitez-vous l'activer maintenant ?",
|
||||
"map_location_service_disabled_title": "Service de localisation désactivé",
|
||||
"map_marker_for_images": "Marqueur de carte pour les images prises à {city}, {country}",
|
||||
"map_marker_for_image": "Marqueur de carte pour une image prise à {city}, {country}",
|
||||
"map_marker_with_image": "Marqueur de carte avec image",
|
||||
"map_no_location_permission_content": "L'autorisation de localisation est nécessaire pour afficher les médias de votre emplacement actuel. Souhaitez-vous l'autoriser maintenant ?",
|
||||
"map_no_location_permission_title": "Permission de localisation refusée",
|
||||
|
||||
+5
-1
@@ -189,18 +189,23 @@
|
||||
"machine_learning_smart_search_enabled": "Cumasaigh cuardach cliste",
|
||||
"machine_learning_smart_search_enabled_description": "Mura bhfuil sé sin ar fáil, ní dhéanfar íomhánna a ionchódú le haghaidh cuardaigh chliste.",
|
||||
"machine_learning_url_description": "URL an fhreastalaí foghlama meaisín. Má chuirtear níos mó ná URL amháin ar fáil, déanfar iarracht ar gach freastalaí ceann ag an am go dtí go bhfreagróidh ceann acu go rathúil, in ord ón gcéad cheann go dtí an ceann deireanach. Déanfar neamhaird shealadach ar fhreastalaithe nach bhfreagróidh go dtí go mbeidh siad ar líne arís.",
|
||||
"maintenance_backup_management": "Bainistíocht chúltaca",
|
||||
"maintenance_delete_backup": "Scrios Cúltaca",
|
||||
"maintenance_delete_backup_description": "Scriosfar an comhad seo go neamh-inchúlghairthe.",
|
||||
"maintenance_delete_error": "Theip ar an gcúltaca a scriosadh.",
|
||||
"maintenance_integrity_check": "Seiceáil",
|
||||
"maintenance_integrity_check_all": "Seiceáil Gach Rud",
|
||||
"maintenance_integrity_checksum_mismatch": "Mí-chomhoiriúnacht suime seiceála",
|
||||
"maintenance_integrity_checksum_mismatch_description": "Comhaid nach bhfuil an tsuim seiceála ar an diosca ag teacht leis an tsuim seiceála atá stóráilte ag Immich ina bhunachar sonraí.",
|
||||
"maintenance_integrity_checksum_mismatch_job": "Seiceáil le haghaidh mí-oiriúnuithe suime seiceála",
|
||||
"maintenance_integrity_checksum_mismatch_refresh_job": "Athnuachan tuairiscí mí-oiriúnachta suime seiceála",
|
||||
"maintenance_integrity_missing_file": "Comhaid ar Iarraidh",
|
||||
"maintenance_integrity_missing_file_description": "Comhaid atá rianaithe ag Immich ina bhunachar sonraí ach nach bhfuil ar fáil ar an gcóras comhad.",
|
||||
"maintenance_integrity_missing_file_job": "Seiceáil le haghaidh comhaid atá ar iarraidh",
|
||||
"maintenance_integrity_missing_file_refresh_job": "Athnuachan tuairiscí ar chomhaid atá ar iarraidh",
|
||||
"maintenance_integrity_report": "Tuarascáil Ionracais",
|
||||
"maintenance_integrity_untracked_file": "Comhaid Gan Rianú",
|
||||
"maintenance_integrity_untracked_file_description": "Comhaid in eolairí Immich nach bhfuil aon taifead ag Immich orthu.",
|
||||
"maintenance_integrity_untracked_file_job": "Seiceáil le haghaidh comhaid neamhrianaithe",
|
||||
"maintenance_integrity_untracked_file_refresh_job": "Athnuachan tuarascálacha comhad neamhrianaithe",
|
||||
"maintenance_restore_backup": "Athchóirigh Cúltaca",
|
||||
@@ -1543,7 +1548,6 @@
|
||||
"map_location_picker_page_use_location": "Úsáid an suíomh seo",
|
||||
"map_location_service_disabled_content": "Ní mór seirbhís suímh a chumasú chun sócmhainní ó do shuíomh reatha a thaispeáint. Ar mhaith leat é a chumasú anois?",
|
||||
"map_location_service_disabled_title": "Seirbhís Suímh díchumasaithe",
|
||||
"map_marker_for_images": "Marcóir léarscáile le haghaidh íomhánna a tógadh i {city}, {country}",
|
||||
"map_marker_with_image": "Marcóir léarscáile le híomhá",
|
||||
"map_no_location_permission_content": "Tá cead suímh ag teastáil chun sócmhainní a thaispeáint ó do shuíomh reatha. Ar mhaith leat é a cheadú anois?",
|
||||
"map_no_location_permission_title": "Cead Suímh diúltaithe",
|
||||
|
||||
@@ -1548,7 +1548,6 @@
|
||||
"map_location_picker_page_use_location": "Usar esta localización",
|
||||
"map_location_service_disabled_content": "O servizo de localización debe estar activado para mostrar activos da súa localización actual. Quere activalo agora?",
|
||||
"map_location_service_disabled_title": "Servizo de localización deshabilitado",
|
||||
"map_marker_for_images": "Marcador de mapa para imaxes tomadas en {city}, {country}",
|
||||
"map_marker_with_image": "Marcador de mapa con imaxe",
|
||||
"map_no_location_permission_content": "Necesítase permiso de localización para mostrar activos da súa localización actual. Quere permitilo agora?",
|
||||
"map_no_location_permission_title": "Permiso de localización denegado",
|
||||
|
||||
+4
-2
@@ -1391,7 +1391,6 @@
|
||||
"map_location_picker_page_use_location": "Ufnahmeort verwände",
|
||||
"map_location_service_disabled_content": "D’Ortigsdienscht müend aktiviert si, um Inhält am aktuelle Standort aazeige z chönne. Wotsch d’Ortigsdienscht jetzt aktiviere?",
|
||||
"map_location_service_disabled_title": "Ortigsdienscht deaktiviert",
|
||||
"map_marker_for_images": "Charte-Markierige für Bilder, wo i {city}, {country} ufgnoh worde sind",
|
||||
"map_marker_with_image": "Charte-Markierig mit Bild",
|
||||
"map_no_location_permission_content": "D’Ortigsdienscht müend aktiviert si, um Inhält am aktuelle Standort aazeige z chönne. Wotsch d’Ortigsdienscht jetzt aktiviere?",
|
||||
"map_no_location_permission_title": "Kei Zuegriff uf dä Standort",
|
||||
@@ -1528,5 +1527,8 @@
|
||||
"on_this_device": "Uf däm Grät",
|
||||
"onboarding": "Iistig",
|
||||
"onboarding_locale_description": "Wähl dini bevorzugti Sprooch. Du chasch die au spöter i dine Iistellige ändere.",
|
||||
"onboarding_privacy_description": "Diä folgende (optionali) Funktione hänged vo externä Diänscht ab und chönd jederziit i de Iistellige deaktiviärt wärde."
|
||||
"onboarding_privacy_description": "Diä folgende (optionali) Funktione hänged vo externä Diänscht ab und chönd jederziit i de Iistellige deaktiviärt wärde.",
|
||||
"upload_finished": "Ufelade beändet",
|
||||
"users": "Benutzer",
|
||||
"waiting": "Usstehend"
|
||||
}
|
||||
|
||||
@@ -1498,7 +1498,6 @@
|
||||
"map_location_picker_page_use_location": "השתמש במיקום הזה",
|
||||
"map_location_service_disabled_content": "שירות המיקום צריך להיות מופעל כדי להציג תמונות מהמיקום הנוכחי שלך. האם ברצונך להפעיל אותו עכשיו?",
|
||||
"map_location_service_disabled_title": "שירות מיקום מבוטל",
|
||||
"map_marker_for_images": "סמן מפה לתמונות שצולמו ב{city}, {country}",
|
||||
"map_marker_with_image": "סמן מפה עם תמונה",
|
||||
"map_no_location_permission_content": "יש צורך בהרשאה למיקום כדי להציג תמונות מהמיקום הנוכחי שלך. האם ברצונך לאפשר זאת עכשיו?",
|
||||
"map_no_location_permission_title": "הרשאה למיקום נדחתה",
|
||||
|
||||
@@ -1479,7 +1479,6 @@
|
||||
"map_location_picker_page_use_location": "इस स्थान का उपयोग करें",
|
||||
"map_location_service_disabled_content": "आपके वर्तमान स्थान की संपत्तियाँ प्रदर्शित करने के लिए स्थान सेवा सक्षम होनी चाहिए। क्या आप इसे अभी सक्षम करना चाहते हैं?",
|
||||
"map_location_service_disabled_title": "स्थान सेवा अक्षम",
|
||||
"map_marker_for_images": "{city}, {country} में ली गई छवियों के लिए मानचित्र मार्कर",
|
||||
"map_marker_with_image": "छवि के साथ मानचित्र मार्कर",
|
||||
"map_no_location_permission_content": "आपके वर्तमान स्थान से संपत्तियाँ प्रदर्शित करने के लिए स्थान अनुमति आवश्यक है। क्या आप इसे अभी अनुमति देना चाहते हैं?",
|
||||
"map_no_location_permission_title": "स्थान की अनुमति अस्वीकृत",
|
||||
|
||||
@@ -1414,7 +1414,6 @@
|
||||
"map_location_picker_page_use_location": "Koristi ovu lokaciju",
|
||||
"map_location_service_disabled_content": "Usluga lokacije mora biti omogućena za prikaz stavki s vaše trenutne lokacije. Želite li je sada omogućiti?",
|
||||
"map_location_service_disabled_title": "Usluga lokacije onemogućena",
|
||||
"map_marker_for_images": "Oznaka karte za slike snimljene u {city}, {country}",
|
||||
"map_marker_with_image": "Oznaka karte sa slikom",
|
||||
"map_no_location_permission_content": "Potrebno je dopuštenje za lokaciju kako bi se prikazale stavke s vaše trenutne lokacije. Želite li ga sada omogućiti?",
|
||||
"map_no_location_permission_title": "Dopuštenje za lokaciju odbijeno",
|
||||
|
||||
+2
-2
@@ -1548,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Kiválasztott hely használata",
|
||||
"map_location_service_disabled_content": "A helymeghatározás szolgáltatást engedélyezni kell a jelenlegi helyednél lévő elemek megjelenítéséhez. Szeretnéd most engedélyezni?",
|
||||
"map_location_service_disabled_title": "Helymeghatározás szolgáltatás letiltva",
|
||||
"map_marker_for_images": "{country}, {city} helyen készült képek térképjelölője",
|
||||
"map_marker_for_image": "Térképjelölő a következő helyen készült képhez: {city}, {country}",
|
||||
"map_marker_with_image": "Térképjelölő képpel",
|
||||
"map_no_location_permission_content": "A helymeghatározást engedélyezni kell a jelenlegi helyednél lévő elemek megjelenítéséhez. Szeretnéd most engedélyezni?",
|
||||
"map_no_location_permission_title": "Helymeghatározás letiltva",
|
||||
@@ -2122,7 +2122,7 @@
|
||||
"server_privacy": "Szerver biztonság",
|
||||
"server_restarting_description": "Az oldal pillanatokon belül frissül.",
|
||||
"server_restarting_title": "A szerver újraindul",
|
||||
"server_stats": "Szerver statisztikák",
|
||||
"server_stats": "Szerver statisztika",
|
||||
"server_update_available": "Szerverfrissítés érhető el",
|
||||
"server_version": "Szerver verzió",
|
||||
"set": "Beállít",
|
||||
|
||||
@@ -1548,7 +1548,6 @@
|
||||
"map_location_picker_page_use_location": "Gunakan lokasi ini",
|
||||
"map_location_service_disabled_content": "Layanan lokasi perlu diaktifkan untuk menampilkan aset yang terletak di lokasi Anda saat ini. Ingin mengaktifkan layanan tersebut sekarang?",
|
||||
"map_location_service_disabled_title": "Layanan Lokasi nonaktif",
|
||||
"map_marker_for_images": "Penanda peta untuk gambar yang diambil di {city}, {country}",
|
||||
"map_marker_with_image": "Penanda peta dengan gambar",
|
||||
"map_no_location_permission_content": "Izin lokasi diperlukan untuk menampilkan aset yang terletak di lokasi Anda. Ingin mengizinkannya sekarang?",
|
||||
"map_no_location_permission_title": "Izin Lokasi ditolak",
|
||||
|
||||
+1
-2
@@ -1548,7 +1548,6 @@
|
||||
"map_location_picker_page_use_location": "Usa questa posizione",
|
||||
"map_location_service_disabled_content": "I servizi di geolocalizzazione devono essere attivati per poter visualizzare le risorse dalla tua posizione attuale. Vuoi attivarli adesso?",
|
||||
"map_location_service_disabled_title": "Servizio Localizzazione disattivato",
|
||||
"map_marker_for_images": "Indicatore mappa per le immagini scattate in {city}, {country}",
|
||||
"map_marker_with_image": "Segnaposto con immagine",
|
||||
"map_no_location_permission_content": "L'accesso alla posizione è necessario per visualizzare le risorse dalla tua posizione attuale. Vuoi consentirlo adesso?",
|
||||
"map_no_location_permission_title": "Autorizzazione Posizione negata",
|
||||
@@ -1603,7 +1602,7 @@
|
||||
},
|
||||
"media_type": "Tipo Media",
|
||||
"memories": "Ricordi",
|
||||
"memories_all_caught_up": "Tutto a posto",
|
||||
"memories_all_caught_up": "Niente di nuovo",
|
||||
"memories_check_back_tomorrow": "Torna domani per altri ricordi",
|
||||
"memories_setting_description": "Gestisci cosa vedi nei tuoi ricordi",
|
||||
"memories_start_over": "Ricomincia",
|
||||
|
||||
@@ -1532,7 +1532,6 @@
|
||||
"map_location_picker_page_use_location": "この位置情報を使う",
|
||||
"map_location_service_disabled_content": "現在地の項目を表示するには位置情報がオンである必要があります。有効化しますか?",
|
||||
"map_location_service_disabled_title": "位置情報がオフです",
|
||||
"map_marker_for_images": "{country} {city}で撮影された写真の地図マーカー",
|
||||
"map_marker_with_image": "画像の地図マーカー",
|
||||
"map_no_location_permission_content": "現在地の項目を表示するには位置情報へのアクセスが必要です。許可しますか?",
|
||||
"map_no_location_permission_title": "位置情報へのアクセスが拒否されました",
|
||||
|
||||
@@ -1101,7 +1101,6 @@
|
||||
"map": "ನಕ್ಷೆ",
|
||||
"map_cannot_get_user_location": "ಬಳಕೆದಾರರ ಸ್ಥಳವನ್ನು ಪಡೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ",
|
||||
"map_location_service_disabled_content": "ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಸ್ಥಳದಿಂದ ಸ್ವತ್ತುಗಳನ್ನು ಪ್ರದರ್ಶಿಸಲು ಸ್ಥಳ ಸೇವೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುವ ಅಗತ್ಯವಿದೆ. ನೀವು ಈಗ ಅದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ಬಯಸುವಿರಾ?",
|
||||
"map_marker_for_images": "{city}, {country} ದಲ್ಲಿ ತೆಗೆದ ಚಿತ್ರಗಳಿಗಾಗಿ ನಕ್ಷೆ ಮಾರ್ಕರ್",
|
||||
"map_marker_with_image": "ಚಿತ್ರದೊಂದಿಗೆ ನಕ್ಷೆ ಮಾರ್ಕರ್",
|
||||
"map_no_location_permission_content": "ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಸ್ಥಳದಿಂದ ಸ್ವತ್ತುಗಳನ್ನು ಪ್ರದರ್ಶಿಸಲು ಸ್ಥಳ ಅನುಮತಿ ಅಗತ್ಯವಿದೆ. ನೀವು ಈಗ ಅದನ್ನು ಅನುಮತಿಸಲು ಬಯಸುವಿರಾ?",
|
||||
"map_zoom_to_see_photos": "ಫೋಟೋಗಳನ್ನು ನೋಡಲು ಝೂಮ್ ಔಟ್ ಮಾಡಿ",
|
||||
|
||||
+9
-6
@@ -56,9 +56,9 @@
|
||||
"backup_database": "데이터베이스 덤프 생성",
|
||||
"backup_database_enable_description": "데이터베이스 덤프 활성화",
|
||||
"backup_keep_last_amount": "보관할 이전 덤프 수",
|
||||
"backup_onboarding_1_description": "개는 클라우드나 다른 물리적 위치에 보관합니다.",
|
||||
"backup_onboarding_2_description": "개는 서로 다른 로컬 장치에 보관하고,",
|
||||
"backup_onboarding_3_description": "개의 데이터 사본을 만듭니다.",
|
||||
"backup_onboarding_1_description": "클라우드 또는 다른 물리적 위치에 오프사이트 사본을 보관합니다.",
|
||||
"backup_onboarding_2_description": "여러 장치에 로컬 복사본이 있습니다. 여기에는 주요 파일과 해당 파일의 로컬 백업이 포함됩니다.",
|
||||
"backup_onboarding_3_description": "원본 파일을 포함한 데이터의 모든 사본 수입니다. 여기에는 오프사이트 사본 1개와 로컬 사본 2개가 포함됩니다.",
|
||||
"backup_onboarding_description": "데이터 보호를 위해 <backblaze-link>3-2-1 백업 전략</backblaze-link> 사용을 권장합니다. 백업에는 업로드한 사진 및 동영상뿐 아니라 Immich 데이터베이스도 포함되어야 합니다.",
|
||||
"backup_onboarding_footer": "Immich 백업에 대한 자세한 내용은 <link>공식 문서</link>를 참조하세요.",
|
||||
"backup_onboarding_parts_title": "3-2-1 백업이란:",
|
||||
@@ -181,7 +181,7 @@
|
||||
"machine_learning_ocr_min_recognition_score": "최소 인식 점수",
|
||||
"machine_learning_ocr_min_score_recognition_description": "인식할 텍스트의 최소 신뢰도 점수를 0~1 범위에서 설정합니다. 값이 작을수록 더 많은 텍스트를 인식하지만 잘못 인식될 가능성도 높아집니다.",
|
||||
"machine_learning_ocr_model": "OCR 모델",
|
||||
"machine_learning_ocr_model_description": "서버 모델은 모바일 모델보다 정확하지만, 처리 시간이 길어지고 메모리 사용량도 늘어납니다.",
|
||||
"machine_learning_ocr_model_description": "서버 모델은 모바일 모델보다 정확도가 높지만 처리 시간이 더 오래 걸리고 메모리 사용량도 더 많습니다.",
|
||||
"machine_learning_settings": "기계 학습 설정",
|
||||
"machine_learning_settings_description": "기계 학습 시 사용할 모델과 세부 설정을 관리합니다.",
|
||||
"machine_learning_smart_search": "스마트 검색",
|
||||
@@ -196,13 +196,16 @@
|
||||
"maintenance_integrity_check": "체크",
|
||||
"maintenance_integrity_check_all": "전체선택",
|
||||
"maintenance_integrity_checksum_mismatch": "체크섬 불일치",
|
||||
"maintenance_integrity_checksum_mismatch_description": "디스크의 체크섬이 Immich 데이터베이스에 저장된 체크섬과 일치하지 않는 파일입니다.",
|
||||
"maintenance_integrity_checksum_mismatch_job": "파일 무결성 검사",
|
||||
"maintenance_integrity_checksum_mismatch_refresh_job": "무결성 오류 보고서 새로고침",
|
||||
"maintenance_integrity_missing_file": "누락된 파일",
|
||||
"maintenance_integrity_missing_file_description": "Immich가 데이터베이스에서 추적했지만 파일 시스템에는 존재하지 않는 파일입니다.",
|
||||
"maintenance_integrity_missing_file_job": "누락된 파일 확인",
|
||||
"maintenance_integrity_missing_file_refresh_job": "누락된 파일 보고서 새로고침",
|
||||
"maintenance_integrity_report": "무결성 보고서",
|
||||
"maintenance_integrity_untracked_file": "추적되지 않은 파일",
|
||||
"maintenance_integrity_untracked_file_description": "Immich의 디렉터리에 있지만 Immich가 기록을 가지고 있지 않은 파일들.",
|
||||
"maintenance_integrity_untracked_file_job": "추적되지 않은 파일 확인",
|
||||
"maintenance_integrity_untracked_file_refresh_job": "추적되지 않은 파일 보고서 새로고침",
|
||||
"maintenance_restore_backup": "백업 복원",
|
||||
@@ -1545,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "이 위치 사용",
|
||||
"map_location_service_disabled_content": "현재 위치의 항목을 표시하려면 위치 서비스를 활성화해야 합니다. 지금 활성화하시겠습니까?",
|
||||
"map_location_service_disabled_title": "위치 서비스 비활성화됨",
|
||||
"map_marker_for_images": "{country}, {city}에서 촬영된 이미지의 지도 마커",
|
||||
"map_marker_for_image": "{city}, {country}에서 촬영한 이미지의 지도 마커입니다.",
|
||||
"map_marker_with_image": "이미지가 있는 지도 마커",
|
||||
"map_no_location_permission_content": "현재 위치의 항목을 표시하려면 위치 권한이 필요합니다. 지금 허용하시겠습니까?",
|
||||
"map_no_location_permission_title": "위치 권한 거부됨",
|
||||
@@ -1838,7 +1841,7 @@
|
||||
"play_motion_photo": "모션 포토 재생",
|
||||
"play_or_pause_video": "동영상 재생/일시 정지",
|
||||
"play_original_video": "원본 동영상 재생",
|
||||
"play_original_video_setting_description": "트랜스코딩된 영상보다 원본 영상을 우선 재생합니다. 원본이 호환되지 않는 형식인 경우 정상적으로 재생되지 않을 수 있습니다.",
|
||||
"play_original_video_setting_description": "변환된 영상보다는 원본 영상을 재생하는 것을 권장합니다. 원본 영상이 호환되지 않으면 제대로 재생되지 않을 수 있습니다.",
|
||||
"play_transcoded_video": "트랜스코딩 동영상 재생",
|
||||
"please_auth_to_access": "계속 진행하려면 인증하세요.",
|
||||
"plugin_method_filter_type": "필터",
|
||||
|
||||
+7
-2
@@ -189,18 +189,23 @@
|
||||
"machine_learning_smart_search_enabled": "Įjungti išmaniąją paiešką",
|
||||
"machine_learning_smart_search_enabled_description": "Jei išjungta, vaizdai nebus užkoduoti išmaniajai paieškai.",
|
||||
"machine_learning_url_description": "Mašininio mokymosi serverio URL. Jei pateikta daugiau nei vienas URL, serveriai bus bandomi eilės tvarka nuo pirmo iki paskutinio tol, kol bus rastas vienas veikiantis serveris.",
|
||||
"maintenance_backup_management": "Atsarginių kopijų tvarkymas",
|
||||
"maintenance_delete_backup": "Ištrinti atsarginę kopiją",
|
||||
"maintenance_delete_backup_description": "Šis failas bus negrįžtamai ištrintas.",
|
||||
"maintenance_delete_error": "Nepavyko ištrinti atsarginės kopijos.",
|
||||
"maintenance_integrity_check": "Tikrinti",
|
||||
"maintenance_integrity_check_all": "Tikrinti Visus",
|
||||
"maintenance_integrity_checksum_mismatch": "Checksum neatitikimas",
|
||||
"maintenance_integrity_checksum_mismatch_description": "Failai, kurių kontrolinė suma diske nesutampa su Immich duomenų bazėje įrašyta kontroline suma.",
|
||||
"maintenance_integrity_checksum_mismatch_job": "Tikrinti checksum neatitikimų",
|
||||
"maintenance_integrity_checksum_mismatch_refresh_job": "Atnaujinti checksum neatitikimo ataskaitas",
|
||||
"maintenance_integrity_missing_file": "Trūkstami failai",
|
||||
"maintenance_integrity_missing_file_description": "Failai, įtraukti į Immich duomenų bazę, tačiau neegzistuojantys failų sistemoje.",
|
||||
"maintenance_integrity_missing_file_job": "Tikrinti, ar nėra trūkstamų failų",
|
||||
"maintenance_integrity_missing_file_refresh_job": "Atnaujinti trūkstamų failų ataskaitas",
|
||||
"maintenance_integrity_report": "Vientisumo Ataskaita",
|
||||
"maintenance_integrity_untracked_file": "Nesekami Failai",
|
||||
"maintenance_integrity_untracked_file_description": "Failai Immich kataloguose, apie kuriuos Immich neturi jokių įrašų.",
|
||||
"maintenance_integrity_untracked_file_job": "Patikrinti, ar nėra nesekamų failų",
|
||||
"maintenance_integrity_untracked_file_refresh_job": "Atnaujinti nesekamų failų ataskaitas",
|
||||
"maintenance_restore_backup": "Atstatyti atsarginę kopiją",
|
||||
@@ -209,7 +214,7 @@
|
||||
"maintenance_restore_backup_unknown_version": "Nepavyko nustatyti atsarginės kopijos versijos.",
|
||||
"maintenance_restore_database_backup": "Atstatyti duomenų bazę",
|
||||
"maintenance_restore_database_backup_description": "Grąžinti į ankstesnę duomenų bazės būseną naudojant atsarginę kopiją",
|
||||
"maintenance_settings": "Aptarnavimas",
|
||||
"maintenance_settings": "Priežiūra",
|
||||
"maintenance_settings_description": "Perjungti „Immich“ į aptarnavimo režimą.",
|
||||
"maintenance_start": "Perjungti į aptarnavimo režimą",
|
||||
"maintenance_start_error": "Nepavyko paleisti aptarnavimo režimo.",
|
||||
@@ -1543,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Naudoti šią vietovę",
|
||||
"map_location_service_disabled_content": "Vietovės servisas turi būti įjungtas, kad rodytų elementus iš dabartinės vietovės. Įjungti vietovės servisą?",
|
||||
"map_location_service_disabled_title": "Vietovės servisas išjungtas",
|
||||
"map_marker_for_images": "Žemėlapio žymeklis nuotraukoms yra {city}, {country}",
|
||||
"map_marker_for_image": "Žemėlapio žymeklis nuotraukai, padarytai {city}, {country}",
|
||||
"map_marker_with_image": "Žemėlapio žymeklis su nuotrauka",
|
||||
"map_no_location_permission_content": "Reikalingas vietovės leidimas, kad rodytų elementus iš dabartinės vietovės. Ar norite suteikti leidimą?",
|
||||
"map_no_location_permission_title": "Vietovės leidimas atmestas",
|
||||
|
||||
@@ -1498,7 +1498,6 @@
|
||||
"map_location_picker_page_use_location": "Izvēlēties šo atrašanās vietu",
|
||||
"map_location_service_disabled_content": "Lai tiktu rādīti jūsu pašreizējās atrašanās vietas faili, ir jāaktivizē atrašanās vietas pakalpojums. Vai vēlaties to iespējot tagad?",
|
||||
"map_location_service_disabled_title": "Atrašanās vietas Pakalpojums atslēgts",
|
||||
"map_marker_for_images": "Kartes marķieris attēliem, kas uzņemti {city}, {country}",
|
||||
"map_marker_with_image": "Kartes marķieris ar attēlu",
|
||||
"map_no_location_permission_content": "Atrašanās vietas atļauja ir nepieciešama, lai parādītu jūsu pašreizējās atrašanās vietas aktīvus. Vai vēlaties to atļaut tagad?",
|
||||
"map_no_location_permission_title": "Atrašanās vietas Atļaujas liegtas",
|
||||
|
||||
@@ -1346,7 +1346,6 @@
|
||||
"map_location_picker_page_use_location": "ഈ സ്ഥലം ഉപയോഗിക്കുക",
|
||||
"map_location_service_disabled_content": "നിങ്ങളുടെ നിലവിലെ സ്ഥാനത്ത് നിന്നുള്ള അസറ്റുകൾ പ്രദർശിപ്പിക്കുന്നതിന് ലൊക്കേഷൻ സേവനം പ്രവർത്തനക്ഷമമാക്കേണ്ടതുണ്ട്. ഇപ്പോൾ പ്രവർത്തനക്ഷമമാക്കണോ?",
|
||||
"map_location_service_disabled_title": "ലൊക്കേഷൻ സേവനം പ്രവർത്തനരഹിതമാക്കി",
|
||||
"map_marker_for_images": "{city}, {country} എന്നിവിടങ്ങളിൽ എടുത്ത ചിത്രങ്ങൾക്കുള്ള മാപ്പ് മാർക്കർ",
|
||||
"map_marker_with_image": "ചിത്രത്തോടുകൂടിയ മാപ്പ് മാർക്കർ",
|
||||
"map_no_location_permission_content": "നിങ്ങളുടെ നിലവിലെ സ്ഥാനത്ത് നിന്നുള്ള അസറ്റുകൾ പ്രദർശിപ്പിക്കുന്നതിന് ലൊക്കേഷൻ അനുമതി ആവശ്യമാണ്. ഇപ്പോൾ അനുവദിക്കണോ?",
|
||||
"map_no_location_permission_title": "ലൊക്കേഷൻ അനുമതി നിഷേധിച്ചു",
|
||||
|
||||
@@ -1341,7 +1341,6 @@
|
||||
"map_location_picker_page_use_location": "हे लोकेशन वापरा",
|
||||
"map_location_service_disabled_content": "सध्याच्या लोकेशनवरील अॅसेट्स दाखवण्यासाठी लोकेशन सेवा सक्षम असणे आवश्यक आहे. तुम्हाला ती आत्ता सक्षम करायची आहे का?",
|
||||
"map_location_service_disabled_title": "लोकेशन सेवा बंद आहे",
|
||||
"map_marker_for_images": "{city}, {country} येथे घेतलेल्या प्रतिमांसाठी नकाशा मार्कर",
|
||||
"map_marker_with_image": "प्रतिमेसह नकाशा मार्कर",
|
||||
"map_no_location_permission_content": "सध्याच्या लोकेशनवरील अॅसेट्स दाखवण्यासाठी लोकेशन परवानगी आवश्यक आहे. तुम्हाला ती परवानगी आत्ता द्यायची आहे का?",
|
||||
"map_no_location_permission_title": "लोकेशन परवानगी नाकारली",
|
||||
|
||||
+3
-4
@@ -80,7 +80,7 @@
|
||||
"cron_expression_presets": "Forhåndsinnstillinger for Cron-uttrykk",
|
||||
"disable_login": "Deaktiver innlogging",
|
||||
"download_csv": "Last ned CSV",
|
||||
"duplicate_detection_job_description": "Kjør maskinlæring på filer for å oppdage lignende bilder. Krever bruk av Smart Søk",
|
||||
"duplicate_detection_job_description": "Kjør maskinlæring på filer for å oppdage lignende bilder. Krever bruk av smartsøk",
|
||||
"exclusion_pattern_description": "Ekskluderingsmønstre lar deg ignorere filer og mapper når du skanner biblioteket ditt. Dette er nyttig hvis du har mapper som inneholder filer du ikke vil importere, for eksempel RAW-filer.",
|
||||
"export_config_as_json_description": "Last ned nåværende systemkonfigurasjon som en JSON fil",
|
||||
"external_libraries_page_description": "Administrering for eksterne bibliotek",
|
||||
@@ -187,7 +187,7 @@
|
||||
"machine_learning_smart_search": "Smart søk",
|
||||
"machine_learning_smart_search_description": "Søk etter bilder semantisk ved å bruke CLIP-embeddings",
|
||||
"machine_learning_smart_search_enabled": "Aktiver smart søk",
|
||||
"machine_learning_smart_search_enabled_description": "Hvis deaktivert, vil bilder ikke bli enkodet for smart søk.",
|
||||
"machine_learning_smart_search_enabled_description": "Hvis deaktivert så blir ikke bilder kodet for smartsøk.",
|
||||
"machine_learning_url_description": "URL til maskinlærings-serveren. Hvis mer enn en URL er lagt inn, hver server vill bli forsøkt en om gangen frem til en svarer suksessfullt, i rekkefølge fra først til sist. Servere som ikke svarer vil midlertidig bli oversett frem til dem svarer igjen.",
|
||||
"maintenance_backup_management": "Administrasjon av sikkerhetskopier",
|
||||
"maintenance_delete_backup": "Slett sikkerhetskopi",
|
||||
@@ -205,7 +205,7 @@
|
||||
"maintenance_integrity_missing_file_refresh_job": "Oppdater rapporten for manglende filer",
|
||||
"maintenance_integrity_report": "Integritetsrapport",
|
||||
"maintenance_integrity_untracked_file": "Usporede filer",
|
||||
"maintenance_integrity_untracked_file_description": "Filer i Immich-mappene som ikke er registrert i databasen.",
|
||||
"maintenance_integrity_untracked_file_description": "Filer i Immichs mapper som Immich ikke har noen oversikt over.",
|
||||
"maintenance_integrity_untracked_file_job": "Sjekk etter usporede filer",
|
||||
"maintenance_integrity_untracked_file_refresh_job": "Oppdater rapporten for usporede filer",
|
||||
"maintenance_restore_backup": "Gjenopprett Sikkerhetskopi",
|
||||
@@ -1548,7 +1548,6 @@
|
||||
"map_location_picker_page_use_location": "Bruk dette stedet",
|
||||
"map_location_service_disabled_content": "Lokasjonstjeneste må være aktivert for å vise elementer fra din nåværende lokasjon. Vil du aktivere det nå?",
|
||||
"map_location_service_disabled_title": "Lokasjonstjeneste deaktivert",
|
||||
"map_marker_for_images": "Kart makeringer for bilder tatt i {city}, {country}",
|
||||
"map_marker_with_image": "Kartmarkør med bilde",
|
||||
"map_no_location_permission_content": "Lokasjonstilgang er påkrevet for å vise elementer fra din nåværende lokasjon. Vil du tillate det nå?",
|
||||
"map_no_location_permission_title": "Lokasjonstilgang avvist",
|
||||
|
||||
+17
-1
@@ -1 +1,17 @@
|
||||
{}
|
||||
{
|
||||
"about": "बारे",
|
||||
"account": "खाता",
|
||||
"account_settings": "खाता सेटिङ",
|
||||
"acknowledge": "स्वीकार",
|
||||
"action": "कार्य",
|
||||
"action_description": "छानियेको चिजमा सामुहिक कार्य",
|
||||
"add_a_description": "थप विवरण",
|
||||
"add_a_location": "स्थान थप्नुहोस्",
|
||||
"add_a_name": "नाम हाल्नुहोस्",
|
||||
"add_a_title": "शीर्षक हाल्नुहोस्",
|
||||
"add_action": "कार्य थप्नुहोस्",
|
||||
"add_action_description": "कार्य गर्नको लागि थप कार्यमा क्लिक गर्नुहोस्",
|
||||
"add_assets": "फोटोहरू थप्नुहोस्",
|
||||
"add_birthday": "जन्मदिन हाल्नुहोस",
|
||||
"add_endpoint": "अन्तिम बिन्दु थप्नुहोस्"
|
||||
}
|
||||
|
||||
+31
-31
@@ -609,7 +609,7 @@
|
||||
"asset_skipped": "Overgeslagen",
|
||||
"asset_skipped_in_trash": "In prullenbak",
|
||||
"asset_trashed": "Asset verwijderd",
|
||||
"asset_troubleshoot": "Asset probleemoplossing",
|
||||
"asset_troubleshoot": "Item probleemoplossing",
|
||||
"asset_uploaded": "Geüpload",
|
||||
"asset_uploading": "Uploaden…",
|
||||
"asset_viewer_settings_subtitle": "Beheer je instellingen voor galerijweergave",
|
||||
@@ -638,14 +638,14 @@
|
||||
"assets_were_part_of_album_count": "{count, plural, one {Item was} other {Items waren}} al onderdeel van het album",
|
||||
"assets_were_part_of_albums_count": "{count, plural, one {Item is} other {Items zijn}} al onderdeel van de albums",
|
||||
"authorized_devices": "Geautoriseerde apparaten",
|
||||
"automatic_endpoint_switching_subtitle": "Maak indien beschikbaar lokaal verbinding via het aangewezen wifi-netwerk en gebruik elders alternatieve verbindingen",
|
||||
"automatic_endpoint_switching_subtitle": "Maak indien beschikbaar lokaal verbinding via het aangewezen wifinetwerk en gebruik elders alternatieve verbindingen",
|
||||
"automatic_endpoint_switching_title": "Automatische serverwissel",
|
||||
"autoplay_slideshow": "Diavoorstelling automatisch afspelen",
|
||||
"back": "Terug",
|
||||
"back_close_deselect": "Terug, sluiten of deselecteren",
|
||||
"background_backup_running_error": "Back-up draait op de achtergrond, handmatige back-up kan niet worden gestart",
|
||||
"background_location_permission": "Achtergrond locatie toestemming",
|
||||
"background_location_permission_content": "Om van netwerk te wisselen terwijl de app op de achtergrond draait, heeft Immich *altijd* toegang tot de exacte locatie nodig om de naam van het WiFi-netwerk te kunnen lezen",
|
||||
"background_location_permission_content": "Om van netwerk te wisselen terwijl de app op de achtergrond draait, heeft Immich *altijd* toegang tot de exacte locatie nodig om de naam van het wifinetwerk te kunnen lezen",
|
||||
"background_options": "Achtergrond opties",
|
||||
"backup": "Back-up",
|
||||
"backup_album_selection_page_albums_device": "Albums op apparaat ({count})",
|
||||
@@ -680,7 +680,7 @@
|
||||
"backup_controller_page_background_is_on": "Automatische achtergrond back-up staat aan",
|
||||
"backup_controller_page_background_turn_off": "Achtergrondservice uitzetten",
|
||||
"backup_controller_page_background_turn_on": "Achtergrondservice aanzetten",
|
||||
"backup_controller_page_background_wifi": "Alleen op WiFi",
|
||||
"backup_controller_page_background_wifi": "Alleen op wifi",
|
||||
"backup_controller_page_backup": "Back-up",
|
||||
"backup_controller_page_backup_selected": "Geselecteerd: ",
|
||||
"backup_controller_page_backup_sub": "Geback-upte foto's en video's",
|
||||
@@ -785,7 +785,7 @@
|
||||
"charging_requirement_mobile_backup": "Achtergrond backup vereist dat het apparaat wordt opgeladen",
|
||||
"check_corrupt_asset_backup": "Controleer op corrupte back-ups van items",
|
||||
"check_corrupt_asset_backup_button": "Controle uitvoeren",
|
||||
"check_corrupt_asset_backup_description": "Voer deze controle alleen uit via WiFi en nadat alle items zijn geback-upt. De procedure kan een paar minuten duren.",
|
||||
"check_corrupt_asset_backup_description": "Voer deze controle alleen uit via wifi en nadat van alle items een back-up gemaakt is. De procedure kan een paar minuten duren.",
|
||||
"check_logs": "Controleer logboek",
|
||||
"checksum": "Controlegetal",
|
||||
"choose": "Kies",
|
||||
@@ -795,14 +795,14 @@
|
||||
"cleanup_confirm_prompt_title": "Van dit apparaat verwijderen?",
|
||||
"cleanup_deleted_assets": "{count} items verplaats naar prullenbak van apparaat",
|
||||
"cleanup_deleting": "Naar prullenbak verplaatsen...",
|
||||
"cleanup_found_assets": "Er zijn {count} backup bestanden gevonden",
|
||||
"cleanup_found_assets_with_size": "Er zijn {count} back-upbestanden gevonden ({size})",
|
||||
"cleanup_found_assets": "Er zijn {count} back-upbestanden gevonden",
|
||||
"cleanup_found_assets_with_size": "Er zijn {count} back-upbestanden gevonden ({size})",
|
||||
"cleanup_icloud_shared_albums_excluded": "Gedeelde albums van iCloud zijn uitgesloten van de scan",
|
||||
"cleanup_no_assets_found": "Er zijn geen bestanden gevonden die aan bovenstaande criteria voldoen. Free Up Space kan alleen bestanden verwijderen die op de server zijn geback-upt",
|
||||
"cleanup_preview_title": "Bestanden te verwijderen ({count})",
|
||||
"cleanup_step3_description": "Scan naar back-upbestanden die overeenkomen met uw datum en behoud uw instellingen.",
|
||||
"cleanup_step4_summary": "{count} bestanden (gemaakt vóór {date}) die van uw lokale apparaat moeten worden verwijderd. Foto's blijven toegankelijk via de Immich-app.",
|
||||
"cleanup_trash_hint": "Om de opslagruimte volledig vrij te maken, opent u de systeemgalerij-app en leegt u de prullenbak",
|
||||
"cleanup_trash_hint": "Open de galerij-app en leeg de prullenbak om de opslagruimte volledig vrij te maken",
|
||||
"clear": "Wissen",
|
||||
"clear_all": "Alles wissen",
|
||||
"clear_all_recent_searches": "Wis alle recente zoekopdrachten",
|
||||
@@ -814,7 +814,7 @@
|
||||
"client_cert_enter_password": "Voer wachtwoord in",
|
||||
"client_cert_import": "Importeren",
|
||||
"client_cert_import_success_msg": "Cliëntcertificaat is geïmporteerd",
|
||||
"client_cert_invalid_msg": "Ongeldig certificaatbestand of verkeerd wachtwoord",
|
||||
"client_cert_invalid_msg": "Ongeldig certificaatbestand of verkeerd wachtwoord",
|
||||
"client_cert_password_message": "Voer het wachtwoord voor dit certificaat in",
|
||||
"client_cert_password_title": "Certificaat wachtwoord",
|
||||
"client_cert_remove_msg": "Clientcertificaat is verwijderd",
|
||||
@@ -850,7 +850,7 @@
|
||||
"confirm_tag_face_unnamed": "Wil je dit gezicht taggen?",
|
||||
"connected_device": "Verbonden apparaat",
|
||||
"connected_to": "Verbonden met",
|
||||
"contain": "Bevat",
|
||||
"contain": "Passend",
|
||||
"context": "Context",
|
||||
"continue": "Doorgaan",
|
||||
"control_bottom_app_bar_add_tags": "Tags toevoegen",
|
||||
@@ -1066,7 +1066,7 @@
|
||||
"enabled": "Ingeschakeld",
|
||||
"end_date": "Einddatum",
|
||||
"enqueued": "In de wachtrij",
|
||||
"enter_wifi_name": "Voer de WiFi-naam in",
|
||||
"enter_wifi_name": "Voer de naam van het wifinetwerk in",
|
||||
"enter_your_pin_code": "Voer uw pincode in",
|
||||
"enter_your_pin_code_subtitle": "Voer uw pincode in om toegang te krijgen tot de vergrendelde map",
|
||||
"error": "Fout",
|
||||
@@ -1114,7 +1114,7 @@
|
||||
"failed_to_stack_assets": "Fout bij stapelen van items",
|
||||
"failed_to_tag_assets": "Fout bij taggen van items",
|
||||
"failed_to_unstack_assets": "Fout bij ontstapelen van items",
|
||||
"failed_to_update_notification_status": "Kon notificatiestatus niet updaten",
|
||||
"failed_to_update_notification_status": "Kan notificatiestatus niet updaten",
|
||||
"incorrect_email_or_password": "Onjuist e-mailadres of wachtwoord",
|
||||
"library_folder_already_exists": "Dit importpad bestaat al.",
|
||||
"page_not_found": "Pagina niet gevonden",
|
||||
@@ -1237,7 +1237,7 @@
|
||||
"external": "Extern",
|
||||
"external_libraries": "Externe bibliotheken",
|
||||
"external_network": "Extern netwerk",
|
||||
"external_network_sheet_info": "Als je niet verbonden bent met het opgegeven WiFi-netwerk, maakt de app verbinding met de server via de eerst bereikbare URL in de onderstaande lijst, van boven naar beneden",
|
||||
"external_network_sheet_info": "Als je niet verbonden bent met het opgegeven wifinetwerk, maakt de app verbinding met de server via de eerst bereikbare URL in de onderstaande lijst, van boven naar beneden",
|
||||
"f_number": "Diafragma",
|
||||
"face_unassigned": "Niet toegewezen",
|
||||
"failed": "Mislukt",
|
||||
@@ -1261,7 +1261,7 @@
|
||||
"filename": "Bestandsnaam",
|
||||
"filetype": "Bestandstype",
|
||||
"filter": "Filter",
|
||||
"filter_description": "Filtervoorwaarden voor doel items",
|
||||
"filter_description": "Filtervoorwaarden voor betreffende items",
|
||||
"filter_people": "Filteren op persoon",
|
||||
"filter_places": "Filteren op locatie",
|
||||
"filter_tags": "Filteren op label",
|
||||
@@ -1273,7 +1273,7 @@
|
||||
"folder": "Map",
|
||||
"folder_not_found": "Map niet gevonden",
|
||||
"folders": "Mappen",
|
||||
"folders_feature_description": "Bladeren door de mapweergave van de foto's en video's op het bestandssysteem",
|
||||
"folders_feature_description": "Bladeren door de mapweergave van de foto's en video's op het bestandssysteem",
|
||||
"forgot_pin_code_question": "Pincode vergeten?",
|
||||
"forward": "Vooruit",
|
||||
"free_up_space": "Maak opslag vrij",
|
||||
@@ -1287,7 +1287,7 @@
|
||||
"geolocation_instruction_location": "Klik op een item met gps-coördinaten om de locatie te gebruiken, of kies een locatie direct op de kaart",
|
||||
"get_help": "Hulp vragen",
|
||||
"get_people_error": "Fout bij ophalen mensen",
|
||||
"get_wifiname_error": "Kon de WiFi-naam niet ophalen. Zorg ervoor dat je de benodigde machtigingen hebt verleend en verbonden bent met een WiFi-netwerk",
|
||||
"get_wifiname_error": "Kon de naam van het netwerk niet ophalen. Zorg ervoor dat je de benodigde machtigingen hebt verleend en verbonden bent met een wifinetwerk",
|
||||
"getting_started": "Aan de slag",
|
||||
"go_back": "Ga terug",
|
||||
"go_to_folder": "Ga naar map",
|
||||
@@ -1387,9 +1387,9 @@
|
||||
"invite_to_album": "Uitnodigen voor album",
|
||||
"ios_debug_info_fetch_ran_at": "Ophalen gelukt op {dateTime}",
|
||||
"ios_debug_info_last_sync_at": "Laatst gesynchroniseerd {dateTime}",
|
||||
"ios_debug_info_no_processes_queued": "Geen achtergrondprocessen in de wachtrij",
|
||||
"ios_debug_info_no_processes_queued": "Geen achtergrondprocessen in de wachtrij",
|
||||
"ios_debug_info_no_sync_yet": "Er is nog geen achtergrondsynchronisatie uitgevoerd",
|
||||
"ios_debug_info_processes_queued": "{count, plural, one {{count} achtergrondproces in de wachtrij} other {{count} achtergrondprocessen in de wachtrij}}",
|
||||
"ios_debug_info_processes_queued": "{count, plural, one {{count} achtergrondproces} other {{count} achtergrondprocessen}} in de wachtrij",
|
||||
"ios_debug_info_processing_ran_at": "Verwerking uitgevoerd op {dateTime}",
|
||||
"iso": "ISO",
|
||||
"items_count": "{count, plural, one {# item} other {# items}}",
|
||||
@@ -1456,10 +1456,10 @@
|
||||
"local_id": "Lokaal ID",
|
||||
"local_media_summary": "Lokale media samenvatting",
|
||||
"local_network": "Lokaal netwerk",
|
||||
"local_network_sheet_info": "De app maakt verbinding met de server via deze URL wanneer het opgegeven WiFi-netwerk wordt gebruikt",
|
||||
"local_network_sheet_info": "De app maakt verbinding met de server via deze URL wanneer het opgegeven wifinetwerk wordt gebruikt",
|
||||
"location": "Locatie",
|
||||
"location_permission": "Locatietoestemming",
|
||||
"location_permission_content": "Om de functie voor automatische serverwissel te gebruiken, heeft Immich toegang tot de exacte locatie nodig om de naam van het huidige WiFi-netwerk te kunnen bepalen",
|
||||
"location_permission_content": "Om de functie voor automatische serverwissel te gebruiken, heeft Immich toegang tot de exacte locatie nodig om de naam van het huidige wifinetwerk te kunnen bepalen",
|
||||
"location_picker_choose_on_map": "Kies op kaart",
|
||||
"location_picker_latitude_error": "Voer een geldige breedtegraad in",
|
||||
"location_picker_latitude_hint": "Voer hier je breedtegraad in",
|
||||
@@ -1502,8 +1502,8 @@
|
||||
"longitude": "Lengtegraad",
|
||||
"look": "Uiterlijk",
|
||||
"loop_videos": "Video's herhalen",
|
||||
"loop_videos_description": "Inschakelen om video's automatisch te herhalen in de detailweergave.",
|
||||
"main_branch_warning": "Je gebruikt een ontwikkelingsversie. We raden je ten zeerste aan een releaseversie te gebruiken!",
|
||||
"loop_videos_description": "Inschakelen om video's automatisch te herhalen in de detailweergave.",
|
||||
"main_branch_warning": "Je gebruikt een ontwikkelingsversie. We raden je ten zeerste aan een releaseversie te gebruiken!",
|
||||
"main_menu": "Hoofdmenu",
|
||||
"maintenance_action_restore": "Database wordt hersteld",
|
||||
"maintenance_description": "Immich is in de <link>onderhoudsmodus</link> gezet.",
|
||||
@@ -1512,7 +1512,7 @@
|
||||
"maintenance_logged_in_as": "Momenteel ingelogd als {user}",
|
||||
"maintenance_restore_from_backup": "Herstellen vanaf backup",
|
||||
"maintenance_restore_library": "Bibliotheek herstellen",
|
||||
"maintenance_restore_library_confirm": "Als dit er goed uit ziet ga dan verder om de backup terug te zetten!",
|
||||
"maintenance_restore_library_confirm": "Als dit er goed uit ziet, ga dan verder om de back-up terug te zetten!",
|
||||
"maintenance_restore_library_description": "Database wordt hersteld",
|
||||
"maintenance_restore_library_folder_has_files": "{folder} heeft {count} map(pen)",
|
||||
"maintenance_restore_library_folder_no_files": "{folder} mist bestanden!",
|
||||
@@ -1548,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Gebruik deze locatie",
|
||||
"map_location_service_disabled_content": "Locatie service moet ingeschakeld zijn om items van je huidige locatie weer te geven. Wil je het nu inschakelen?",
|
||||
"map_location_service_disabled_title": "Locatie service uitgeschakeld",
|
||||
"map_marker_for_images": "Kaartmarkering voor afbeeldingen gemaakt in {city}, {country}",
|
||||
"map_marker_for_image": "Kaartmarkering voor afbeelding gemaakt in {city}, {country}",
|
||||
"map_marker_with_image": "Kaartmarkering met afbeelding",
|
||||
"map_no_location_permission_content": "Locatietoestemming is nodig om items van je huidige locatie weer te geven. Wil je dit nu toestaan?",
|
||||
"map_no_location_permission_title": "Locatietoestemming geweigerd",
|
||||
@@ -1983,7 +1983,7 @@
|
||||
"reset_sqlite": "SQLite database resetten",
|
||||
"reset_sqlite_clear_app_data": "Wis gegevens",
|
||||
"reset_sqlite_confirmation": "Weet je zeker dat je de app-gegevens wilt wissen? Hiermee worden alle instellingen verwijderd en word je uitgelogd.",
|
||||
"reset_sqlite_confirmation_note": "Let op: Je moet de app opnieuw opstarten nadat je deze hebt gewist.",
|
||||
"reset_sqlite_confirmation_note": "Let op: je moet de app opnieuw opstarten nadat je deze hebt gewist.",
|
||||
"reset_sqlite_done": "App data is gewist. Start Immich opnieuw op en log opnieuw in.",
|
||||
"reset_sqlite_success": "De SQLite database is succesvol gereset",
|
||||
"reset_to_default": "Resetten naar standaard",
|
||||
@@ -1996,7 +1996,7 @@
|
||||
"restore_user": "Gebruiker herstellen",
|
||||
"restored_asset": "Item hersteld",
|
||||
"resume": "Hervatten",
|
||||
"resume_paused_jobs": "Hervat {count, plural, one {# gepauseerde taak} other {# gepauseerde taken}}",
|
||||
"resume_paused_jobs": "{count, plural, one {# gepauzeerde taak} other {# gepauzeerde taken}} hervatten",
|
||||
"retry_upload": "Opnieuw uploaden",
|
||||
"review_duplicates": "Controleer duplicaten",
|
||||
"review_large_files": "Grote bestanden beoordelen",
|
||||
@@ -2470,8 +2470,8 @@
|
||||
"use_template": "Gebruik template",
|
||||
"user": "Gebruiker",
|
||||
"user_has_been_deleted": "Deze gebruiker is verwijderd.",
|
||||
"user_id": "Gebruikers ID",
|
||||
"user_liked": "{user} heeft {type, select, photo {deze foto} video {deze video} asset {} other {dit item}} geliket",
|
||||
"user_id": "Gebruikers-ID",
|
||||
"user_liked": "{user} vindt {type, select, photo {deze foto} video {deze video} asset {} other {dit item}} leuk",
|
||||
"user_pin_code_settings": "Pincode",
|
||||
"user_pin_code_settings_description": "Beheer je pincode",
|
||||
"user_privacy": "Gebruikersprivacy",
|
||||
@@ -2479,7 +2479,7 @@
|
||||
"user_purchase_settings_description": "Beheer je aankoop",
|
||||
"user_role_set": "{user} instellen als {role}",
|
||||
"user_usage_detail": "Gedetailleerd gebruik van gebruikers",
|
||||
"user_usage_stats": "Statistieken van accountgebruik",
|
||||
"user_usage_stats": "Accountstatistieken",
|
||||
"user_usage_stats_description": "Bekijk statistieken van accountgebruik",
|
||||
"username": "Gebruikersnaam",
|
||||
"users": "Gebruikers",
|
||||
@@ -2532,7 +2532,7 @@
|
||||
"welcome_to_immich": "Welkom bij Immich",
|
||||
"when": "Wanneer",
|
||||
"width": "Breedte",
|
||||
"wifi_name": "WiFi-naam",
|
||||
"wifi_name": "Wifinetwerk",
|
||||
"workflow": "Werkstroom",
|
||||
"workflow_delete_prompt": "Weet je zeker dat je deze werkstroom wilt verwijderen?",
|
||||
"workflow_deleted": "Werkstroom verwijderd",
|
||||
@@ -2554,7 +2554,7 @@
|
||||
"years_ago": "{years, plural, one {Een jaar} other {# jaar}} geleden",
|
||||
"yes": "Ja",
|
||||
"you_dont_have_any_shared_links": "Je hebt geen gedeelde links",
|
||||
"your_wifi_name": "Je WiFi-naam",
|
||||
"your_wifi_name": "Je wifinetwerk",
|
||||
"zero_to_clear_rating": "druk op 0 om de sterwaardering te verwijderen",
|
||||
"zoom_image": "Inzoomen",
|
||||
"zoom_to_bounds": "Zoom naar randen"
|
||||
|
||||
+3
-3
@@ -1548,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Użyj tej lokalizacji",
|
||||
"map_location_service_disabled_content": "Aby wyświetlić zasoby z Twojej bieżącej lokalizacji, należy włączyć usługę lokalizacyjną. Czy chcesz to teraz włączyć?",
|
||||
"map_location_service_disabled_title": "Usługa lokalizacji wyłączona",
|
||||
"map_marker_for_images": "Wskaźnik mapy dla zdjęć zrobionych w {city}, {country}",
|
||||
"map_marker_for_image": "Znacznik na mapie dla zdjęcia wykonanego w {city}, {country}",
|
||||
"map_marker_with_image": "Znacznik na mapie ze zdjęciem",
|
||||
"map_no_location_permission_content": "Aby wyświetlić zasoby z Twojej bieżącej lokalizacji, potrzebne jest pozwolenie na lokalizację. Czy chcesz teraz na to pozwolić?",
|
||||
"map_no_location_permission_title": "Odmowa dostępu do lokalizacji",
|
||||
@@ -2031,7 +2031,7 @@
|
||||
"search_by_full_path": "Wyszukaj według pełnej ścieżki lub folderu",
|
||||
"search_by_full_path_example": "/John/Projekty/Drukowanie_3D/2026-07-01 – możesz wyszukiwać hasła takie jak Projekty, 3D, Drukowanie, 2026 itp.",
|
||||
"search_by_ocr": "Wyszukaj przy użyciu OCR",
|
||||
"search_by_ocr_example": "Latte",
|
||||
"search_by_ocr_example": "Kawa, trampolina",
|
||||
"search_camera_lens_model": "Wyszukaj model obiektywu...",
|
||||
"search_camera_make": "Wyszukaj markę aparatu...",
|
||||
"search_camera_model": "Wyszukaj model aparatu...",
|
||||
@@ -2185,7 +2185,7 @@
|
||||
"shared_by_you": "Udostępnione przez ciebie",
|
||||
"shared_from_partner": "Zdjęcia od {partner}",
|
||||
"shared_intent_upload_button_progress_text": "{current} / {total} Przesłano",
|
||||
"shared_link_app_bar_title": "Udostępnione",
|
||||
"shared_link_app_bar_title": "Udostępnione linki",
|
||||
"shared_link_clipboard_copied_massage": "Skopiowane do schowka",
|
||||
"shared_link_clipboard_text": "Link: {link}\nHasło: {password}",
|
||||
"shared_link_create_error": "Błąd podczas tworzenia linka do udostępnienia",
|
||||
|
||||
@@ -1548,7 +1548,6 @@
|
||||
"map_location_picker_page_use_location": "Utilizar esta localização",
|
||||
"map_location_service_disabled_content": "Serviço de localização precisa de estar ativado para mostrar recursos da localização atual. Deseja ativar agora?",
|
||||
"map_location_service_disabled_title": "Serviço de localização desativado",
|
||||
"map_marker_for_images": "Marcador no mapa para fotos tiradas em {city}, {country}",
|
||||
"map_marker_with_image": "Marcador de mapa com imagem",
|
||||
"map_no_location_permission_content": "A permissão da localização é necessária para mostrar recursos da localização atual. Deseja conceder a permissão agora?",
|
||||
"map_no_location_permission_title": "Permissão de localização foi negada",
|
||||
|
||||
+6
-1
@@ -189,18 +189,23 @@
|
||||
"machine_learning_smart_search_enabled": "Habilitar a Pesquisa Inteligente",
|
||||
"machine_learning_smart_search_enabled_description": "Se desativado, as imagens não serão codificadas para pesquisa inteligente.",
|
||||
"machine_learning_url_description": "A URL do servidor de aprendizado de máquina. Se mais de uma URL for fornecida, elas serão tentadas, uma de cada vez e na ordem indicada, até que uma responda com sucesso. Servidores que não responderem serão ignorados temporariamente até voltarem a estar conectados.",
|
||||
"maintenance_backup_management": "Gerenciamento de backup",
|
||||
"maintenance_delete_backup": "Excluir Backup",
|
||||
"maintenance_delete_backup_description": "Este arquivo será excluído de forma irreversível.",
|
||||
"maintenance_delete_error": "Falha ao excluir o backup.",
|
||||
"maintenance_integrity_check": "Verificar",
|
||||
"maintenance_integrity_check_all": "Verificar tudo",
|
||||
"maintenance_integrity_checksum_mismatch": "Checksum não corresponde",
|
||||
"maintenance_integrity_checksum_mismatch_description": "Arquivos cujo o checksum atual não corresponde ao checksum que Immich armazenou no banco de dados.",
|
||||
"maintenance_integrity_checksum_mismatch_job": "Verificar se há erros de checksum",
|
||||
"maintenance_integrity_checksum_mismatch_refresh_job": "Atualizar # de checksum sem correspondência",
|
||||
"maintenance_integrity_missing_file": "Arquivos não encontrados",
|
||||
"maintenance_integrity_missing_file_description": "Arquivos que Immich rastreou em seu banco de dados, mas que não existem no sistema de arquivos.",
|
||||
"maintenance_integrity_missing_file_job": "Verificar se há arquivos não encontrados",
|
||||
"maintenance_integrity_missing_file_refresh_job": "Atualizar # de arquivos não encontrados",
|
||||
"maintenance_integrity_report": "Relatório de integridade",
|
||||
"maintenance_integrity_untracked_file": "Arquivos não rastreados",
|
||||
"maintenance_integrity_untracked_file_description": "Arquivos não rastreados dentro dos diretórios do Immich.",
|
||||
"maintenance_integrity_untracked_file_job": "Verificar se há arquivos não rastreados",
|
||||
"maintenance_integrity_untracked_file_refresh_job": "Atualizar # de arquivos não rastreados",
|
||||
"maintenance_restore_backup": "Restaurar Backup",
|
||||
@@ -1543,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Use esta localização",
|
||||
"map_location_service_disabled_content": "O serviço de localização precisa estar ativado para exibir os arquivos da sua localização atual. Deseja ativar agora?",
|
||||
"map_location_service_disabled_title": "Serviço de localização desativado",
|
||||
"map_marker_for_images": "Marcador de mapa para imagens tiradas em {city}, {country}",
|
||||
"map_marker_for_image": "Marcador do mapa para a foto tirada em {city}, {country}",
|
||||
"map_marker_with_image": "Marcador de mapa com imagem",
|
||||
"map_no_location_permission_content": "É necessária a permissão de localização para exibir os arquivos da sua localização atual. Deseja conceder a permissão agora?",
|
||||
"map_no_location_permission_title": "Permissão de localização foi negada",
|
||||
|
||||
@@ -1523,7 +1523,6 @@
|
||||
"map_location_picker_page_use_location": "Folosește această locație",
|
||||
"map_location_service_disabled_content": "Serviciul de localizare trebuie să fie activat pentru a afișa resursele din locația actuală. Dorești să o activezi acum?",
|
||||
"map_location_service_disabled_title": "Serviciul de localizare este dezactivat",
|
||||
"map_marker_for_images": "Marcator de hartă pentru imaginile realizate în {city}, {country}",
|
||||
"map_marker_with_image": "Marcator de hartă cu imagine",
|
||||
"map_no_location_permission_content": "Permisiunea de localizare este necesară pentru a afișa resursele din locația actuală. Dorești să o activezi acum?",
|
||||
"map_no_location_permission_title": "Permisiunea de localizare este dezactivată",
|
||||
|
||||
+2
-2
@@ -1548,8 +1548,8 @@
|
||||
"map_location_picker_page_use_location": "Это местоположение",
|
||||
"map_location_service_disabled_content": "Для отображения объектов в текущем месте необходимо включить службу определения местоположения. Включить?",
|
||||
"map_location_service_disabled_title": "Служба определения местоположения отключена",
|
||||
"map_marker_for_images": "Маркер на карте для изображений, сделанных в {city}, {country}",
|
||||
"map_marker_with_image": "Маркер на карте с изображением",
|
||||
"map_marker_for_image": "Маркер на карте для объекта, сделанного в {city}, {country}",
|
||||
"map_marker_with_image": "Маркер на карте для объекта",
|
||||
"map_no_location_permission_content": "Для отображения объектов в текущем месте необходимо разрешение на определение местоположения. Предоставить разрешение?",
|
||||
"map_no_location_permission_title": "Доступ к местоположению отклонен",
|
||||
"map_settings": "Настройки карты",
|
||||
|
||||
@@ -1548,7 +1548,6 @@
|
||||
"map_location_picker_page_use_location": "Použiť túto polohu",
|
||||
"map_location_service_disabled_content": "Služba určovania polohy musí byť povolená, aby sa zobrazovali položky z vašej aktuálnej polohy. Chcete ju teraz zapnúť?",
|
||||
"map_location_service_disabled_title": "Služba určovania polohy vypnutá",
|
||||
"map_marker_for_images": "Značka na mape pre obrázky odfotené v {city}, {country}",
|
||||
"map_marker_with_image": "Mapová značka pre obrázok",
|
||||
"map_no_location_permission_content": "Na zobrazenie položiek z vašej aktuálnej polohy je potrebné povolenie na polohu. Chcete to teraz povoliť?",
|
||||
"map_no_location_permission_title": "Povolenie polohy zamietnuté",
|
||||
|
||||
+1
-1
@@ -1548,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Uporabi to lokacijo",
|
||||
"map_location_service_disabled_content": "Lokacijska storitev mora biti omogočena za prikaz sredstev z vaše trenutne lokacije. Ali jo želite takoj omogočiti?",
|
||||
"map_location_service_disabled_title": "Lokacijska storitev onemogočena",
|
||||
"map_marker_for_images": "Oznaka zemljevida za slike, posnete v {city}, {country}",
|
||||
"map_marker_for_image": "Oznaka na zemljevidu za sliko, posneto v {city}, {country}",
|
||||
"map_marker_with_image": "Oznaka zemljevida s sliko",
|
||||
"map_no_location_permission_content": "Za prikaz sredstev z vaše trenutne lokacije je potrebno dovoljenje za lokacijo. Ali to želite takoj dovoliti?",
|
||||
"map_no_location_permission_title": "Dovoljenje za lokacijo je zavrnjeno",
|
||||
|
||||
@@ -1184,7 +1184,6 @@
|
||||
"map_location_picker_page_use_location": "Користите ову локацију",
|
||||
"map_location_service_disabled_content": "Услуга локације мора бити омогућена да би се приказивала средства са ваше тренутне локације. Да ли желите да је сада омогућите?",
|
||||
"map_location_service_disabled_title": "Услуга локације је онемогућена",
|
||||
"map_marker_for_images": "Означивач на мапи за слике снимљене у {city}, {country}",
|
||||
"map_marker_with_image": "Маркер на мапи са сликом",
|
||||
"map_no_location_permission_content": "Потребна је дозвола за локацију да би се приказали ресурси са ваше тренутне локације. Да ли желите да је сада дозволите?",
|
||||
"map_no_location_permission_title": "Дозвола за локацију је одбијена",
|
||||
|
||||
@@ -1370,7 +1370,6 @@
|
||||
"map_location_picker_page_use_location": "Koristite ovu lokaciju",
|
||||
"map_location_service_disabled_content": "Usluga lokacije mora biti omogućena da bi se prikazivala sredstva sa vaše trenutne lokacije. Da li želite da je sada omogućite?",
|
||||
"map_location_service_disabled_title": "Usluga lokacije je onemogućena",
|
||||
"map_marker_for_images": "Označivač na mapi za slike snimljene u {city}, {country}",
|
||||
"map_marker_with_image": "Marker na mapi sa slikom",
|
||||
"map_no_location_permission_content": "Potrebna je dozvola za lokaciju da bi se prikazali resursi sa vaše trenutne lokacije. Da li želite da je sada dozvolite?",
|
||||
"map_no_location_permission_title": "Dozvola za lokaciju je odbijena",
|
||||
|
||||
+1
-1
@@ -1548,7 +1548,7 @@
|
||||
"map_location_picker_page_use_location": "Använd den här platsen",
|
||||
"map_location_service_disabled_content": "Platstjänst måste vara aktiverad för att visa objekt från din nuvarande plats. Vill du aktivera den nu?",
|
||||
"map_location_service_disabled_title": "Platstjänst inaktiverad",
|
||||
"map_marker_for_images": "Kartmarkering för bilder tagna i {city}, {country}",
|
||||
"map_marker_for_image": "Kartmarkör för bild tagen i {city}, {country}",
|
||||
"map_marker_with_image": "Kartmarkör med bild",
|
||||
"map_no_location_permission_content": "Platsrättighet är nödvändigt för att kunna visa objekt från din nuvarande plats. Vill du tillåta det nu?",
|
||||
"map_no_location_permission_title": "Platsrättighet nekad",
|
||||
|
||||
@@ -1485,7 +1485,6 @@
|
||||
"map_location_picker_page_use_location": "இந்த இருப்பிடத்தைப் பயன்படுத்தவும்",
|
||||
"map_location_service_disabled_content": "உங்கள் தற்போதைய இருப்பிடத்திலிருந்து சொத்துக்களைக் காட்ட இருப்பிட பணி இயக்கப்பட வேண்டும். இப்போது அதை இயக்க விரும்புகிறீர்களா?",
|
||||
"map_location_service_disabled_title": "இருப்பிட பணி முடக்கப்பட்டது",
|
||||
"map_marker_for_images": "{city}, {country}",
|
||||
"map_marker_with_image": "படத்துடன் வரைபட மார்க்கர்",
|
||||
"map_no_location_permission_content": "உங்கள் தற்போதைய இருப்பிடத்திலிருந்து சொத்துக்களைக் காட்ட இருப்பிட இசைவு தேவை. இப்போது அதை அனுமதிக்க விரும்புகிறீர்களா?",
|
||||
"map_no_location_permission_title": "இருப்பிட இசைவு மறுக்கப்பட்டது",
|
||||
|
||||
@@ -837,7 +837,6 @@
|
||||
"manage_your_devices": "మీ లాగిన్ అయిన పరికరాలను నిర్వహించండి",
|
||||
"manage_your_oauth_connection": "మీ OAuth కనెక్షన్ని నిర్వహించండి",
|
||||
"map": "మ్యాప్",
|
||||
"map_marker_for_images": "{city}, {country} లో తీసిన చిత్రాల కోసం మ్యాప్ మార్కర్",
|
||||
"map_marker_with_image": "చిత్రంతో మ్యాప్ మార్కర్",
|
||||
"map_settings": "మ్యాప్ సెట్టింగ్లు",
|
||||
"matches": "మ్యాచ్లు",
|
||||
|
||||
@@ -1468,7 +1468,6 @@
|
||||
"map_location_picker_page_use_location": "ใช้ตำแหน่งนี้",
|
||||
"map_location_service_disabled_content": "ต้องเปิดตำแหน่งเพื่อแสดงทรัพยากรจากตำแหน่งปัจจุบัน เปิดตอนนี้?",
|
||||
"map_location_service_disabled_title": "บริการตำแหน่งถูกปิด",
|
||||
"map_marker_for_images": "หมุดแผนที่สำหรับรูปถ่ายที่ {city}, {country}",
|
||||
"map_marker_with_image": "หมุดแผนที่กับรูปถ่าย",
|
||||
"map_no_location_permission_content": "จำเป็นต้องมีสิทธิ์เข้าถึงตำแหน่งเพื่อแสดงทรัพยากรจากตำแหน่งปัจจุบัน อนุญาตตอนนี้?",
|
||||
"map_no_location_permission_title": "สิทธิ์เข้าถึงตำแหน่งถูกปฏิเสธ",
|
||||
|
||||
+61
-3
@@ -79,6 +79,7 @@
|
||||
"cron_expression_description": "Cron formatını kullanarak tarama aralığını belirle. Daha fazla bilgi için örneğin <link>Crontab Guru</link>’ya bakın",
|
||||
"cron_expression_presets": "Cron ifadesi ön ayarları",
|
||||
"disable_login": "Girişi devre dışı bırak",
|
||||
"download_csv": "CSV’yi indir",
|
||||
"duplicate_detection_job_description": "Benzer fotoğrafları bulmak için makine öğrenmesini çalıştır. Bu işlem Akıllı Arama'ya bağlıdır",
|
||||
"exclusion_pattern_description": "Kütüphaneyi tararken dosya ve klasörleri görmezden gelmek için dışlama desenlerini kullanabilirsiniz. RAW dosyaları gibi bazı dosya ve klasörleri içe aktarmak istemediğinizde bu seçeneği kullanabilirsiniz.",
|
||||
"export_config_as_json_description": "Geçerli sistem yapılandırmasını JSON dosyası olarak indir",
|
||||
@@ -188,9 +189,23 @@
|
||||
"machine_learning_smart_search_enabled": "Akıllı aramayı etkinleştir",
|
||||
"machine_learning_smart_search_enabled_description": "Eğer devre dışı bırakılırsa fotoğraflar akıllı arama için işlenmeyecek.",
|
||||
"machine_learning_url_description": "Makine öğrenimi sunucusunun URL’si. Birden fazla URL sağlanırsa, her sunucu sırayla tek tek denenir ve biri başarılı yanıt verene kadar devam edilir. Yanıt vermeyen sunucular, çevrimiçi duruma gelene kadar geçici olarak yok sayılır.",
|
||||
"maintenance_backup_management": "Yedekleme sistemi",
|
||||
"maintenance_delete_backup": "Yedeği Sil",
|
||||
"maintenance_delete_backup_description": "Bu dosya geri alınamaz şekilde silinecektir.",
|
||||
"maintenance_delete_error": "Yedek silinemedi.",
|
||||
"maintenance_integrity_check": "Kontrol et",
|
||||
"maintenance_integrity_check_all": "Hepsini kontrol et",
|
||||
"maintenance_integrity_checksum_mismatch_description": "Disk üzerindeki sağlama toplamı, Immich'in veritabanında sakladığı sağlama toplamıyla uyuşmayan dosyalar.",
|
||||
"maintenance_integrity_checksum_mismatch_job": "Sağlama toplamı uyuşmazlıklarını kontrol et",
|
||||
"maintenance_integrity_missing_file": "Eksik Dosyalar",
|
||||
"maintenance_integrity_missing_file_description": "Immich'in veritabanında izlediği ancak dosya sisteminde bulunmayan dosyalar.",
|
||||
"maintenance_integrity_missing_file_job": "Eksik dosyaları kontrol et",
|
||||
"maintenance_integrity_missing_file_refresh_job": "Eksik dosya raporlarını yenile",
|
||||
"maintenance_integrity_report": "Entegrasyon Raporu",
|
||||
"maintenance_integrity_untracked_file": "İzlenmeyen Dosyalar",
|
||||
"maintenance_integrity_untracked_file_description": "Immich'in dizinlerinde bulunan ancak Immich'in hiçbir kaydının bulunmadığı dosyalar.",
|
||||
"maintenance_integrity_untracked_file_job": "İzlenmeyen dosyaları kontrol et",
|
||||
"maintenance_integrity_untracked_file_refresh_job": "İzlenmeyen dosya raporlarını yenile",
|
||||
"maintenance_restore_backup": "Yedeği Geri Yükle",
|
||||
"maintenance_restore_backup_description": "Immich tamamen silinecek ve seçilen yedekten geri yüklenecektir. İşleme devam etmeden önce bir yedek oluşturulacaktır.",
|
||||
"maintenance_restore_backup_different_version": "Bu yedek, Immich’in farklı bir sürümüyle oluşturulmuş!",
|
||||
@@ -305,6 +320,7 @@
|
||||
"refreshing_all_libraries": "Tüm kütüphaneler yenileniyor",
|
||||
"registration": "Yönetici Kaydı",
|
||||
"registration_description": "Sistemdeki ilk kullanıcı olduğunuz için hesabınız Yönetici olarak ayarlandı. Yeni oluşturulan üyeliklerin, ve yönetici görevlerinin sorumlusu olarak atandınız.",
|
||||
"release_channel_release_candidate": "Yayın adayı",
|
||||
"release_channel_stable": "Stabil",
|
||||
"remove_failed_jobs": "Başarısız işleri kaldır",
|
||||
"require_password_change_on_login": "Kullanıcının ilk girişinde şifre değiştirmesini zorunlu kıl",
|
||||
@@ -400,6 +416,9 @@
|
||||
"transcoding_preferred_hardware_device_description": "Sadece VAAPI ve QSV için uygulanır. Donanım kod çevrimi için DRI Node ayarlar.",
|
||||
"transcoding_preset_preset": "Ön ayar (-ön)",
|
||||
"transcoding_preset_preset_description": "Sıkıştırma hızı. Daha yavaş olan ayarlar belirli bitrate ayarları için daha küçük ve daha kaliteli dosya üretir. VP9 ayarı 'daha hızlı' ayarının üstündeki ayarları görmezden gelir.",
|
||||
"transcoding_realtime": "Gerçek Zamanlı Kod Dönüştürme [DENEYSEL]",
|
||||
"transcoding_realtime_enabled": "Gerçek zamanlı kod dönüştürmeyi etkinleştirin",
|
||||
"transcoding_realtime_enabled_description": "Devre dışı bırakılırsa, sunucu yeni gerçek zamanlı kod dönüştürme oturumları başlatmayı reddedecektir.",
|
||||
"transcoding_reference_frames": "Referans kareler",
|
||||
"transcoding_reference_frames_description": "Belirli bir kareyi sıkıştırırken referans alınacak kare sayısı. Daha yüksek değerler sıkıştırma verimliliğini artırır, ancak kodlamayı yavaşlatır. 0 bu değeri otomatik olarak ayarlar.",
|
||||
"transcoding_required_description": "Yalnızca kabul edilen formatta olmayan videolar",
|
||||
@@ -443,6 +462,8 @@
|
||||
"user_settings_description": "Kullanıcı ayarlarını yönet",
|
||||
"user_successfully_removed": "Kullanıcı {email} başarıyla kaldırıldı.",
|
||||
"users_page_description": "Yönetici kullanıcılar sayfası",
|
||||
"version_check_channel": "Yayın kanalı",
|
||||
"version_check_channel_description": "Sürüm duyurularını almak istediğiniz yayın kanalını seçin",
|
||||
"version_check_enabled_description": "Sürüm kontrolü etkin",
|
||||
"version_check_implications": "Sürüm kontrol özelliği, {server} ile periyodik iletişime dayanır",
|
||||
"version_check_settings": "Sürüm Kontrolü",
|
||||
@@ -692,6 +713,7 @@
|
||||
"backup_settings_subtitle": "Yükleme ayarlarını yönet",
|
||||
"backup_upload_details_page_more_details": "Daha fazla ayrıntı için dokunun",
|
||||
"backward": "Geriye doğru",
|
||||
"battery_optimization_backup_reliability": "Pil optimizasyonlarını devre dışı bırakmak, arka plan yedeklemesinin güvenilirliğini artırabilir",
|
||||
"biometric_auth_enabled": "Biyometrik kimlik doğrulama etkin",
|
||||
"biometric_locked_out": "Biyometrik kimlik doğrulaması kilitli",
|
||||
"biometric_no_options": "Biyometrik seçenek yok",
|
||||
@@ -733,6 +755,7 @@
|
||||
"cannot_update_the_description": "Açıklama güncellenemiyor",
|
||||
"cast": "Yansıt",
|
||||
"cast_description": "Kullanılabilir yansıtma hedeflerini yapılandır",
|
||||
"change": "Değiştir",
|
||||
"change_date": "Tarihi değiştir",
|
||||
"change_description": "Açıklamayı değiştir",
|
||||
"change_display_order": "Görüntüleme sırasını değiştir",
|
||||
@@ -779,6 +802,7 @@
|
||||
"clear": "Temizle",
|
||||
"clear_all": "Hepsini temizle",
|
||||
"clear_all_recent_searches": "Son aramaların hepsini temizle",
|
||||
"clear_failed_count": "Temizleme başarısız oldu ({count})",
|
||||
"clear_file_cache": "Dosya Önbelleğini Temizle",
|
||||
"clear_message": "Mesajı temizle",
|
||||
"clear_value": "Değeri temizle",
|
||||
@@ -904,6 +928,7 @@
|
||||
"deduplicate_all": "Tüm kopyaları kaldır",
|
||||
"default_locale": "Varsayılan Dil",
|
||||
"default_locale_description": "Tarih ve sayıları tarayıcınızın yerel ayarlarına göre biçimlendirin",
|
||||
"default_share_quality": "Varsayılan paylaşım kalitesi",
|
||||
"delete": "Sil",
|
||||
"delete_action_confirmation_message": "Bu öğeyi silmek istediğinizden emin misiniz? Bu işlem, öğeyi sunucunun çöp kutusuna taşıyacak ve yerel olarak silmek isteyip istemediğinizi soracaktır",
|
||||
"delete_action_prompt": "{count} silindi",
|
||||
@@ -977,8 +1002,10 @@
|
||||
"downloading_asset_filename": "Öğe indiriliyor {filename}",
|
||||
"downloading_from_icloud": "iCloud’dan indiriliyor",
|
||||
"downloading_media": "Medya indiriliyor",
|
||||
"drag_to_reorder": "Sırayı değiştirmek için sürükleyin",
|
||||
"drop_files_to_upload": "Dosyaları yüklemek için herhangi bir yere bırakın",
|
||||
"duplicate": "Kopyala",
|
||||
"duplicate_workflow": "İş akışını kopyala",
|
||||
"duplicates": "Kopyalar",
|
||||
"duplicates_description": "Her bir grubu, varsa tekrarlanan öğeleri belirterek çözümleyin.",
|
||||
"duration": "Süre",
|
||||
@@ -1080,6 +1107,7 @@
|
||||
"failed_to_remove_product_key": "Ürün anahtarı kaldırılamadı",
|
||||
"failed_to_reset_pin_code": "PIN kodu sıfırlanamadı",
|
||||
"failed_to_stack_assets": "Öğeler yığınlanamadı",
|
||||
"failed_to_tag_assets": "Varlıkları etiketleme başarısız oldu",
|
||||
"failed_to_unstack_assets": "Öğelerin yığını kaldırılamadı",
|
||||
"failed_to_update_notification_status": "Bildirim durumu güncellenemedi",
|
||||
"incorrect_email_or_password": "Yanlış e-posta veya şifre",
|
||||
@@ -1204,10 +1232,12 @@
|
||||
"external_libraries": "Harici kütüphaneler",
|
||||
"external_network": "Harici ağlar",
|
||||
"external_network_sheet_info": "Belirlenmiş Wi-Fi ağına bağlı olmadığında uygulama, yukarıdan aşağıya doğru ulaşabileceği aşağıdaki URL'lerden ilki aracılığıyla sunucuya bağlanacaktır",
|
||||
"f_number": "F-Numarası",
|
||||
"face_unassigned": "Yüz atanmadı",
|
||||
"failed": "Başarısız",
|
||||
"failed_count": "Başarısız: {count}",
|
||||
"failed_to_authenticate": "Kimlik doğrulaması yapılamadı",
|
||||
"failed_to_delete_file": "Dosya silme işlemi başarısız oldu",
|
||||
"failed_to_load_assets": "Öğeler yüklenemedi",
|
||||
"failed_to_load_folder": "Klasör yüklenemedi",
|
||||
"favorite": "Favori",
|
||||
@@ -1338,6 +1368,7 @@
|
||||
"individual_share": "Bireysel paylaşım",
|
||||
"individual_shares": "Kişisel paylaşımlar",
|
||||
"info": "Bilgi",
|
||||
"integrity_checks": "Bütünlük Kontrolleri",
|
||||
"interval": {
|
||||
"day_at_onepm": "Her gün saat 13:00'te",
|
||||
"hours": "{hours, plural, one {Her saat} other {Her {hours, number} saatte}}",
|
||||
@@ -1385,6 +1416,7 @@
|
||||
"leave": "Ayrıl",
|
||||
"leave_album": "Albümden çık",
|
||||
"lens_model": "Mercek modeli",
|
||||
"less": "Daha az",
|
||||
"let_others_respond": "Diğerlerinin yanıt vermesine izin ver",
|
||||
"level": "Seviye",
|
||||
"library": "Kütüphane",
|
||||
@@ -1409,6 +1441,7 @@
|
||||
"linked_oauth_account": "Bağlı OAuth hesabı",
|
||||
"list": "Liste",
|
||||
"live": "Canlı",
|
||||
"load_more": "Daha Fazla Yükle",
|
||||
"loading": "Yükleniyor",
|
||||
"loading_search_results_failed": "Arama sonuçları yüklenemedi",
|
||||
"local": "Yerel",
|
||||
@@ -1509,7 +1542,6 @@
|
||||
"map_location_picker_page_use_location": "Bu konumu kullan",
|
||||
"map_location_service_disabled_content": "Mevcut konumunuzdan öğeleri görüntülemek için konum hizmetinin etkinleştirilmesi gerekiyor. Şimdi etkinleştirmek istiyor musunuz?",
|
||||
"map_location_service_disabled_title": "Konum hizmeti devre dışı bırakıldı",
|
||||
"map_marker_for_images": "{city}, {country} şehrinde çekilen fotoğraflar için harita işaretleyicisi",
|
||||
"map_marker_with_image": "Resimli harita işaretleyicisi",
|
||||
"map_no_location_permission_content": "Mevcut konumunuzdan öğeleri görüntülemek için konum iznine ihtiyaç var. Şimdi izin vermek istiyor musunuz?",
|
||||
"map_no_location_permission_title": "Konum izni reddedildi",
|
||||
@@ -1532,8 +1564,11 @@
|
||||
"matching_assets": "Eşleşen Öğeler",
|
||||
"media_chrome": {
|
||||
"auto": "Otomatik",
|
||||
"captions": "Altyazılar",
|
||||
"captions_off": "Kapalı",
|
||||
"closed_captions": "kapalı altyazılar",
|
||||
"decode_error": "Kod çözümleme hatası",
|
||||
"disable_captions": "Altyazıları devre dışı bırak",
|
||||
"enable_captions": "Altyazılar açık",
|
||||
"enter_fullscreen_mode": "Tam ekran kipini aç",
|
||||
"exit_fullscreen_mode": "Tam ekran kipini kapat",
|
||||
@@ -1553,6 +1588,8 @@
|
||||
"seconds": "saniyeler",
|
||||
"time_value_of_total_time": "{currentTime} / {totalTime}",
|
||||
"time_value_remaining": "{time} kaldı",
|
||||
"unmute": "Sesini açmak",
|
||||
"unsupported_error_description": "Desteklenmeyen bir hata oluştu. Sunucu veya ağ hatası ya da tarayıcınız bu formatı desteklemiyor.",
|
||||
"video_not_loaded_unknown_time": "video yüklenmedi, süre bilinmiyor.",
|
||||
"video_player": "Video oynatıcı",
|
||||
"volume": "Ses"
|
||||
@@ -1573,6 +1610,8 @@
|
||||
"merge_people_prompt": "Bu kişileri birleştirmek istiyor musunuz? Bu işlem geri alınamaz.",
|
||||
"merge_people_successfully": "Kişiler başarılı bir şekilde birleştirildi",
|
||||
"merged_people_count": "{count, plural, one {# kişi} other {# kişi}} birleştirildi",
|
||||
"minFaces": "Minimum yüzler",
|
||||
"minFaces_description": "Bir kişinin görüntülenebilmesi için minimum tanınan yüz sayısı",
|
||||
"minimize": "Küçült",
|
||||
"minute": "Dakika",
|
||||
"minutes": "Dakika",
|
||||
@@ -1659,6 +1698,7 @@
|
||||
"no_results": "Sonuç bulunamadı",
|
||||
"no_results_description": "Eş anlamlı ya da daha genel anlamlı bir kelime deneyin",
|
||||
"no_shared_albums_message": "Fotoğrafları ve videoları ağınızdaki kişilerle paylaşmak için bir albüm oluşturun",
|
||||
"no_steps": "Henüz hiçbir adım eklenmedi",
|
||||
"no_uploads_in_progress": "Yükleme işlemi yok",
|
||||
"none": "Yok",
|
||||
"not_allowed": "İzin verilmiyor",
|
||||
@@ -1667,6 +1707,7 @@
|
||||
"not_selected": "Seçilmedi",
|
||||
"notes": "Notlar",
|
||||
"nothing_here_yet": "Burada henüz bir şey yok",
|
||||
"notification_backup_reliability": "Arka plan yedeklemelerinin güvenirliğini iyileştirmek için bildirimlere izin verin",
|
||||
"notification_permission_dialog_content": "Bildirimleri etkinleştirmek için cihaz ayarlarına gidin ve izin verin.",
|
||||
"notification_permission_list_tile_content": "Bildirimleri etkinleştirmek için izin verin.",
|
||||
"notification_permission_list_tile_enable_button": "Bildirimleri Etkinleştir",
|
||||
@@ -1796,6 +1837,7 @@
|
||||
"play_transcoded_video": "Kodlanmış videoyu oynat",
|
||||
"please_auth_to_access": "Erişim için lütfen kimliğinizi doğrulayın",
|
||||
"plugin_method_filter_type": "Süzgeç",
|
||||
"plugin_method_filter_type_description": "Bu yöntem olayları filtreleyebilir ve koşullu olarak sonraki adımların çalışmasını engelleyebilir",
|
||||
"port": "Port",
|
||||
"preferences_settings_subtitle": "Uygulama tercihlerini düzenle",
|
||||
"preferences_settings_title": "Tercihler",
|
||||
@@ -1978,6 +2020,8 @@
|
||||
"search_by_description_example": "Sapa'da yürüyüş günü",
|
||||
"search_by_filename": "Dosya adına veya uzantısına göre ara",
|
||||
"search_by_filename_example": "Örn. IMG_1234.JPG veya PNG",
|
||||
"search_by_full_path": "Tam dosya yolu veya klasöre göre arama yapın",
|
||||
"search_by_full_path_example": "/John/Projeler/3D_Baskı/2026-07-01 - Projeler, 3D, Baskı, 2026 vb. kelimelerle arama yapabilirsiniz.",
|
||||
"search_by_ocr": "OCR'ye göre ara",
|
||||
"search_by_ocr_example": "Sütlü Kahve",
|
||||
"search_camera_lens_model": "Lens modelini ara...",
|
||||
@@ -2054,6 +2098,7 @@
|
||||
"select_person": "Kişileri seç",
|
||||
"select_person_to_tag": "Etiketlemek için bir kişi seçin",
|
||||
"select_photos": "Fotoğrafları seç",
|
||||
"select_quality": "Kaliteyi seçin",
|
||||
"select_trash_all": "Hepsini çöpe at",
|
||||
"select_user_for_sharing_page_err_album": "Albüm oluşturulamadı",
|
||||
"selected": "Seçildi",
|
||||
@@ -2117,6 +2162,8 @@
|
||||
"share_assets_selected": "{count} seçili",
|
||||
"share_dialog_preparing": "Hazırlanıyor...",
|
||||
"share_link": "Bağlantıyı Paylaş",
|
||||
"share_original": "Orijinal (büyük) olanı kullanın",
|
||||
"share_preview": "Küçük resmi kullan",
|
||||
"shared": "Paylaşılan",
|
||||
"shared_album_activities_input_disable": "Yoruma kapalı",
|
||||
"shared_album_activity_remove_content": "Bu etkinliği silmek istiyor musunuz?",
|
||||
@@ -2210,12 +2257,14 @@
|
||||
"skip_to_folders": "Klasörlere atla",
|
||||
"skip_to_tags": "Etiketlere atla",
|
||||
"slideshow": "Slayt gösterisi",
|
||||
"slideshow_metadata_overlay_mode": "Yer paylaşımı içeriği",
|
||||
"slideshow_metadata_overlay_mode_description_only": "Sadece açıklama",
|
||||
"slideshow_metadata_overlay_mode_full": "Dolu",
|
||||
"slideshow_repeat": "Slayt gösterisini tekrarla",
|
||||
"slideshow_repeat_description": "Slayt gösterisi bittiğinde başa dön",
|
||||
"slideshow_settings": "Slayt gösterisi ayarları",
|
||||
"smart_album": "Akıllı albüm",
|
||||
"some_assets_already_have_a_location_warning": "Seçilen varlıkların bazılarının zaten bir konumu mevcut",
|
||||
"sort_albums_by": "Albümleri sırala...",
|
||||
"sort_created": "Oluşturulma tarihi",
|
||||
"sort_items": "Öğe sayısı",
|
||||
@@ -2239,6 +2288,7 @@
|
||||
"state": "Eyalet/İl",
|
||||
"status": "Durum",
|
||||
"step_delete": "Adımı sil",
|
||||
"step_delete_confirm": "Bu adımı silmek istediğinizden emin misiniz?",
|
||||
"step_details": "Adım ayrıntıları",
|
||||
"steps": "Adımlar",
|
||||
"stop_casting": "Yansıtmayı durdur",
|
||||
@@ -2334,11 +2384,13 @@
|
||||
"trash_page_title": "Çöp Kutusu ({count})",
|
||||
"trashed_items_will_be_permanently_deleted_after": "Silinen öğeler {days, plural, one {# gün} other {# gün}} sonra kalıcı olarak silinecek.",
|
||||
"trigger": "Tetikleyici",
|
||||
"trigger_asset_uploaded": "Öğe Karşıya Yüklendi",
|
||||
"trigger_asset_metadata_extraction": "Varlık Meta Veri Çıkarma",
|
||||
"trigger_asset_metadata_extraction_description": "Bir varlığın EXIF meta verileri çıkarıldığında tetiklenir",
|
||||
"trigger_asset_uploaded": "Öğe Karşıya Yüklenince",
|
||||
"trigger_asset_uploaded_description": "Yeni bir öğe karşıya yüklendiğinde tetiklenir",
|
||||
"trigger_description": "İş akışını başlatan bir olay",
|
||||
"trigger_person_recognized": "Tanınan Kişi",
|
||||
"trigger_person_recognized_description": "Bir kişi algılandığında tetiklenir",
|
||||
"trigger_person_recognized_description": "Bir kişi tanındığında tetiklenir",
|
||||
"trigger_type": "Tetikleyici türü",
|
||||
"troubleshoot": "Sorun giderme",
|
||||
"type": "Tür",
|
||||
@@ -2380,6 +2432,7 @@
|
||||
"updated_password": "Güncellenen şifre",
|
||||
"upload": "Yükle",
|
||||
"upload_concurrency": "Yükleme eşzamanlılığı",
|
||||
"upload_day_count": "{tarih}: {sayı, çoğul, bir {# yükleme} diğer {# yüklemeler}}",
|
||||
"upload_details": "Yükleme Ayrıntıları",
|
||||
"upload_dialog_info": "Seçili öğeleri sunucuya yedeklemek istiyor musunuz?",
|
||||
"upload_dialog_title": "Öğe Yükle",
|
||||
@@ -2395,6 +2448,7 @@
|
||||
"upload_to_immich": "Immich'e Yükle ({count})",
|
||||
"uploading": "Yükleniyor",
|
||||
"uploading_media": "Medya yükleme",
|
||||
"uploads": "Yüklemeler",
|
||||
"url": "URL",
|
||||
"usage": "Kullanım",
|
||||
"use_biometric": "Biyometri kullan",
|
||||
@@ -2402,6 +2456,7 @@
|
||||
"use_browser_locale_description": "Tarih, saat ve sayılar tarayıcınızın yerel ayarlarına göre biçimlendirilsin",
|
||||
"use_current_connection": "Mevcut bağlantıyı kullan",
|
||||
"use_custom_date_range": "Bunun yerine özel tarih aralığını kullan",
|
||||
"use_template": "Şablonu kullan",
|
||||
"user": "Kullanıcı",
|
||||
"user_has_been_deleted": "Bu kullanıcı silindi.",
|
||||
"user_id": "Kullanıcı ID",
|
||||
@@ -2431,6 +2486,7 @@
|
||||
"video": "Video",
|
||||
"video_hover_setting": "Üzerinde durulduğunda video ön izlemesi oynat",
|
||||
"video_hover_setting_description": "Öğe üzerinde fareyle durulduğunda video küçük resmini oynatır. Bu özellik devre dışıyken, oynatma simgesine fareyle gidilerek oynatma başlatılabilir.",
|
||||
"video_quality": "Video kalitesi",
|
||||
"videos": "Videolar",
|
||||
"videos_count": "{count, plural, one {# video} other {# video}}",
|
||||
"videos_only": "Sadece videolar",
|
||||
@@ -2463,6 +2519,7 @@
|
||||
"week": "Hafta",
|
||||
"welcome": "Hoş geldiniz",
|
||||
"welcome_to_immich": "Immich'e hoş geldiniz",
|
||||
"when": "Ne zaman",
|
||||
"width": "Genişlik",
|
||||
"wifi_name": "Wi-Fi Adı",
|
||||
"workflow": "İş Akışı",
|
||||
@@ -2475,6 +2532,7 @@
|
||||
"workflow_name": "İş akışı adı",
|
||||
"workflow_navigation_prompt": "Değişikliklerinizi kaydetmeden ayrılmak istediğinizden emin misiniz?",
|
||||
"workflow_summary": "İş akışı özeti",
|
||||
"workflow_templates": "İş akışı şablonları",
|
||||
"workflow_update_success": "İş akışı başarıyla güncellendi",
|
||||
"workflow_updated": "İş akışı güncellendi",
|
||||
"workflows": "İş akışları",
|
||||
|
||||
@@ -1532,7 +1532,6 @@
|
||||
"map_location_picker_page_use_location": "Використати це місце",
|
||||
"map_location_service_disabled_content": "Служба визначення місця має бути увімкнена, щоб відображати елементи з вашого поточного місця. Увімкнути її зараз?",
|
||||
"map_location_service_disabled_title": "Служба визначення місця вимкнена",
|
||||
"map_marker_for_images": "Маркер на мапі для зображень, знятих у {city}, {country}",
|
||||
"map_marker_with_image": "Маркер на мапі із зображенням",
|
||||
"map_no_location_permission_content": "Потрібен дозвіл, щоб показувати елементи із поточного місця. Надати його зараз?",
|
||||
"map_no_location_permission_title": "Доступ до місця не надано",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"add_partner": "ساتھی شامل کریں",
|
||||
"add_path": "راستہ شامل کریں",
|
||||
"add_photos": "تصاویر شامل کریں",
|
||||
"add_step": "مرحلہ بنائیں",
|
||||
"add_tag": "ٹیگ شامل کریں",
|
||||
"add_to": "اس میں شامل کریں…",
|
||||
"add_to_album": "البم میں شامل کریں",
|
||||
@@ -70,7 +71,11 @@
|
||||
"confirm_reprocess_all_faces": "کیا آپ واقعی تمام چہروں کو دوبارہ پروسیس کرنا چاہتے ہیں؟ اس سے نام والے افراد بھی صاف ہو جائیں گے۔",
|
||||
"confirm_user_password_reset": "کیا آپ {user} کا پاس ورڈ ری سیٹ کرنا چاہتے ہیں؟",
|
||||
"confirm_user_pin_code_reset": "کیا آپ {user} کا پن کوڈ ری سیٹ کرنا چاہتے ہیں؟",
|
||||
"copy_config_to_clipboard_description": "اپنی موجودہ سسٹم کے نظام کی ترتیب JSON کی شکل میں کلپ بورڈ میں کاپی کریں",
|
||||
"create_job": "کام بنائیں",
|
||||
"disable_login": "لاگ ان بند کریں",
|
||||
"download_csv": "CSV ڈاون لوڈ کریں",
|
||||
"duplicate_detection_job_description": "اپنی اجراۂ پر مشین لرننگ چلا کر ایک جیسی تصاویر کا پتہ لگا ئے۔ \"Smart Search\" پر انحصار کرتا ہے",
|
||||
"face_detection": "چہرے کی پہچان",
|
||||
"failed_job_command": "کام: {job} کے لیے کمانڈ: {command} ناکام ہو گئی",
|
||||
"image_preview_title": "پیش نظارہ",
|
||||
|
||||
+491
-356
File diff suppressed because it is too large
Load Diff
@@ -304,6 +304,12 @@
|
||||
"oauth_storage_label_claim": "儲存標籤宣告",
|
||||
"oauth_storage_label_claim_description": "自動將使用者嘅儲存標籤設定為呢個宣告值。",
|
||||
"oauth_storage_quota_claim": "儲存限額宣告",
|
||||
"oauth_storage_quota_claim_description": "自動將使用者嘅儲存限額設定為呢個宣告之值。",
|
||||
"oauth_storage_quota_default": "預設儲存限額(GiB)",
|
||||
"oauth_storage_quota_default_description": "未提供宣告時所使用嘅限額(GiB)。",
|
||||
"oauth_timeout": "請求超時",
|
||||
"oauth_timeout_description": "請求超時(毫秒)",
|
||||
"ocr_job_description": "用機械學習辨識影像中嘅文字",
|
||||
"queue_details": "隊列資訊",
|
||||
"queues": "任務隊列",
|
||||
"queues_page_description": "管理員任務隊列頁面",
|
||||
|
||||
@@ -1548,7 +1548,6 @@
|
||||
"map_location_picker_page_use_location": "使用此位置",
|
||||
"map_location_service_disabled_content": "需要启用定位服务才能显示您当前位置的媒体文件。是否现在启用它?",
|
||||
"map_location_service_disabled_title": "定位服务已禁用",
|
||||
"map_marker_for_images": "标记{city}、{country}拍摄照片的地图图标",
|
||||
"map_marker_with_image": "带预览图的地图标记",
|
||||
"map_no_location_permission_content": "需要位置权限才能显示您当前位置的照片/视频。现在要允许吗?",
|
||||
"map_no_location_permission_title": "位置权限被拒绝",
|
||||
|
||||
@@ -1548,7 +1548,6 @@
|
||||
"map_location_picker_page_use_location": "使用此位置",
|
||||
"map_location_service_disabled_content": "需要啟用定位服務才能顯示您目前位置相關的項目。要現在啟用嗎?",
|
||||
"map_location_service_disabled_title": "定位服務已停用",
|
||||
"map_marker_for_images": "在 {city}、{country} 拍攝影像的地圖標記",
|
||||
"map_marker_with_image": "帶有影像的地圖標記",
|
||||
"map_no_location_permission_content": "需要位置權限才能顯示與您目前位置相關的項目。要現在就授予位置權限嗎?",
|
||||
"map_no_location_permission_title": "沒有位置權限",
|
||||
|
||||
@@ -5,6 +5,7 @@ const Map<String, Locale> locales = {
|
||||
'English (en)': Locale('en'),
|
||||
// Additional locales
|
||||
'Arabic (ar)': Locale('ar'),
|
||||
'Basque (eu)': Locale('eu'),
|
||||
'Bosnian (bl)': Locale('bn'),
|
||||
'Brazilian Portuguese (pt_BR)': Locale('pt', 'BR'),
|
||||
'Bulgarian (bg)': Locale('bg'),
|
||||
|
||||
@@ -280,7 +280,8 @@ class SyncStreamService {
|
||||
return;
|
||||
// SyncCompleteV1 is used to signal the completion of the sync process. Cleanup stale assets and signal completion
|
||||
case SyncEntityType.syncCompleteV1:
|
||||
return _syncStreamRepository.pruneAssets();
|
||||
return;
|
||||
// return _syncStreamRepository.pruneAssets();
|
||||
// Request to reset the client state. Clear everything related to remote entities
|
||||
case SyncEntityType.syncResetV1:
|
||||
return _syncStreamRepository.reset();
|
||||
|
||||
@@ -1,23 +1,13 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.widget.dart';
|
||||
import 'package:immich_mobile/presentation/actions/partner.action.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/people/partner_user_avatar.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/confirm_dialog.dart';
|
||||
|
||||
@visibleForTesting
|
||||
final candidatesStateProvider = StreamProvider.autoDispose<Iterable<User>>((ref) {
|
||||
final currentUser = ref.watch(currentUserProvider);
|
||||
// TODO: Refactor with a route guard to avoid this check in every provider
|
||||
if (currentUser == null) {
|
||||
return const Stream.empty();
|
||||
}
|
||||
return ref.watch(partnerServiceProvider).getCandidates(currentUser.id);
|
||||
});
|
||||
|
||||
@visibleForTesting
|
||||
final partnersStateProvider = StreamProvider.autoDispose<Iterable<Partner>>((ref) {
|
||||
@@ -30,28 +20,6 @@ final partnersStateProvider = StreamProvider.autoDispose<Iterable<Partner>>((ref
|
||||
return ref.watch(partnerServiceProvider).search(currentUser.id, .sharedBy);
|
||||
});
|
||||
|
||||
Future<void> _addPartner(BuildContext context, WidgetRef ref) async {
|
||||
final selected = await showDialog<User>(context: context, builder: (_) => const PartnerSelectionDialog());
|
||||
final currentUser = ref.read(currentUserProvider);
|
||||
if (selected != null && currentUser != null) {
|
||||
await ref.read(partnerServiceProvider).create(sharedById: currentUser.id, sharedWithId: selected.id);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _removePartner(BuildContext context, WidgetRef ref, Partner partner) => showDialog(
|
||||
context: context,
|
||||
builder: (_) => ConfirmDialog(
|
||||
title: "stop_photo_sharing",
|
||||
content: context.t.partner_page_stop_sharing_content(partner: partner.name),
|
||||
onOk: () {
|
||||
final currentUser = ref.read(currentUserProvider);
|
||||
if (currentUser != null) {
|
||||
ref.read(partnerServiceProvider).delete(sharedById: currentUser.id, sharedWithId: partner.id);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@RoutePage()
|
||||
class PartnerPage extends ConsumerWidget {
|
||||
const PartnerPage({super.key});
|
||||
@@ -65,20 +33,10 @@ class PartnerPage extends ConsumerWidget {
|
||||
title: Text(context.t.partners),
|
||||
elevation: 0,
|
||||
centerTitle: false,
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () => _addPartner(context, ref),
|
||||
icon: const Icon(Icons.person_add),
|
||||
tooltip: context.t.add_partner,
|
||||
),
|
||||
],
|
||||
actions: const [ActionIconButtonWidget(action: PartnerAddAction())],
|
||||
),
|
||||
body: sharedByAsync.when(
|
||||
data: (partners) => PartnerSharedByList(
|
||||
partners: partners.toList(growable: false),
|
||||
onAdd: () => _addPartner(context, ref),
|
||||
onRemove: (partner) => _removePartner(context, ref, partner),
|
||||
),
|
||||
data: (partners) => PartnerSharedByList(partners: partners.toList(growable: false)),
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (error, _) => Center(child: Text(context.t.error_loading_partners(error: error))),
|
||||
),
|
||||
@@ -87,9 +45,7 @@ class PartnerPage extends ConsumerWidget {
|
||||
}
|
||||
|
||||
class _EmptyPartners extends StatelessWidget {
|
||||
const _EmptyPartners({required this.onAdd});
|
||||
|
||||
final VoidCallback onAdd;
|
||||
const _EmptyPartners();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -102,13 +58,9 @@ class _EmptyPartners extends StatelessWidget {
|
||||
padding: const .symmetric(vertical: 8),
|
||||
child: Text(context.t.partner_page_empty_message, style: const TextStyle(fontSize: 14)),
|
||||
),
|
||||
Align(
|
||||
const Align(
|
||||
alignment: .center,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: onAdd,
|
||||
icon: const Icon(Icons.person_add),
|
||||
label: Text(context.t.add_partner),
|
||||
),
|
||||
child: ActionButtonWidget(action: PartnerAddAction()),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -118,16 +70,14 @@ class _EmptyPartners extends StatelessWidget {
|
||||
|
||||
@visibleForTesting
|
||||
class PartnerSharedByList extends StatelessWidget {
|
||||
const PartnerSharedByList({super.key, required this.partners, required this.onAdd, required this.onRemove});
|
||||
const PartnerSharedByList({super.key, required this.partners});
|
||||
|
||||
final List<Partner> partners;
|
||||
final VoidCallback onAdd;
|
||||
final ValueChanged<Partner> onRemove;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (partners.isEmpty) {
|
||||
return _EmptyPartners(onAdd: onAdd);
|
||||
return const _EmptyPartners();
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
@@ -138,63 +88,11 @@ class PartnerSharedByList extends StatelessWidget {
|
||||
leading: PartnerUserAvatar(userId: partner.id, name: partner.name),
|
||||
title: Text(partner.name),
|
||||
subtitle: Text(partner.email),
|
||||
trailing: IconButton(icon: const Icon(Icons.person_remove), onPressed: () => onRemove(partner)),
|
||||
trailing: ActionIconButtonWidget(
|
||||
action: PartnerRemoveAction(sharedWithId: partner.id, partnerName: partner.name),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
class PartnerSelectionDialog extends ConsumerWidget {
|
||||
const PartnerSelectionDialog({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final candidatesAsync = ref.watch(candidatesStateProvider);
|
||||
|
||||
return SimpleDialog(
|
||||
title: const Text("partner_page_select_partner").tr(),
|
||||
children: candidatesAsync.when(
|
||||
data: (candidates) {
|
||||
final users = candidates.toList();
|
||||
if (users.isEmpty) {
|
||||
return [
|
||||
Padding(
|
||||
padding: const .symmetric(horizontal: 24, vertical: 8),
|
||||
child: const Text("partner_page_no_more_users").tr(),
|
||||
),
|
||||
];
|
||||
}
|
||||
return [
|
||||
for (final candidate in users)
|
||||
SimpleDialogOption(
|
||||
onPressed: () => Navigator.of(context).pop(candidate),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const .only(right: 8),
|
||||
child: PartnerUserAvatar(userId: candidate.id, name: candidate.name),
|
||||
),
|
||||
Text(candidate.name),
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
loading: () => const [
|
||||
Padding(
|
||||
padding: .all(24),
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
],
|
||||
error: (error, _) => [
|
||||
Padding(
|
||||
padding: const .symmetric(horizontal: 24, vertical: 8),
|
||||
child: Text(context.t.error_loading_partners(error: error)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
|
||||
class ActionScope {
|
||||
final BuildContext context;
|
||||
final WidgetRef ref;
|
||||
final UserDto authUser;
|
||||
|
||||
const ActionScope({required this.context, required this.ref, required this.authUser});
|
||||
}
|
||||
|
||||
abstract class BaseAction {
|
||||
const BaseAction();
|
||||
|
||||
IconData get icon;
|
||||
|
||||
String label(ActionScope scope);
|
||||
|
||||
bool isVisible(ActionScope scope) => true;
|
||||
|
||||
Future<void> onAction(ActionScope scope);
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/utils/error_handler.dart';
|
||||
import 'package:immich_ui/immich_ui.dart';
|
||||
|
||||
class _ActionWidgetScope {
|
||||
final String label;
|
||||
final VoidCallback onAction;
|
||||
|
||||
const _ActionWidgetScope({required this.label, required this.onAction});
|
||||
}
|
||||
|
||||
class _ActionWidget extends ConsumerWidget {
|
||||
final BaseAction action;
|
||||
final Widget Function(_ActionWidgetScope context) builder;
|
||||
|
||||
const _ActionWidget({required this.action, required this.builder});
|
||||
|
||||
Future<void> _onAction(ActionScope scope) async {
|
||||
try {
|
||||
await action.onAction(scope);
|
||||
} catch (error, stackTrace) {
|
||||
handleError(scope.context, error, stack: stackTrace, description: 'Action failed: ${action.runtimeType}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final authUser = ref.watch(currentUserProvider);
|
||||
if (authUser == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final scope = ActionScope(context: context, ref: ref, authUser: authUser);
|
||||
if (!action.isVisible(scope)) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return builder(.new(label: action.label(scope), onAction: () => _onAction(scope)));
|
||||
}
|
||||
}
|
||||
|
||||
class ActionIconButtonWidget extends StatelessWidget {
|
||||
final BaseAction action;
|
||||
final ImmichVariant variant;
|
||||
|
||||
const ActionIconButtonWidget({super.key, required this.action, this.variant = .ghost});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _ActionWidget(
|
||||
action: action,
|
||||
builder: (ctx) => ImmichIconButton(icon: action.icon, onPressed: ctx.onAction, variant: variant),
|
||||
);
|
||||
}
|
||||
|
||||
class ActionButtonWidget extends StatelessWidget {
|
||||
final BaseAction action;
|
||||
final ImmichVariant variant;
|
||||
|
||||
const ActionButtonWidget({super.key, required this.action, this.variant = .ghost});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _ActionWidget(
|
||||
action: action,
|
||||
builder: (ctx) =>
|
||||
ImmichTextButton(labelText: ctx.label, icon: action.icon, onPressed: ctx.onAction, variant: variant),
|
||||
);
|
||||
}
|
||||
|
||||
class ActionColumnButtonWidget extends StatelessWidget {
|
||||
final BaseAction action;
|
||||
|
||||
const ActionColumnButtonWidget({super.key, required this.action});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _ActionWidget(
|
||||
action: action,
|
||||
builder: (ctx) => ImmichColumnButton(icon: action.icon, label: ctx.label, onPressed: ctx.onAction),
|
||||
);
|
||||
}
|
||||
|
||||
class ActionMenuItemWidget extends StatelessWidget {
|
||||
final BaseAction action;
|
||||
|
||||
const ActionMenuItemWidget({super.key, required this.action});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _ActionWidget(
|
||||
action: action,
|
||||
builder: (ctx) => ImmichMenuItem(icon: action.icon, label: ctx.label, onPressed: ctx.onAction),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/people/partner_user_avatar.widget.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/confirm_dialog.dart';
|
||||
|
||||
class PartnerAddAction extends BaseAction {
|
||||
const PartnerAddAction();
|
||||
|
||||
@override
|
||||
IconData get icon => Icons.person_add_rounded;
|
||||
|
||||
@override
|
||||
String label(ActionScope scope) => scope.context.t.add_partner;
|
||||
|
||||
@override
|
||||
Future<void> onAction(ActionScope scope) async {
|
||||
final ActionScope(:context, :ref, :authUser) = scope;
|
||||
final selected = await showDialog<User>(context: context, builder: (_) => const PartnerSelectionDialog());
|
||||
if (selected == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
await ref.read(partnerServiceProvider).create(sharedById: authUser.id, sharedWithId: selected.id);
|
||||
}
|
||||
}
|
||||
|
||||
class PartnerRemoveAction extends BaseAction {
|
||||
const PartnerRemoveAction({required this.sharedWithId, required this.partnerName});
|
||||
|
||||
final String sharedWithId;
|
||||
final String partnerName;
|
||||
|
||||
@override
|
||||
IconData get icon => Icons.person_remove_rounded;
|
||||
|
||||
@override
|
||||
String label(ActionScope scope) => scope.context.t.remove;
|
||||
|
||||
@override
|
||||
Future<void> onAction(ActionScope scope) async {
|
||||
final ActionScope(:context, :ref, :authUser) = scope;
|
||||
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (_) => ConfirmDialog(
|
||||
title: context.t.stop_photo_sharing,
|
||||
content: context.t.partner_page_stop_sharing_content(partner: partnerName),
|
||||
),
|
||||
);
|
||||
if (confirmed != true) {
|
||||
return;
|
||||
}
|
||||
|
||||
await ref.read(partnerServiceProvider).delete(sharedById: authUser.id, sharedWithId: sharedWithId);
|
||||
}
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
final candidatesStateProvider = StreamProvider.autoDispose<Iterable<User>>((ref) {
|
||||
final currentUser = ref.watch(currentUserProvider);
|
||||
// TODO: Refactor with a route guard to avoid this check in every provider
|
||||
if (currentUser == null) {
|
||||
return const Stream.empty();
|
||||
}
|
||||
return ref.watch(partnerServiceProvider).getCandidates(currentUser.id);
|
||||
});
|
||||
|
||||
@visibleForTesting
|
||||
class PartnerSelectionDialog extends ConsumerWidget {
|
||||
const PartnerSelectionDialog({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final candidatesAsync = ref.watch(candidatesStateProvider);
|
||||
|
||||
return SimpleDialog(
|
||||
title: Text(context.t.partner_page_select_partner),
|
||||
children: candidatesAsync.when(
|
||||
data: (candidates) {
|
||||
final users = candidates.toList();
|
||||
if (users.isEmpty) {
|
||||
return [
|
||||
Padding(
|
||||
padding: const .symmetric(horizontal: 24, vertical: 8),
|
||||
child: Text(context.t.partner_page_no_more_users),
|
||||
),
|
||||
];
|
||||
}
|
||||
return [
|
||||
for (final candidate in users)
|
||||
SimpleDialogOption(
|
||||
onPressed: () => Navigator.of(context).pop(candidate),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const .only(right: 8),
|
||||
child: PartnerUserAvatar(userId: candidate.id, name: candidate.name),
|
||||
),
|
||||
Text(candidate.name),
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
loading: () => const [
|
||||
Padding(
|
||||
padding: .all(24),
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
],
|
||||
error: (error, _) => [
|
||||
Padding(
|
||||
padding: const .symmetric(horizontal: 24, vertical: 8),
|
||||
child: Text(context.t.error_loading_partners(error: error)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/memory/memory_bottom_info.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/memory/memory_card.widget.dart';
|
||||
import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
|
||||
import 'package:immich_mobile/utils/system_ui.utils.dart';
|
||||
import 'package:immich_mobile/widgets/memories/memory_epilogue.dart';
|
||||
import 'package:immich_mobile/widgets/memories/memory_progress_indicator.dart';
|
||||
|
||||
@@ -49,7 +50,7 @@ class DriftMemoryPage extends HookConsumerWidget {
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
|
||||
return () {
|
||||
// Clean up to normal edge to edge when we are done
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||
restoreEdgeToEdge();
|
||||
};
|
||||
});
|
||||
|
||||
@@ -328,7 +329,7 @@ class DriftMemoryPage extends HookConsumerWidget {
|
||||
// turn off full screen mode here
|
||||
// https://github.com/Milad-Akarie/auto_route_library/issues/1799
|
||||
context.maybePop();
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||
restoreEdgeToEdge();
|
||||
},
|
||||
shape: const CircleBorder(),
|
||||
color: Colors.white.withValues(alpha: 0.2),
|
||||
|
||||
@@ -19,6 +19,7 @@ import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart'
|
||||
import 'package:immich_mobile/providers/asset_viewer/video_player_provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/utils/system_ui.utils.dart';
|
||||
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
|
||||
import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
@@ -76,7 +77,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
|
||||
_pageController.dispose();
|
||||
_crossfadeController.dispose();
|
||||
unawaited(WakelockPlus.disable());
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||
unawaited(restoreEdgeToEdge());
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -255,7 +256,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
|
||||
}
|
||||
|
||||
void _onTapUp() async {
|
||||
await SystemChrome.setEnabledSystemUIMode(_showAppBar ? SystemUiMode.immersive : SystemUiMode.edgeToEdge);
|
||||
await (_showAppBar ? SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive) : restoreEdgeToEdge());
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
setState(() {
|
||||
|
||||
@@ -23,6 +23,7 @@ import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart'
|
||||
import 'package:immich_mobile/providers/cast.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
import 'package:immich_mobile/utils/system_ui.utils.dart';
|
||||
import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
|
||||
|
||||
@RoutePage()
|
||||
@@ -128,7 +129,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||
_reloadSubscription?.cancel();
|
||||
_stackChildrenKeepAlive?.close();
|
||||
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||
unawaited(restoreEdgeToEdge());
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
@@ -251,10 +252,8 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||
}
|
||||
|
||||
void _setSystemUIMode(bool controls, bool details) {
|
||||
final mode = !controls || (CurrentPlatform.isIOS && details)
|
||||
? SystemUiMode.immersiveSticky
|
||||
: SystemUiMode.edgeToEdge;
|
||||
unawaited(SystemChrome.setEnabledSystemUIMode(mode));
|
||||
final immersive = !controls || (CurrentPlatform.isIOS && details);
|
||||
unawaited(immersive ? SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky) : restoreEdgeToEdge());
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/video_player_provider.dart';
|
||||
@@ -77,18 +79,17 @@ class AssetViewerState {
|
||||
}
|
||||
|
||||
class AssetViewerStateNotifier extends Notifier<AssetViewerState> {
|
||||
StreamSubscription<BaseAsset?>? _assetSubscription;
|
||||
|
||||
@override
|
||||
AssetViewerState build() {
|
||||
ref.listen(_watchedCurrentAssetProvider, (_, next) {
|
||||
final updated = next.valueOrNull;
|
||||
if (updated != null) {
|
||||
state = state.copyWith(currentAsset: updated);
|
||||
}
|
||||
});
|
||||
ref.onDispose(() => _assetSubscription?.cancel());
|
||||
return const AssetViewerState();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_assetSubscription?.cancel();
|
||||
_assetSubscription = null;
|
||||
state = const AssetViewerState();
|
||||
}
|
||||
|
||||
@@ -97,6 +98,16 @@ class AssetViewerStateNotifier extends Notifier<AssetViewerState> {
|
||||
return;
|
||||
}
|
||||
state = state.copyWith(currentAsset: asset, stackIndex: 0, showingOcr: false);
|
||||
_watchCurrentAsset(asset);
|
||||
}
|
||||
|
||||
void _watchCurrentAsset(BaseAsset asset) {
|
||||
_assetSubscription?.cancel();
|
||||
_assetSubscription = ref.read(assetServiceProvider).watchAsset(asset).listen((updated) {
|
||||
if (updated != null) {
|
||||
state = state.copyWith(currentAsset: updated);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void setOpacity(double opacity) {
|
||||
@@ -150,12 +161,3 @@ class AssetViewerStateNotifier extends Notifier<AssetViewerState> {
|
||||
}
|
||||
|
||||
final assetViewerProvider = NotifierProvider<AssetViewerStateNotifier, AssetViewerState>(AssetViewerStateNotifier.new);
|
||||
|
||||
final _watchedCurrentAssetProvider = StreamProvider<BaseAsset?>((ref) {
|
||||
ref.watch(assetViewerProvider.select((s) => s.currentAsset?.heroTag));
|
||||
final asset = ref.read(assetViewerProvider).currentAsset;
|
||||
if (asset == null) {
|
||||
return const Stream.empty();
|
||||
}
|
||||
return ref.read(assetServiceProvider).watchAsset(asset);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
@@ -97,7 +98,7 @@ class AndroidViewIntentHandler implements ViewIntentHandler {
|
||||
|
||||
await _router.replaceAll([
|
||||
const TabShellRoute(),
|
||||
AssetViewerRoute(initialIndex: 0, timelineService: timelineService),
|
||||
AssetViewerRoute(key: UniqueKey(), initialIndex: 0, timelineService: timelineService),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/utils/debug_print.dart';
|
||||
import 'package:immich_ui/immich_ui.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:stack_trace/stack_trace.dart';
|
||||
|
||||
void handleError(BuildContext context, Object error, {StackTrace? stack, String? description}) {
|
||||
String? stackTrace;
|
||||
if (stack != null) {
|
||||
final trace = Trace.from(stack);
|
||||
final clean = trace.foldFrames(
|
||||
(frame) => frame.package == 'flutter' || frame.package == 'flutter_test' || frame.isCore,
|
||||
terse: true,
|
||||
);
|
||||
stackTrace = clean.toString();
|
||||
}
|
||||
|
||||
dPrint(
|
||||
() => 'Error${description != null ? ' ($description)' : ''}: $error${stackTrace != null ? '\n$stackTrace' : ''}',
|
||||
);
|
||||
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String message;
|
||||
if (serverErrorMessage(error) case String serverMessage) {
|
||||
message = serverMessage;
|
||||
} else if (isConnectionError(error)) {
|
||||
message = context.t.login_form_server_error;
|
||||
} else {
|
||||
message = context.t.scaffold_body_error_occurred;
|
||||
}
|
||||
|
||||
snackbar.error(message);
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
String? serverErrorMessage(Object error) {
|
||||
if (error is! ApiException || error.innerException != null || error.message == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
final body = jsonDecode(error.message!);
|
||||
if (body is Map && body['message'] != null) {
|
||||
final message = body['message'];
|
||||
return message is List ? message.join(', ') : message.toString();
|
||||
}
|
||||
} catch (_) {
|
||||
// The body was not JSON; fall back to the raw payload below.
|
||||
}
|
||||
return error.message;
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
bool isConnectionError(Object error) => error is ApiException && error.innerException != null;
|
||||
@@ -0,0 +1,14 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
/// Restore the system bars and return to edge-to-edge layout.
|
||||
///
|
||||
/// On Android 15+/API 36 edge-to-edge is enforced, so calling
|
||||
/// setEnabledSystemUIMode(edgeToEdge) does NOT re-show bars that an immersive
|
||||
/// mode (immersive / immersiveSticky) previously hid. Explicitly request all
|
||||
/// overlays first, then return to edge-to-edge layout.
|
||||
Future<void> restoreEdgeToEdge() async {
|
||||
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values);
|
||||
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
|
||||
class ConfirmDialog extends StatelessWidget {
|
||||
final Function onOk;
|
||||
final Function? onOk;
|
||||
final String title;
|
||||
final String content;
|
||||
final String cancel;
|
||||
@@ -11,7 +11,7 @@ class ConfirmDialog extends StatelessWidget {
|
||||
|
||||
const ConfirmDialog({
|
||||
super.key,
|
||||
required this.onOk,
|
||||
this.onOk,
|
||||
required this.title,
|
||||
required this.content,
|
||||
this.cancel = "cancel",
|
||||
@@ -21,7 +21,7 @@ class ConfirmDialog extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
void onOkPressed() {
|
||||
onOk();
|
||||
onOk?.call();
|
||||
context.pop(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class AssetBulkUploadCheckResult {
|
||||
///
|
||||
Optional<String?> assetId;
|
||||
|
||||
/// Asset ID
|
||||
/// Client-side identifier echoed from the request to match results to inputs
|
||||
String id;
|
||||
|
||||
/// Whether existing asset is trashed
|
||||
|
||||
+34
-34
@@ -69,10 +69,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: background_downloader
|
||||
sha256: "4cb23d9ad4f5060944f38164e7b90d4bf99b57b2472a3bd4676e59b2db4afd06"
|
||||
sha256: aceacec2b2a72ec3a8862ab5895fcbbc71ab33765f3619d57963f3110dd268e3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.5.4"
|
||||
version: "9.5.5"
|
||||
bonsoir:
|
||||
dependency: "direct overridden"
|
||||
description:
|
||||
@@ -229,10 +229,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_assets
|
||||
sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687"
|
||||
sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.2.1"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -326,18 +326,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dbus
|
||||
sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270
|
||||
sha256: "792974a4007974fbc5c1b5433eb2330a9db3e368c3f906253af4c007d0f49a91"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.12"
|
||||
version: "0.7.13"
|
||||
desktop_webview_window:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: desktop_webview_window
|
||||
sha256: "57cf20d81689d5cbb1adfd0017e96b669398a669d927906073b0e42fc64111c0"
|
||||
sha256: b6fdae2cbf9571879b1761c12f27facaf82e22d0bdc74d049907c2a09a432957
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.3"
|
||||
version: "0.3.0"
|
||||
device_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -549,18 +549,18 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_native_splash
|
||||
sha256: "4fb9f4113350d3a80841ce05ebf1976a36de622af7d19aca0ca9a9911c7ff002"
|
||||
sha256: "9db4b80b044e9af17cc4b1272137fc7ace0054d879ef8210a76adc34aaf4cdff"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.7"
|
||||
version: "2.4.8"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0"
|
||||
sha256: "3854fe5e3bff0b113c658f260b90c95dea17c92db0f2addeac2e343dd9969785"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.34"
|
||||
version: "2.0.35"
|
||||
flutter_riverpod:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -642,10 +642,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_web_auth_2
|
||||
sha256: d354998934ddc338e69b999b2abaeb33c6fd09999d3a5f92ead1a6b49b49712e
|
||||
sha256: "8f9303471dcd96670878c9b7c0c4e14c37595b2add67465f6a868f17a5872dfc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.2"
|
||||
version: "5.0.3"
|
||||
flutter_web_auth_2_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -780,10 +780,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: hooks
|
||||
sha256: "025f060e86d2d4c3c47b56e33caf7f93bf9283340f26d23424ebcfccf34f621e"
|
||||
sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
version: "2.0.2"
|
||||
hooks_riverpod:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -844,10 +844,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce
|
||||
sha256: "6300175e00616bbc832e2fc91bfa4d776af5402c81c7151bee6905bb08473c52"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.8.0"
|
||||
version: "4.9.1"
|
||||
image_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -860,10 +860,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_android
|
||||
sha256: d5b3e1774af29c9ab00103afb0d4614070f924d2e0057ac867ec98800114793f
|
||||
sha256: "6f3a1995eafb000333174fae92202622033b0ee7fd917a6cd3730295264df84a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.13+17"
|
||||
version: "0.8.13+19"
|
||||
image_picker_for_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1120,10 +1120,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: native_toolchain_c
|
||||
sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572"
|
||||
sha256: f59351d28f49520cd3a74eb1f41c5f19ae15e53c65a3231d14af672e46510a96
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.17.6"
|
||||
version: "0.19.1"
|
||||
native_video_player:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1161,10 +1161,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: objective_c
|
||||
sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52"
|
||||
sha256: "6cb691c686fa2838c6deb34980d426145c2a5d537491cb83d463c33cdbc726ed"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.3.0"
|
||||
version: "9.4.1"
|
||||
octo_image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1297,10 +1297,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
|
||||
sha256: e20daf680eef1ca62ffe8c8c526b778cc386d50137c77ac71c8ec9c88c13fb9d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.4.7"
|
||||
version: "9.4.9"
|
||||
permission_handler_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1529,10 +1529,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53
|
||||
sha256: a2c49fc1fed7140cadd892d765bd47edbe4ac0b9c7e7e3c493dcb58126f99cf0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.23"
|
||||
version: "2.4.25"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1791,10 +1791,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: "17bc677f0b301615530dd1d67e0a9828cafa2d0b6b6eae4cd3679b7eac4a273c"
|
||||
sha256: b413d49b73867ac08dd2f9890efd3cc11f2a0e577618d50843440a1fb3776c32
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.30"
|
||||
version: "6.3.32"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1871,10 +1871,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_compiler
|
||||
sha256: b9b3f391857781aa96acacef96066f2f49b4cd03cf9fce3ca4d8da2ef5ea129e
|
||||
sha256: "7ee12e6dffe0fc8e755179d6d91b3b34f5924223fc104d85572ef9180d73d172"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.3"
|
||||
version: "1.2.5"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1991,10 +1991,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025"
|
||||
sha256: "67f0aff7be013d107995e9b75bf4e7f2c3ef2dfdb2c8e68024bba0a7fd5756a4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.6.1"
|
||||
version: "7.0.1"
|
||||
xxh3:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:immich_mobile/domain/services/asset.service.dart';
|
||||
import 'package:immich_mobile/domain/services/partner.service.dart';
|
||||
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||
import 'package:immich_mobile/domain/services/user.service.dart';
|
||||
import 'package:immich_mobile/domain/utils/background_sync.dart';
|
||||
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
||||
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||
@@ -14,3 +16,7 @@ class MockNativeSyncApi extends Mock implements NativeSyncApi {}
|
||||
class MockAppSettingsService extends Mock implements AppSettingsService {}
|
||||
|
||||
class MockPartnerService extends Mock implements PartnerService {}
|
||||
|
||||
class MockAssetService extends Mock implements AssetService {}
|
||||
|
||||
class MockUserService extends Mock implements UserService {}
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart';
|
||||
|
||||
import '../repository_context.dart';
|
||||
|
||||
void main() {
|
||||
late MediumRepositoryContext ctx;
|
||||
late SyncStreamRepository sut;
|
||||
|
||||
setUp(() {
|
||||
ctx = MediumRepositoryContext();
|
||||
sut = SyncStreamRepository(ctx.db);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await ctx.dispose();
|
||||
});
|
||||
|
||||
group('pruneAssets', () {
|
||||
test('deletes foreign orphans and keeps owned, partner, and in-album assets', () async {
|
||||
final me = await ctx.newUser();
|
||||
final partner = await ctx.newUser();
|
||||
final stranger = await ctx.newUser();
|
||||
await ctx.newAuthUser(id: me.id);
|
||||
await ctx.newPartner(sharedById: partner.id, sharedWithId: me.id);
|
||||
|
||||
final own = await ctx.newRemoteAsset(ownerId: me.id);
|
||||
final fromPartner = await ctx.newRemoteAsset(ownerId: partner.id);
|
||||
final shared = await ctx.newRemoteAsset(ownerId: stranger.id);
|
||||
await ctx.newRemoteAsset(ownerId: stranger.id);
|
||||
|
||||
final album = await ctx.newRemoteAlbum(ownerId: me.id);
|
||||
await ctx.newRemoteAlbumAsset(albumId: album.id, assetId: shared.id);
|
||||
|
||||
await sut.pruneAssets();
|
||||
|
||||
final remaining = await ctx.db.select(ctx.db.remoteAssetEntity).get();
|
||||
expect(remaining.map((a) => a.id), unorderedEquals([own.id, fromPartner.id, shared.id]));
|
||||
});
|
||||
|
||||
test('does nothing when there is no authenticated user', () async {
|
||||
final stranger = await ctx.newUser();
|
||||
final orphan = await ctx.newRemoteAsset(ownerId: stranger.id);
|
||||
|
||||
await sut.pruneAssets();
|
||||
|
||||
final remaining = await ctx.db.select(ctx.db.remoteAssetEntity).get();
|
||||
expect(remaining.map((a) => a.id), [orphan.id]);
|
||||
});
|
||||
|
||||
test('prunes every stale foreign asset in a large data set', () async {
|
||||
final stranger = await ctx.newUser();
|
||||
await ctx.newAuthUser();
|
||||
for (var i = 0; i < 600; i++) {
|
||||
await ctx.newRemoteAsset(ownerId: stranger.id);
|
||||
}
|
||||
|
||||
await sut.pruneAssets();
|
||||
|
||||
final remaining = await ctx.db.select(ctx.db.remoteAssetEntity).get();
|
||||
expect(remaining, isEmpty);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/memory.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart';
|
||||
@@ -73,20 +72,6 @@ class MediumRepositoryContext {
|
||||
);
|
||||
}
|
||||
|
||||
Future<AuthUserEntityData> newAuthUser({String? id, String? email, AvatarColor? avatarColor}) async {
|
||||
id ??= TestUtils.uuid();
|
||||
return await db
|
||||
.into(db.authUserEntity)
|
||||
.insertReturning(
|
||||
AuthUserEntityCompanion(
|
||||
id: .new(id),
|
||||
email: .new(email ?? '$id@test.com'),
|
||||
name: .new('user_$id'),
|
||||
avatarColor: .new(avatarColor ?? TestUtils.randElement(AvatarColor.values)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> newPartner({required String sharedById, required String sharedWithId, bool? inTimeline}) {
|
||||
return db
|
||||
.into(db.partnerEntity)
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
import '../../domain/service.mock.dart';
|
||||
import '../../unit/factories/remote_asset_factory.dart';
|
||||
|
||||
void main() {
|
||||
late ProviderContainer container;
|
||||
late MockAssetService assetService;
|
||||
|
||||
setUpAll(() => registerFallbackValue(RemoteAssetFactory.create()));
|
||||
|
||||
setUp(() {
|
||||
assetService = MockAssetService();
|
||||
when(() => assetService.watchAsset(any())).thenAnswer((_) => const Stream.empty());
|
||||
|
||||
container = ProviderContainer(overrides: [assetServiceProvider.overrideWithValue(assetService)]);
|
||||
addTearDown(container.dispose);
|
||||
});
|
||||
|
||||
group('AssetViewerStateNotifier asset watching', () {
|
||||
test('propagates stream updates for the current asset into state', () async {
|
||||
final controller = StreamController<BaseAsset?>();
|
||||
addTearDown(controller.close);
|
||||
final asset = RemoteAssetFactory.create();
|
||||
when(() => assetService.watchAsset(asset)).thenAnswer((_) => controller.stream);
|
||||
|
||||
final notifier = container.read(assetViewerProvider.notifier);
|
||||
notifier.setAsset(asset);
|
||||
|
||||
final updated = asset.copyWith(isFavorite: true);
|
||||
controller.add(updated);
|
||||
await pumpEventQueue();
|
||||
|
||||
expect(container.read(assetViewerProvider).currentAsset, updated);
|
||||
});
|
||||
|
||||
test('ignores null stream emissions', () async {
|
||||
final controller = StreamController<BaseAsset?>();
|
||||
addTearDown(controller.close);
|
||||
final asset = RemoteAssetFactory.create();
|
||||
when(() => assetService.watchAsset(asset)).thenAnswer((_) => controller.stream);
|
||||
|
||||
container.read(assetViewerProvider.notifier).setAsset(asset);
|
||||
|
||||
controller.add(null);
|
||||
await pumpEventQueue();
|
||||
|
||||
expect(container.read(assetViewerProvider).currentAsset, asset);
|
||||
});
|
||||
|
||||
test('reset cancels the subscription so later emissions are dropped', () async {
|
||||
final controller = StreamController<BaseAsset?>();
|
||||
addTearDown(controller.close);
|
||||
final asset = RemoteAssetFactory.create();
|
||||
when(() => assetService.watchAsset(asset)).thenAnswer((_) => controller.stream);
|
||||
|
||||
final notifier = container.read(assetViewerProvider.notifier);
|
||||
notifier.setAsset(asset);
|
||||
notifier.reset();
|
||||
|
||||
controller.add(RemoteAssetFactory.create(isFavorite: true));
|
||||
await pumpEventQueue();
|
||||
|
||||
expect(container.read(assetViewerProvider).currentAsset, isNull);
|
||||
});
|
||||
|
||||
test('setAsset switches the current asset, cancels the previous watch and listens to the new one', () async {
|
||||
final first = StreamController<BaseAsset?>();
|
||||
final second = StreamController<BaseAsset?>();
|
||||
addTearDown(first.close);
|
||||
addTearDown(second.close);
|
||||
|
||||
final assetOne = RemoteAssetFactory.create();
|
||||
final assetTwo = RemoteAssetFactory.create();
|
||||
when(() => assetService.watchAsset(assetOne)).thenAnswer((_) => first.stream);
|
||||
when(() => assetService.watchAsset(assetTwo)).thenAnswer((_) => second.stream);
|
||||
|
||||
final notifier = container.read(assetViewerProvider.notifier);
|
||||
notifier.setAsset(assetOne);
|
||||
expect(container.read(assetViewerProvider).currentAsset, assetOne);
|
||||
|
||||
// Updates to the first asset propagate into state.
|
||||
final updatedOne = assetOne.copyWith(visibility: .archive);
|
||||
first.add(updatedOne);
|
||||
await pumpEventQueue();
|
||||
expect(container.read(assetViewerProvider).currentAsset, updatedOne);
|
||||
|
||||
// Switch to new asset
|
||||
notifier.setAsset(assetTwo);
|
||||
expect(container.read(assetViewerProvider).currentAsset, assetTwo);
|
||||
|
||||
// The previous watch is cancelled: stale emissions from the first stream are dropped.
|
||||
first.add(assetOne.copyWith(isFavorite: true));
|
||||
await pumpEventQueue();
|
||||
expect(container.read(assetViewerProvider).currentAsset, assetTwo);
|
||||
|
||||
// The new asset is watched instead: its emissions propagate into state.
|
||||
final updatedTwo = assetTwo.copyWith(isFavorite: true);
|
||||
second.add(updatedTwo);
|
||||
await pumpEventQueue();
|
||||
expect(container.read(assetViewerProvider).currentAsset, updatedTwo);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -5,19 +5,21 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/timeline.model.dart';
|
||||
import 'package:immich_mobile/domain/services/asset.service.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/domain/services/user.service.dart';
|
||||
import 'package:immich_mobile/models/auth/auth_state.model.dart';
|
||||
import 'package:immich_mobile/platform/view_intent_api.g.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||
import 'package:immich_mobile/providers/view_intent/view_intent_handler_android.dart';
|
||||
import 'package:immich_mobile/providers/view_intent/view_intent_pending.provider.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:immich_mobile/services/auth.service.dart';
|
||||
import 'package:immich_mobile/services/secure_storage.service.dart';
|
||||
import 'package:immich_mobile/services/view_intent.service.dart';
|
||||
import 'package:immich_mobile/services/view_intent_asset_resolver.service.dart';
|
||||
import 'package:immich_mobile/services/auth.service.dart';
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:immich_mobile/services/secure_storage.service.dart';
|
||||
import 'package:immich_mobile/services/widget.service.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
@@ -41,6 +43,11 @@ class FakePageRouteInfo extends Fake implements PageRouteInfo<dynamic> {}
|
||||
|
||||
class FakeTimelineService extends Fake implements TimelineService {}
|
||||
|
||||
class FakeAssetService extends Fake implements AssetService {
|
||||
@override
|
||||
Stream<BaseAsset?> watchAsset(BaseAsset asset) => const Stream.empty();
|
||||
}
|
||||
|
||||
class TestViewIntentService extends ViewIntentService {
|
||||
ViewIntentPayload? consumedAttachment;
|
||||
int cleanupStaleTempFilesCalls = 0;
|
||||
@@ -129,6 +136,7 @@ void main() {
|
||||
authNotifier = TestAuthNotifier(ref, _authState(isAuthenticated: true));
|
||||
return authNotifier;
|
||||
}),
|
||||
assetServiceProvider.overrideWithValue(FakeAssetService()),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -195,9 +203,9 @@ void main() {
|
||||
|
||||
testWidgets('onAppResumed handles attachment immediately when authenticated', (tester) async {
|
||||
viewIntentService.consumedAttachment = payload;
|
||||
when(() => resolver.resolve(payload)).thenAnswer(
|
||||
(_) async => ViewIntentResolvedAsset(asset: deepLinkAsset, timelineService: deepLinkTimelineService),
|
||||
);
|
||||
when(
|
||||
() => resolver.resolve(payload),
|
||||
).thenAnswer((_) async => ViewIntentResolvedAsset(asset: deepLinkAsset, timelineService: deepLinkTimelineService));
|
||||
|
||||
unawaited(handler.onAppResumed());
|
||||
await tester.pump();
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
|
||||
import '../../utils.dart';
|
||||
|
||||
class RemoteAssetFactory {
|
||||
const RemoteAssetFactory();
|
||||
|
||||
static RemoteAsset create({String? id, String? name, String? ownerId, bool isFavorite = false}) {
|
||||
id = TestUtils.uuid(id);
|
||||
|
||||
return RemoteAsset(
|
||||
id: id,
|
||||
name: name ?? 'remote_$id.jpg',
|
||||
ownerId: TestUtils.uuid(ownerId),
|
||||
checksum: 'checksum-$id',
|
||||
type: .image,
|
||||
createdAt: TestUtils.yesterday(),
|
||||
updatedAt: TestUtils.now(),
|
||||
isFavorite: isFavorite,
|
||||
isEdited: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -23,4 +23,23 @@ class UserFactory {
|
||||
avatarColor: avatarColor ?? .primary,
|
||||
);
|
||||
}
|
||||
|
||||
static UserDto createDto({
|
||||
String? id,
|
||||
String? name,
|
||||
String? email,
|
||||
DateTime? profileChangedAt,
|
||||
bool? hasProfileImage,
|
||||
AvatarColor? avatarColor,
|
||||
}) {
|
||||
id = TestUtils.uuid(id);
|
||||
return UserDto(
|
||||
id: id,
|
||||
name: name ?? 'user_$id',
|
||||
email: email ?? '$id@test.com',
|
||||
profileChangedAt: TestUtils.date(profileChangedAt),
|
||||
hasProfileImage: hasProfileImage ?? false,
|
||||
avatarColor: avatarColor ?? .primary,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+97
-28
@@ -1,24 +1,15 @@
|
||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:mocktail/mocktail.dart' as mocktail;
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:mocktail/mocktail.dart' as mock;
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
import '../domain/service.mock.dart';
|
||||
import '../infrastructure/repository.mock.dart';
|
||||
|
||||
void _registerFallbacks() {
|
||||
mocktail.registerFallbackValue(LocalAlbum(id: '', name: '', updatedAt: DateTime.now()));
|
||||
mocktail.registerFallbackValue(
|
||||
LocalAsset(
|
||||
id: '',
|
||||
name: '',
|
||||
type: AssetType.image,
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
playbackStyle: AssetPlaybackStyle.image,
|
||||
isEdited: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
import 'factories/local_album_factory.dart';
|
||||
import 'factories/local_asset_factory.dart';
|
||||
import 'factories/user_factory.dart';
|
||||
|
||||
class RepositoryMocks {
|
||||
final localAlbum = MockLocalAlbumRepository();
|
||||
@@ -28,25 +19,103 @@ class RepositoryMocks {
|
||||
final nativeApi = MockNativeSyncApi();
|
||||
|
||||
RepositoryMocks() {
|
||||
_registerFallbacks();
|
||||
resetAll();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
mocktail.reset(localAlbum);
|
||||
mocktail.reset(localAsset);
|
||||
mocktail.reset(trashedAsset);
|
||||
mocktail.reset(nativeApi);
|
||||
void resetAll() {
|
||||
_registerFallbacks();
|
||||
reset(localAlbum);
|
||||
reset(localAsset);
|
||||
reset(trashedAsset);
|
||||
reset(nativeApi);
|
||||
}
|
||||
}
|
||||
|
||||
class ServiceMocks {
|
||||
final partner = MockPartnerService();
|
||||
final PartnerStub partner = PartnerStub(MockPartnerService());
|
||||
final UserStub user = UserStub(MockUserService());
|
||||
|
||||
ServiceMocks() {
|
||||
_registerFallbacks();
|
||||
resetAll();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
mocktail.reset(partner);
|
||||
void resetAll() {
|
||||
_registerFallbacks();
|
||||
partner.reset();
|
||||
user.reset();
|
||||
_stubUserService();
|
||||
_stubPartnerService();
|
||||
}
|
||||
|
||||
void _stubUserService() {
|
||||
when(user.getMyUser).thenReturn(UserFactory.createDto());
|
||||
when(user.tryGetMyUser).thenReturn(null);
|
||||
when(user.watchMyUser).thenAnswer((_) => const Stream.empty());
|
||||
when(user.refreshMyUser).thenAnswer((_) async => null);
|
||||
when(user.createProfileImage).thenAnswer((_) async => null);
|
||||
}
|
||||
|
||||
void _stubPartnerService() {
|
||||
registerFallbackValue(PartnerDirection.sharedBy);
|
||||
when(partner.getCandidates).thenAnswer((_) => const Stream.empty());
|
||||
when(partner.search).thenAnswer((_) => const Stream.empty());
|
||||
when(partner.update).thenAnswer((_) async {});
|
||||
when(partner.create).thenAnswer((_) async {});
|
||||
when(partner.delete).thenAnswer((_) async {});
|
||||
}
|
||||
}
|
||||
|
||||
void _registerFallbacks() {
|
||||
registerFallbackValue(LocalAlbumFactory.create());
|
||||
registerFallbackValue(LocalAssetFactory.create());
|
||||
registerFallbackValue(Uint8List(0));
|
||||
}
|
||||
|
||||
extension type const Stub<T extends Mock>(T mockedService) {
|
||||
void reset() => mock.reset(mockedService);
|
||||
}
|
||||
|
||||
extension type const PartnerStub(MockPartnerService service) implements Stub<MockPartnerService> {
|
||||
Stream<Iterable<User>> Function() get getCandidates =>
|
||||
() => service.getCandidates(any());
|
||||
|
||||
Stream<Iterable<Partner>> Function() get search =>
|
||||
() => service.search(any(), any());
|
||||
|
||||
Future<void> Function() get create =>
|
||||
() => service.create(
|
||||
sharedById: any(named: 'sharedById'),
|
||||
sharedWithId: any(named: 'sharedWithId'),
|
||||
inTimeline: any(named: 'inTimeline'),
|
||||
);
|
||||
|
||||
Future<void> Function() get update =>
|
||||
() => service.update(
|
||||
sharedById: any(named: 'sharedById'),
|
||||
sharedWithId: any(named: 'sharedWithId'),
|
||||
inTimeline: any(named: 'inTimeline'),
|
||||
);
|
||||
|
||||
Future<void> Function() get delete =>
|
||||
() => service.delete(
|
||||
sharedById: any(named: 'sharedById'),
|
||||
sharedWithId: any(named: 'sharedWithId'),
|
||||
);
|
||||
}
|
||||
|
||||
extension type const UserStub(MockUserService service) implements Stub<MockUserService> {
|
||||
UserDto Function() get getMyUser =>
|
||||
() => service.getMyUser();
|
||||
|
||||
UserDto? Function() get tryGetMyUser =>
|
||||
() => service.tryGetMyUser();
|
||||
|
||||
Stream<UserDto?> Function() get watchMyUser =>
|
||||
() => service.watchMyUser();
|
||||
|
||||
Future<UserDto?> Function() get refreshMyUser =>
|
||||
() => service.refreshMyUser();
|
||||
|
||||
Future<String?> Function() get createProfileImage =>
|
||||
() => service.createProfileImage(any(), any());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/presentation/actions/partner.action.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
import '../../factories/user_factory.dart';
|
||||
import '../../mocks.dart';
|
||||
import '../../presentation_context.dart';
|
||||
|
||||
void main() {
|
||||
late PresentationContext context;
|
||||
late UserDto currentUser;
|
||||
final mocks = ServiceMocks();
|
||||
|
||||
setUp(() async {
|
||||
currentUser = UserFactory.createDto();
|
||||
context = await PresentationContext.create();
|
||||
when(mocks.user.tryGetMyUser).thenReturn(currentUser);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
mocks.resetAll();
|
||||
await context.dispose();
|
||||
});
|
||||
|
||||
List<Override> overrides({List<User> candidates = const []}) => [
|
||||
currentUserProvider.overrideWith((ref) => CurrentUserProvider(mocks.user.service)),
|
||||
partnerServiceProvider.overrideWithValue(mocks.partner.service),
|
||||
candidatesStateProvider.overrideWith((ref) => Stream<Iterable<User>>.value(candidates)),
|
||||
];
|
||||
|
||||
group('PartnerAddAction', () {
|
||||
testWidgets('creates a partner for the selected candidate', (tester) async {
|
||||
final candidate = UserFactory.create();
|
||||
|
||||
await tester.pumpTestAction(const PartnerAddAction(), overrides: overrides(candidates: [candidate]));
|
||||
await tester.pumpUntilFound(find.text(candidate.name));
|
||||
await tester.tap(find.text(candidate.name));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
verify(() => mocks.partner.service.create(sharedById: currentUser.id, sharedWithId: candidate.id)).called(1);
|
||||
});
|
||||
|
||||
testWidgets('creates nothing when the selection dialog is dismissed', (tester) async {
|
||||
await tester.pumpTestAction(const PartnerAddAction(), overrides: overrides(candidates: [UserFactory.create()]));
|
||||
await tester.sendKeyEvent(LogicalKeyboardKey.escape); // dismiss without selecting
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
verifyNever(mocks.partner.create);
|
||||
});
|
||||
});
|
||||
|
||||
group('PartnerRemoveAction', () {
|
||||
testWidgets('deletes the partner after confirmation', (tester) async {
|
||||
final partner = UserFactory.create();
|
||||
await tester.pumpTestAction(
|
||||
PartnerRemoveAction(sharedWithId: partner.id, partnerName: partner.name),
|
||||
overrides: overrides(),
|
||||
);
|
||||
await tester.tap(find.byType(TextButton).last); // confirm
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
verify(() => mocks.partner.service.delete(sharedById: currentUser.id, sharedWithId: partner.id)).called(1);
|
||||
});
|
||||
|
||||
testWidgets('deletes nothing when the confirmation is cancelled', (tester) async {
|
||||
final partner = UserFactory.create();
|
||||
await tester.pumpTestAction(
|
||||
PartnerRemoveAction(sharedWithId: partner.id, partnerName: partner.name),
|
||||
overrides: overrides(),
|
||||
);
|
||||
await tester.tap(find.byType(TextButton).first); // cancel
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
verifyNever(mocks.partner.delete);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/pages/library/partner/partner.page.dart';
|
||||
import 'package:immich_mobile/presentation/actions/partner.action.dart';
|
||||
|
||||
import '../factories/partner_user_factory.dart';
|
||||
import '../factories/user_factory.dart';
|
||||
@@ -16,16 +17,18 @@ void main() {
|
||||
|
||||
group('PartnerSharedByList', () {
|
||||
testWidgets('shows the empty-state add button when there are no partners', (tester) async {
|
||||
await tester.pumpTestWidget(PartnerSharedByList(partners: const [], onAdd: () {}, onRemove: (_) {}));
|
||||
final action = const PartnerAddAction();
|
||||
|
||||
await tester.pumpTestWidget(const PartnerSharedByList(partners: []), overrides: context.overrides);
|
||||
|
||||
expect(find.byType(ListView), findsNothing);
|
||||
expect(find.widgetWithIcon(ElevatedButton, Icons.person_add), findsOneWidget);
|
||||
expect(find.widgetWithIcon(TextButton, action.icon), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('renders a tile per partner with name and email', (tester) async {
|
||||
final partner1 = PartnerFactory.create();
|
||||
final partner2 = PartnerFactory.create();
|
||||
await tester.pumpTestWidget(PartnerSharedByList(partners: [partner1, partner2], onAdd: () {}, onRemove: (_) {}));
|
||||
await tester.pumpTestWidget(PartnerSharedByList(partners: [partner1, partner2]), overrides: context.overrides);
|
||||
|
||||
expect(find.byType(ListTile), findsNWidgets(2));
|
||||
expect(find.text(partner1.name), findsOneWidget);
|
||||
@@ -34,18 +37,12 @@ void main() {
|
||||
expect(find.text(partner2.email), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('invokes onRemovePartner with the tapped partner', (tester) async {
|
||||
testWidgets('renders a remove action for each partner', (tester) async {
|
||||
final partner1 = PartnerFactory.create(inTimeline: true);
|
||||
final partner2 = PartnerFactory.create();
|
||||
Partner? removed;
|
||||
await tester.pumpTestWidget(
|
||||
PartnerSharedByList(partners: [partner1, partner2], onAdd: () {}, onRemove: (p) => removed = p),
|
||||
);
|
||||
|
||||
await tester.tap(find.byIcon(Icons.person_remove).first);
|
||||
await tester.pump();
|
||||
|
||||
expect(removed, partner1);
|
||||
final action = const PartnerRemoveAction(sharedWithId: '', partnerName: '');
|
||||
await tester.pumpTestWidget(PartnerSharedByList(partners: [partner1, partner2]), overrides: context.overrides);
|
||||
expect(find.byIcon(action.icon), findsNWidgets(2));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -65,6 +62,7 @@ void main() {
|
||||
}
|
||||
|
||||
List<Override> withCandidates(List<User> candidates) => [
|
||||
...context.overrides,
|
||||
candidatesStateProvider.overrideWith((ref) => Stream<Iterable<User>>.value(candidates)),
|
||||
];
|
||||
|
||||
|
||||
@@ -6,20 +6,35 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/locales.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||
import 'package:immich_mobile/generated/codegen_loader.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/store.repository.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.widget.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_ui/immich_ui.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
import '../test_utils.dart';
|
||||
import 'factories/user_factory.dart';
|
||||
import 'mocks.dart';
|
||||
|
||||
class PresentationContext {
|
||||
const PresentationContext._();
|
||||
PresentationContext._({required UserDto user}) : currentUser = user, mocks = ServiceMocks() {
|
||||
when(mocks.user.tryGetMyUser).thenReturn(currentUser);
|
||||
}
|
||||
|
||||
static const String serverEndpoint = 'http://localhost:3000';
|
||||
|
||||
static Drift? _db;
|
||||
|
||||
final UserDto currentUser;
|
||||
final ServiceMocks mocks;
|
||||
|
||||
List<Override> get overrides => [currentUserProvider.overrideWith((ref) => CurrentUserProvider(mocks.user.service))];
|
||||
|
||||
static Future<PresentationContext> create() async {
|
||||
TestUtils.init();
|
||||
if (_db == null) {
|
||||
@@ -28,7 +43,7 @@ class PresentationContext {
|
||||
await StoreService.I.put(StoreKey.serverEndpoint, serverEndpoint);
|
||||
_db = db;
|
||||
}
|
||||
return const PresentationContext._();
|
||||
return PresentationContext._(user: UserFactory.createDto());
|
||||
}
|
||||
|
||||
Future<void> dispose() async {
|
||||
@@ -54,6 +69,7 @@ extension PumpPresentationWidget on WidgetTester {
|
||||
child: Builder(
|
||||
builder: (context) => MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
scaffoldMessengerKey: scaffoldMessengerKey,
|
||||
localizationsDelegates: context.localizationDelegates,
|
||||
supportedLocales: context.supportedLocales,
|
||||
locale: context.locale,
|
||||
@@ -65,4 +81,23 @@ extension PumpPresentationWidget on WidgetTester {
|
||||
);
|
||||
await pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> pumpTestAction(BaseAction action, {List<Override> overrides = const []}) async {
|
||||
await pumpTestWidget(
|
||||
Scaffold(body: ActionIconButtonWidget(action: action)),
|
||||
overrides: overrides,
|
||||
);
|
||||
await tap(find.byType(ImmichIconButton));
|
||||
await pump();
|
||||
}
|
||||
|
||||
Future<void> pumpUntilFound(Finder finder, {int maxFrames = 10}) async {
|
||||
for (var i = 0; i < maxFrames; i++) {
|
||||
await pump();
|
||||
if (finder.evaluate().isNotEmpty) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw StateError('pumpUntilFound: $finder not found within $maxFrames frames');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ void main() {
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
mocks.reset();
|
||||
mocks.resetAll();
|
||||
});
|
||||
|
||||
group('HashService', () {
|
||||
|
||||
@@ -17012,12 +17012,12 @@
|
||||
},
|
||||
"assetId": {
|
||||
"description": "Existing asset ID if duplicate",
|
||||
"format": "uuid",
|
||||
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "Asset ID",
|
||||
"format": "uuid",
|
||||
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
|
||||
"description": "Client-side identifier echoed from the request to match results to inputs",
|
||||
"type": "string"
|
||||
},
|
||||
"isTrashed": {
|
||||
|
||||
@@ -278,7 +278,9 @@
|
||||
"title": "Album IDs",
|
||||
"array": true,
|
||||
"description": "Target album IDs",
|
||||
"uiHint": "AlbumId"
|
||||
"uiHint": {
|
||||
"type": "AlbumId"
|
||||
}
|
||||
},
|
||||
"albumName": {
|
||||
"type": "string",
|
||||
@@ -368,14 +370,20 @@
|
||||
"type": "string",
|
||||
"title": "Album ID",
|
||||
"description": "Target album ID",
|
||||
"uiHint": "AlbumId"
|
||||
"uiHint": {
|
||||
"type": "AlbumId",
|
||||
"order": 1
|
||||
}
|
||||
},
|
||||
"albumIds": {
|
||||
"type": "string",
|
||||
"title": "Album IDs",
|
||||
"description": "Target album IDs",
|
||||
"array": true,
|
||||
"uiHint": "AlbumId"
|
||||
"uiHint": {
|
||||
"type": "AlbumId",
|
||||
"order": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"@types/node": "^24.13.2",
|
||||
"esbuild": "^0.28.0",
|
||||
"tsc-alias": "^1.8.16",
|
||||
"typescript": "^5.9.3"
|
||||
"typescript": "^6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@extism/js-pdk": "^1.1.1"
|
||||
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
} from 'src/types.js';
|
||||
|
||||
export const wrapper = <
|
||||
T extends WorkflowType = WorkflowType,
|
||||
T extends WorkflowType,
|
||||
TConfig extends ConfigValue = ConfigValue,
|
||||
>(
|
||||
fn: (
|
||||
|
||||
@@ -11,7 +11,7 @@ type DeepPartial<T> = T extends Date
|
||||
export type WorkflowEventMap = {
|
||||
[WorkflowType.AssetV1]: AssetV1;
|
||||
// [WorkflowType.AssetPersonV1]: AssetPersonV1;
|
||||
};
|
||||
} & { [K in WorkflowType]: unknown };
|
||||
|
||||
export type WorkflowEventData<T extends WorkflowType> = WorkflowEventMap[T];
|
||||
|
||||
@@ -22,7 +22,7 @@ export enum WorkflowTrigger {
|
||||
}
|
||||
|
||||
export type WorkflowEventPayload<
|
||||
T extends WorkflowType = WorkflowType,
|
||||
T extends WorkflowType,
|
||||
TConfig = WorkflowStepConfig,
|
||||
> = {
|
||||
trigger: WorkflowTrigger;
|
||||
@@ -37,10 +37,11 @@ export type WorkflowEventPayload<
|
||||
};
|
||||
};
|
||||
|
||||
export type WorkflowChanges<T extends WorkflowType = WorkflowType> =
|
||||
DeepPartial<WorkflowEventData<T>>;
|
||||
export type WorkflowChanges<T extends WorkflowType> = DeepPartial<
|
||||
WorkflowEventData<T>
|
||||
>;
|
||||
|
||||
export type WorkflowResponse<T extends WorkflowType = WorkflowType> = {
|
||||
export type WorkflowResponse<T extends WorkflowType> = {
|
||||
workflow?: {
|
||||
/** stop the workflow */
|
||||
continue?: boolean;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"sourceMap": false,
|
||||
"strict": true,
|
||||
"target": "esnext",
|
||||
"typeRoots": ["./node_modules/@types", "./node_modules"],
|
||||
"types": ["node", "@extism/js-pdk"],
|
||||
"verbatimModuleSyntax": true
|
||||
}
|
||||
|
||||
@@ -707,7 +707,7 @@ export type AssetBulkUploadCheckResult = {
|
||||
action: AssetUploadAction;
|
||||
/** Existing asset ID if duplicate */
|
||||
assetId?: string;
|
||||
/** Asset ID */
|
||||
/** Client-side identifier echoed from the request to match results to inputs */
|
||||
id: string;
|
||||
/** Whether existing asset is trashed */
|
||||
isTrashed?: boolean;
|
||||
|
||||
Generated
+2
-2
@@ -353,8 +353,8 @@ importers:
|
||||
specifier: ^1.8.16
|
||||
version: 1.8.17
|
||||
typescript:
|
||||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
specifier: ^6.0.0
|
||||
version: 6.0.3
|
||||
|
||||
packages/sdk:
|
||||
dependencies:
|
||||
|
||||
@@ -34,10 +34,10 @@ const AssetRejectReasonSchema = z
|
||||
|
||||
const AssetBulkUploadCheckResultSchema = z
|
||||
.object({
|
||||
id: z.uuidv4().describe('Asset ID'),
|
||||
id: z.string().describe('Client-side identifier echoed from the request to match results to inputs'),
|
||||
action: AssetUploadActionSchema,
|
||||
reason: AssetRejectReasonSchema.optional(),
|
||||
assetId: z.string().optional().describe('Existing asset ID if duplicate'),
|
||||
assetId: z.uuidv4().optional().describe('Existing asset ID if duplicate'),
|
||||
isTrashed: z.boolean().optional().describe('Whether existing asset is trashed'),
|
||||
})
|
||||
.meta({ id: 'AssetBulkUploadCheckResult' });
|
||||
|
||||
@@ -14,7 +14,12 @@ const JsonSchemaPropertySchema = z
|
||||
enum: z.array(z.string()).optional().describe('Valid choices for enum types'),
|
||||
array: z.boolean().optional().describe('Type is an array type'),
|
||||
required: z.array(z.string()).optional().describe('A list of required properties'),
|
||||
uiHint: z.string().optional(),
|
||||
uiHint: z
|
||||
.object({
|
||||
type: z.string().optional(),
|
||||
order: z.int().optional(),
|
||||
})
|
||||
.optional(),
|
||||
get properties() {
|
||||
return z.record(z.string(), JsonSchemaPropertySchema).optional();
|
||||
},
|
||||
|
||||
@@ -369,7 +369,7 @@ export class WorkflowExecutionService extends BaseService {
|
||||
const readResult = await read(type);
|
||||
let data = readResult.data;
|
||||
for (const step of workflow.steps) {
|
||||
const payload: WorkflowEventPayload = {
|
||||
const payload: WorkflowEventPayload<typeof type> = {
|
||||
trigger: workflow.trigger,
|
||||
type,
|
||||
config: step.config ?? {},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user