Compare commits

...

2 Commits

Author SHA1 Message Date
shenlong
a887595a40 feat: typed translation generator (#24693)
* feat: typed translation generator

* replace legacy key usage with new generated keys

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-12-20 21:03:19 -06:00
shenlong-tanwen
e1f5f3b939 chore: remove unused key and fix casing for recent_albums 2025-12-19 04:28:44 +05:30
59 changed files with 406 additions and 167 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -1485,7 +1485,6 @@
"not_available": "N/A",
"not_in_any_album": "En cap àlbum",
"not_selected": "No seleccionat",
"note_apply_storage_label_to_previously_uploaded assets": "Nota: per aplicar l'etiqueta d'emmagatzematge als actius penjats anteriorment, executeu el",
"notes": "Notes",
"nothing_here_yet": "No hi ha res encara",
"notification_permission_dialog_content": "Per activar les notificacions, aneu a Configuració i seleccioneu permet.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {S'ha reassignat # recurs} other {S'han reassignat # recursos}} a una persona nova",
"reassing_hint": "Assignar els elements seleccionats a una persona existent",
"recent": "Recent",
"recent-albums": "Àlbums recents",
"recent_albums": "Àlbums recents",
"recent_searches": "Cerques recents",
"recently_added": "Afegit recentment",
"recently_added_page_title": "Afegit recentment",

View File

@@ -1485,7 +1485,6 @@
"not_available": "Není k dispozici",
"not_in_any_album": "Bez alba",
"not_selected": "Není vybráno",
"note_apply_storage_label_to_previously_uploaded assets": "Upozornění: Chcete-li použít štítek úložiště na dříve nahrané položky, spusťte příkaz",
"notes": "Poznámky",
"nothing_here_yet": "Zatím zde nic není",
"notification_permission_dialog_content": "Chcete-li povolit oznámení, přejděte do nastavení a vyberte možnost povolit.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {Přeřazena # položka} few {Přeřazeny # položky} other {Přeřazeno # položek}} na novou osobu",
"reassing_hint": "Přiřazení vybraných položek existující osobě",
"recent": "Nedávné",
"recent-albums": "Nedávná alba",
"recent_albums": "Nedávná alba",
"recent_searches": "Nedávná vyhledávání",
"recently_added": "Nedávno přidané",
"recently_added_page_title": "Nedávno přidané",

View File

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

View File

@@ -1485,7 +1485,6 @@
"not_available": "N/A",
"not_in_any_album": "In keinem Album",
"not_selected": "Nicht ausgewählt",
"note_apply_storage_label_to_previously_uploaded assets": "Hinweis: Um eine Speicherpfadbezeichnung anzuwenden, starte den",
"notes": "Notizen",
"nothing_here_yet": "Noch nichts hier",
"notification_permission_dialog_content": "Um Benachrichtigungen zu aktivieren, navigiere zu Einstellungen und klicke \"Erlauben\".",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# Datei wurde} other {# Dateien wurden}} einer neuen Person zugewiesen",
"reassing_hint": "Markierte Dateien einer vorhandenen Person zuweisen",
"recent": "Neuste",
"recent-albums": "Neuste Alben",
"recent_albums": "Neuste Alben",
"recent_searches": "Letzte Suchen",
"recently_added": "Kürzlich hinzugefügt",
"recently_added_page_title": "Zuletzt hinzugefügt",

View File

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

View File

@@ -1485,7 +1485,6 @@
"not_available": "N/A",
"not_in_any_album": "Not in any album",
"not_selected": "Not selected",
"note_apply_storage_label_to_previously_uploaded assets": "Note: To apply the Storage Label to previously uploaded assets, run the",
"notes": "Notes",
"nothing_here_yet": "Nothing here yet",
"notification_permission_dialog_content": "To enable notifications, go to Settings and select allow.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "Re-assigned {count, plural, one {# asset} other {# assets}} to a new person",
"reassing_hint": "Assign selected assets to an existing person",
"recent": "Recent",
"recent-albums": "Recent albums",
"recent_albums": "Recent albums",
"recent_searches": "Recent searches",
"recently_added": "Recently added",
"recently_added_page_title": "Recently Added",

View File

@@ -1485,7 +1485,6 @@
"not_available": "N/D",
"not_in_any_album": "Sin álbum",
"not_selected": "No seleccionado",
"note_apply_storage_label_to_previously_uploaded assets": "Nota: Para aplicar la etiqueta de almacenamiento a los archivos que ya se subieron, ejecute la",
"notes": "Notas",
"nothing_here_yet": "Sin nada aún",
"notification_permission_dialog_content": "Para activar las notificaciones, ve a Configuración y selecciona permitir.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "Reasignado {count, plural, one {# elemento} other {# elementos}} a un nuevo usuario",
"reassing_hint": "Asignar archivos seleccionados a una persona existente",
"recent": "Reciente",
"recent-albums": "Últimos álbumes",
"recent_albums": "Últimos álbumes",
"recent_searches": "Búsquedas recientes",
"recently_added": "Añadidos recientemente",
"recently_added_page_title": "Recién añadidos",

View File

@@ -1485,7 +1485,6 @@
"not_available": "Pole saadaval",
"not_in_any_album": "Pole üheski albumis",
"not_selected": "Ei ole valitud",
"note_apply_storage_label_to_previously_uploaded assets": "Märkus: Et rakendada talletussilt varem üleslaaditud üksustele, käivita",
"notes": "Märkused",
"nothing_here_yet": "Siin pole veel midagi",
"notification_permission_dialog_content": "Teavituste lubamiseks mine Seadetesse ja vali lubamine.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# üksus} other {# üksust}} seostatud uue isikuga",
"reassing_hint": "Seosta valitud üksused olemasoleva isikuga",
"recent": "Hiljutine",
"recent-albums": "Hiljutised albumid",
"recent_albums": "Hiljutised albumid",
"recent_searches": "Hiljutised otsingud",
"recently_added": "Hiljuti lisatud",
"recently_added_page_title": "Hiljuti lisatud",

View File

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

View File

@@ -1485,7 +1485,6 @@
"not_available": "N/A",
"not_in_any_album": "Dans aucun album",
"not_selected": "Non sélectionné",
"note_apply_storage_label_to_previously_uploaded assets": "Note : Pour appliquer l'étiquette de stockage aux médias précédemment envoyés, exécutez",
"notes": "Notes",
"nothing_here_yet": "Rien pour le moment",
"notification_permission_dialog_content": "Pour activer les notifications, allez dans Paramètres et sélectionnez Autoriser.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# média réattribué} other {# médias réattribués}} à une nouvelle personne",
"reassing_hint": "Attribuer ces médias à une personne existante",
"recent": "Récent",
"recent-albums": "Albums récents",
"recent_albums": "Albums récents",
"recent_searches": "Recherches récentes",
"recently_added": "Récemment ajouté",
"recently_added_page_title": "Récemment ajouté",

View File

@@ -1485,7 +1485,6 @@
"not_available": "N/B",
"not_in_any_album": "Ní in aon albam",
"not_selected": "Níor roghnaíodh",
"note_apply_storage_label_to_previously_uploaded assets": "Nóta: Chun an Lipéad Stórála a chur i bhfeidhm ar shócmhainní a uaslódáileadh roimhe seo, rith an",
"notes": "Nótaí",
"nothing_here_yet": "Níl aon rud anseo fós",
"notification_permission_dialog_content": "Chun fógraí a chumasú, téigh go Socruithe agus roghnaigh ceadaigh.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "Athshannadh {count, plural, one {# sócmhainn} other {# sócmhainní}} do dhuine nua",
"reassing_hint": "Sannadh sócmhainní roghnaithe do dhuine atá ann cheana féin",
"recent": "Le déanaí",
"recent-albums": "Albaim le déanaí",
"recent_albums": "Albaim le déanaí",
"recent_searches": "Cuardaigh le déanaí",
"recently_added": "Cuireadh leis le déanaí",
"recently_added_page_title": "Curtha leis le Déanaí",

View File

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

View File

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

View File

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

View File

@@ -1464,7 +1464,6 @@
"not_available": "लागू नहीं",
"not_in_any_album": "किसी एलबम में नहीं",
"not_selected": "चयनित नहीं",
"note_apply_storage_label_to_previously_uploaded assets": "नोट: पहले अपलोड की गई संपत्तियों पर स्टोरेज लेबल लागू करने के लिए, चलाएँ",
"notes": "टिप्पणियाँ",
"nothing_here_yet": "यहाँ अभी तक कुछ नहीं",
"notification_permission_dialog_content": "सूचनाएं सक्षम करने के लिए सेटिंग्स में जाएं और अनुमति दें चुनें।",
@@ -1659,7 +1658,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# asset} other {# assets}} को एक नए व्यक्ति को फिर से असाइन किया गया",
"reassing_hint": "चयनित संपत्तियों को किसी मौजूदा व्यक्ति को सौंपें",
"recent": "हाल ही का",
"recent-albums": "हाल के एल्बम",
"recent_albums": "हाल के एल्बम",
"recent_searches": "हाल की खोजें",
"recently_added": "हाल ही में डाला गया",
"recently_added_page_title": "हाल ही में डाला गया",

View File

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

View File

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

View File

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

View File

@@ -1485,7 +1485,6 @@
"not_available": "N/A",
"not_in_any_album": "In nessun album",
"not_selected": "Non selezionato",
"note_apply_storage_label_to_previously_uploaded assets": "Nota: Per aggiungere l'etichetta dell'archiviazione agli asset caricati in precedenza, esegui",
"notes": "Note",
"nothing_here_yet": "Ancora nulla qui",
"notification_permission_dialog_content": "Per attivare le notifiche, vai alle Impostazioni e seleziona concedi.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {Riassegnato # asset} other {Riassegnati # assets}} ad una nuova persona",
"reassing_hint": "Assegna gli assets selezionati ad una persona esistente",
"recent": "Recenti",
"recent-albums": "Album recenti",
"recent_albums": "Album recenti",
"recent_searches": "Ricerche recenti",
"recently_added": "Aggiunti recentemente",
"recently_added_page_title": "Aggiunti di recente",

View File

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

View File

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

View File

@@ -1399,7 +1399,6 @@
"not_available": "Nepasiekiamas",
"not_in_any_album": "Nė viename albume",
"not_selected": "Nepasirinkta",
"note_apply_storage_label_to_previously_uploaded assets": "Pastaba: Priskirti Saugyklos Žymą prie anksčiau įkeltų ištekliu, paleiskite šį",
"notes": "Pastabos",
"nothing_here_yet": "Kol kas tuščia",
"notification_permission_dialog_content": "Pranešimų įgalinimui eikite į Nustatymus ir pasirinkite Leisti.",
@@ -1575,7 +1574,7 @@
"rating_description": "Rodyti EXIF įvertinimus informacijos skydelyje",
"read_changelog": "Skaityti pakeitimų sąrašą",
"ready_for_upload": "Paruošta įkėlimui",
"recent-albums": "Naujausi albumai",
"recent_albums": "Naujausi albumai",
"recent_searches": "Naujausios paieškos",
"recently_added": "Neseniai pridėta",
"recently_added_page_title": "Neseniai pridėta",

View File

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

View File

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

View File

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

View File

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

View File

@@ -1485,7 +1485,6 @@
"not_available": "n.v.t.",
"not_in_any_album": "Niet in een album",
"not_selected": "Niet geselecteerd",
"note_apply_storage_label_to_previously_uploaded assets": "Opmerking: om het opslaglabel toe te passen op eerder geüploade items, voer de volgende taak uit",
"notes": "Opmerkingen",
"nothing_here_yet": "Hier staan nog geen items",
"notification_permission_dialog_content": "Om meldingen in te schakelen, ga naar Instellingen en selecteer toestaan.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# item} other {# items}} opnieuw toegewezen aan een nieuw persoon",
"reassing_hint": "Geselecteerde items toewijzen aan een bestaand persoon",
"recent": "Recent",
"recent-albums": "Recente albums",
"recent_albums": "Recente albums",
"recent_searches": "Recente zoekopdrachten",
"recently_added": "Onlangs toegevoegd",
"recently_added_page_title": "Recent toegevoegd",

View File

@@ -1485,7 +1485,6 @@
"not_available": "Nie dotyczy",
"not_in_any_album": "Bez albumu",
"not_selected": "Nie wybrano",
"note_apply_storage_label_to_previously_uploaded assets": "Uwaga: Aby przypisać etykietę magazynowania do wcześniej przesłanych zasobów, uruchom",
"notes": "Uwagi",
"nothing_here_yet": "Nic tu jeszcze nie ma",
"notification_permission_dialog_content": "Aby włączyć powiadomienia, przejdź do Ustawień i wybierz opcję Zezwalaj.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "Przypisano ponownie {count, plural, one {# zasób} other {# zasobów}} do nowej osoby",
"reassing_hint": "Przypisz wybrane zasoby do istniejącej osoby",
"recent": "Ostatnie",
"recent-albums": "Ostatnie albumy",
"recent_albums": "Ostatnie albumy",
"recent_searches": "Ostatnie wyszukiwania",
"recently_added": "Ostatnio dodane",
"recently_added_page_title": "Ostatnio Dodane",

View File

@@ -1485,7 +1485,6 @@
"not_available": "N/A",
"not_in_any_album": "Não está em nenhum álbum",
"not_selected": "Não selecionado",
"note_apply_storage_label_to_previously_uploaded assets": "Nota: Para aplicar o Rótulo de Armazenamento a ficheiros carregados anteriormente, execute o",
"notes": "Notas",
"nothing_here_yet": "Ainda não existe nada aqui",
"notification_permission_dialog_content": "Para ativar as notificações, vá em Configurações e selecione permitir.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "Reatribuído {count, plural, one {# ficheiro} other {# ficheiros}} a uma nova pessoa",
"reassing_hint": "Atribuir ficheiros selecionados a uma pessoa existente",
"recent": "Recentes",
"recent-albums": "Álbuns recentes",
"recent_albums": "Álbuns recentes",
"recent_searches": "Pesquisas recentes",
"recently_added": "Adicionados Recentemente",
"recently_added_page_title": "Adicionado recentemente",

View File

@@ -1485,7 +1485,6 @@
"not_available": "N/A",
"not_in_any_album": "Fora de álbum",
"not_selected": "Não selecionado",
"note_apply_storage_label_to_previously_uploaded assets": "Nota: Para aplicar o rótulo de armazenamento a arquivos enviados anteriormente, execute o",
"notes": "Notas",
"nothing_here_yet": "Ainda não existe nada aqui",
"notification_permission_dialog_content": "Para ativar as notificações, vá em Configurações e selecione permitir.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# arquivo reatribuído} other {# arquivos reatribuídos}} a uma nova pessoa",
"reassing_hint": "Atribuir arquivos selecionados a uma pessoa existente",
"recent": "Recente",
"recent-albums": "Álbuns recentes",
"recent_albums": "Álbuns recentes",
"recent_searches": "Pesquisas recentes",
"recently_added": "Adicionado recentemente",
"recently_added_page_title": "Adicionados recentemente",

View File

@@ -1477,7 +1477,6 @@
"not_available": "N/A",
"not_in_any_album": "Nu există în niciun album",
"not_selected": "Neselectat",
"note_apply_storage_label_to_previously_uploaded assets": "Notă: Pentru a aplica eticheta de stocare la resursele încărcate anterior, rulați",
"notes": "Note",
"nothing_here_yet": "Nimic aici încă",
"notification_permission_dialog_content": "Pentru a activa notificările, mergi în Setări > Immich și selectează permite.",
@@ -1673,7 +1672,7 @@
"reassigned_assets_to_new_person": "Re-alocat {count, plural, one {# resursă} other {# resurse}} unei noi persoane",
"reassing_hint": "Atribuiți resursele selectate unei persoane existente",
"recent": "Recent",
"recent-albums": "Albume recente",
"recent_albums": "Albume recente",
"recent_searches": "Căutări recente",
"recently_added": "Adăugate recent",
"recently_added_page_title": "Adăugate recent",

View File

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

View File

@@ -1485,7 +1485,6 @@
"not_available": "Nedostupné",
"not_in_any_album": "Nie je v žiadnom albume",
"not_selected": "Nevybrané",
"note_apply_storage_label_to_previously_uploaded assets": "Poznámka: Ak chcete použiť Štítok úložiska na predtým nahrané médiá, spustite príkaz",
"notes": "Poznámky",
"nothing_here_yet": "Zatiaľ tu nič nie je",
"notification_permission_dialog_content": "Ak chcete povoliť upozornenia, prejdite do Nastavenia a vyberte možnosť Povoliť.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "Opätovne {count, plural, one {priradená # položka} few {priradené # položky} other {priradených # položiek}} novej osobe",
"reassing_hint": "Priradí zvolenú položku k existujúcej osobe",
"recent": "Nedávne",
"recent-albums": "Posledné albumy",
"recent_albums": "Posledné albumy",
"recent_searches": "Posledné vyhľadávania",
"recently_added": "Nedávno pridané",
"recently_added_page_title": "Nedávno pridané",

View File

@@ -1485,7 +1485,6 @@
"not_available": "Ni na voljo",
"not_in_any_album": "Ni v nobenem albumu",
"not_selected": "Ni izbrano",
"note_apply_storage_label_to_previously_uploaded assets": "Opomba: Če želite oznako za shranjevanje uporabiti za predhodno naložena sredstva, zaženite",
"notes": "Opombe",
"nothing_here_yet": "Tukaj še ni ničesar",
"notification_permission_dialog_content": "Če želite omogočiti obvestila, pojdite v Nastavitve in izberite Dovoli.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "Ponovno dodeljeno {count, plural, one {# sredstvo} two {# sredstvi} few {# sredstva} other {# sredstev}} za novo osebo",
"reassing_hint": "Dodeli izbrana sredstva obstoječi osebi",
"recent": "Nedavno",
"recent-albums": "Zadnji albumi",
"recent_albums": "Zadnji albumi",
"recent_searches": "Nedavna iskanja",
"recently_added": "Nedavno dodano",
"recently_added_page_title": "Nedavno dodano",

View File

@@ -1283,7 +1283,6 @@
"not_available": "Недоступно",
"not_in_any_album": "Нема ни у једном албуму",
"not_selected": "Није изабрано",
"note_apply_storage_label_to_previously_uploaded assets": "Напомена: Да бисте применили ознаку за складиштење на претходно уплоадиране датотеке, покрените",
"notes": "Напомене",
"notification_permission_dialog_content": "Да би укљуцили нотификације, идите у Опције и одаберите Дозволи.",
"notification_permission_list_tile_content": "Дајте дозволу за омогућавање обавештења.",
@@ -1451,7 +1450,7 @@
"reassigned_assets_to_new_person": "Поново додељено {count, plural, one {# датотека} other {# датотеке}} новој особи",
"reassing_hint": "Доделите изабрана средства постојећој особи",
"recent": "Скорашњи",
"recent-albums": "Недавни албуми",
"recent_albums": "Недавни албуми",
"recent_searches": "Скорашње претраге",
"recently_added": "Недавно додато",
"recently_added_page_title": "Недавно Додато",

View File

@@ -1232,7 +1232,6 @@
"no_shared_albums_message": "Napravite album da biste delili fotografije i video zapise sa ljudima u vašoj mreži",
"not_in_any_album": "Nema ni u jednom albumu",
"not_selected": "Nije izabrano",
"note_apply_storage_label_to_previously_uploaded assets": "Napomena: Da biste primenili oznaku za skladištenje na prethodno uploadirane datoteke, pokrenite",
"notes": "Napomene",
"notification_permission_dialog_content": "Da bi ukljucili notifikacije, idite u Opcije i odaberite Dozvoli.",
"notification_permission_list_tile_content": "Dajte dozvolu za omogućavanje obaveštenja.",
@@ -1390,7 +1389,7 @@
"reassigned_assets_to_new_person": "Ponovo dodeljeno {count, plural, one {# datoteka} other {# datoteke}} novoj osobi",
"reassing_hint": "Dodelite izabrana sredstva postojećoj osobi",
"recent": "Skorašnji",
"recent-albums": "Nedavni albumi",
"recent_albums": "Nedavni albumi",
"recent_searches": "Skorašnje pretrage",
"recently_added": "Nedavno dodato",
"recently_added_page_title": "Nedavno Dodato",

View File

@@ -1485,7 +1485,6 @@
"not_available": "N/A",
"not_in_any_album": "Inte i något album",
"not_selected": "Ej vald",
"note_apply_storage_label_to_previously_uploaded assets": "Obs: Om du vill använda lagringsetiketten på tidigare uppladdade tillgångar kör du",
"notes": "Notera",
"nothing_here_yet": "Inget här ännu",
"notification_permission_dialog_content": "För att aktivera notiser, gå till Inställningar och välj tillåt.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "Tilldelade om {count, plural, one {# objekt} other {# objekt}} till en ny persson",
"reassing_hint": "Tilldela valda tillgångar till en befintlig person",
"recent": "Nyligen",
"recent-albums": "Senaste album",
"recent_albums": "Senaste album",
"recent_searches": "Senaste sökningar",
"recently_added": "Nyligen tillagda",
"recently_added_page_title": "Nyligen tillagda",

View File

@@ -1474,7 +1474,6 @@
"not_available": "இதற்கில்லை",
"not_in_any_album": "எந்த ஆல்பத்திலும் இல்லை",
"not_selected": "தேர்ந்தெடுக்கப்படவில்லை",
"note_apply_storage_label_to_previously_uploaded assets": "குறிப்பு: முன்னர் பதிவேற்றப்பட்ட சொத்துக்களுக்கு சேமிப்பக லேபிளை பயன்படுத்த, இயக்கவும்",
"notes": "குறிப்புகள்",
"nothing_here_yet": "இன்னும் இங்கே எதுவும் இல்லை",
"notification_permission_dialog_content": "அறிவிப்புகளை இயக்க, அமைப்புகளுக்குச் சென்று இசைவு என்பதைத் தேர்ந்தெடுக்கவும்.",
@@ -1670,7 +1669,7 @@
"reassigned_assets_to_new_person": "புதிய நபருக்கு {count, plural, one {# சொத்து} other {# சொத்துகள்}} மீண்டும் ஒதுக்கப்பட்டது",
"reassing_hint": "தேர்ந்தெடுக்கப்பட்ட சொத்துக்களை ஏற்கனவே இருக்கும் நபருக்கு ஒதுக்குங்கள்",
"recent": "அண்மைக் கால",
"recent-albums": "அண்மைக் கால ஆல்பங்கள்",
"recent_albums": "அண்மைக் கால ஆல்பங்கள்",
"recent_searches": "அண்மைக் கால தேடல்கள்",
"recently_added": "அண்மைக் காலத்தில் சேர்க்கப்பட்டது",
"recently_added_page_title": "அண்மைக் காலத்தில் சேர்க்கப்பட்டது",

View File

@@ -898,7 +898,6 @@
"no_results_description": "పర్యాయపదం లేదా మరింత సాధారణ కీవర్డ్‌ని ప్రయత్నించండి",
"no_shared_albums_message": "మీ నెట్‌వర్క్‌లోని వ్యక్తులతో ఫోటోలు మరియు వీడియోలను భాగస్వామ్యం చేయడానికి ఆల్బమ్‌ను సృష్టించండి",
"not_in_any_album": "ఏ ఆల్బమ్‌లోనూ లేదు",
"note_apply_storage_label_to_previously_uploaded assets": "గమనిక: గతంలో అప్‌లోడ్ చేసిన ఆస్తులకు నిల్వ లేబుల్‌ను వర్తింపజేయడానికి,",
"notes": "గమనికలు",
"notification_toggle_setting_description": "ఇమెయిల్ నోటిఫికేషన్‌లను ప్రారంభించండి",
"notifications": "నోటిఫికేషన్‌లు",
@@ -1024,7 +1023,7 @@
"reassign": "తిరిగి కేటాయించు",
"reassing_hint": "ఎంచుకున్న ఆస్తులను ఇప్పటికే ఉన్న వ్యక్తికి కేటాయించండి",
"recent": "ఇటీవలి",
"recent-albums": "ఇటీవలి ఆల్బమ్‌లు",
"recent_albums": "ఇటీవలి ఆల్బమ్‌లు",
"recent_searches": "ఇటీవలి శోధనలు",
"refresh": "రిఫ్రెష్ చేయి",
"refresh_encoded_videos": "ఎన్‌కోడ్ చేసిన వీడియోలను రిఫ్రెష్ చేయండి",

View File

@@ -1289,7 +1289,6 @@
"no_results_description": "ลองใช้คำพ้องหรือคำหลักที่กว้างกว่านี้",
"no_shared_albums_message": "สร้างอัลบั้มเพื่อแชร์รูปภาพและวิดีโอกับคนในเครือข่ายของคุณ",
"not_in_any_album": "ไม่อยู่ในอัลบั้มใด ๆ",
"note_apply_storage_label_to_previously_uploaded assets": "หมายเหตุ: หากต้องการใช้ป้ายกำกับพื้นที่เก็บข้อมูลกับเนื้อหาที่อัปโหลดก่อนหน้านี้ ให้เรียกใช้",
"notes": "หมายเหตุ",
"notification_permission_dialog_content": "เพื่อเปิดการแจ้งเตือน เข้าตั้งค่าแล้วกดอนุญาต",
"notification_permission_list_tile_content": "อนุญาตการแจ้งเตือน",
@@ -1443,7 +1442,7 @@
"reassigned_assets_to_new_person": "มอบหมาย {count, plural, one {# สื่อ} other {# สื่อ}} ให้กับบุคคลใหม่",
"reassing_hint": "มอบหมายสื่อที่เลือกให้กับบุคคลที่มีอยู่แล้ว",
"recent": "ล่าสุด",
"recent-albums": "อัลบั้มล่าสุด",
"recent_albums": "อัลบั้มล่าสุด",
"recent_searches": "การค้นหาล่าสุด",
"recently_added_page_title": "เพิ่มล่าสุด",
"refresh": "รีเฟรช",

View File

@@ -1485,7 +1485,6 @@
"not_available": "YOK",
"not_in_any_album": "Hiçbir albümde değil",
"not_selected": "Seçilmedi",
"note_apply_storage_label_to_previously_uploaded assets": "Not: Daha önce yüklenen öğeler için bir depolama yolu etiketi uygulamak üzere şunu başlatın",
"notes": "Notlar",
"nothing_here_yet": "Burada henüz bir şey yok",
"notification_permission_dialog_content": "Bildirimleri etkinleştirmek için cihaz ayarlarına gidin ve izin verin.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "{count, plural, one {# öğe} other {# öğeler}} yeni bir kişiye atandı",
"reassing_hint": "Seçili öğeleri mevcut bir kişiye atayın",
"recent": "Son",
"recent-albums": "Son kaydedilen albümler",
"recent_albums": "Son kaydedilen albümler",
"recent_searches": "Son aramalar",
"recently_added": "Son eklenenler",
"recently_added_page_title": "Son Eklenenler",

View File

@@ -1485,7 +1485,6 @@
"not_available": "Немає даних",
"not_in_any_album": "У жодному альбомі",
"not_selected": "Не вибрано",
"note_apply_storage_label_to_previously_uploaded assets": "Примітка: Щоб застосувати мітку сховища до раніше завантажених ресурсів, виконайте команду",
"notes": "Нотатки",
"nothing_here_yet": "Тут ще нічого немає",
"notification_permission_dialog_content": "Щоб увімкнути сповіщення, перейдіть до Налаштувань і надайте дозвіл.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "Перепризначено {count, plural, one {# ресурс} other {# ресурси}} новій особі",
"reassing_hint": "Призначити обрані ресурси існуючій особі",
"recent": "Нещодавно",
"recent-albums": "Останні альбоми",
"recent_albums": "Останні альбоми",
"recent_searches": "Нещодавні пошукові запити",
"recently_added": "Нещодавно додані",
"recently_added_page_title": "Нещодавні",

View File

@@ -1485,7 +1485,6 @@
"not_available": "Thiếu",
"not_in_any_album": "Không thuộc album nào",
"not_selected": "Không được chọn",
"note_apply_storage_label_to_previously_uploaded assets": "Lưu ý: Để áp dụng Nhãn lưu trữ cho các ảnh đã tải lên trước đó, hãy chạy",
"notes": "Lưu ý",
"nothing_here_yet": "Chưa có nội dung nào",
"notification_permission_dialog_content": "Để bật thông báo, chuyển tới Cài đặt và chọn cho phép.",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "Đã gán lại {count, plural, one {# ảnh} other {# ảnh}} cho một người mới",
"reassing_hint": "Gán các ảnh đã chọn cho một người hiện có",
"recent": "Gần đây",
"recent-albums": "Album gần đây",
"recent_albums": "Album gần đây",
"recent_searches": "Tìm kiếm gần đây",
"recently_added": "Thêm gần đây",
"recently_added_page_title": "Mới thêm gần đây",

View File

@@ -1485,7 +1485,6 @@
"not_available": "不適用",
"not_in_any_album": "不在任何相簿中",
"not_selected": "未選擇",
"note_apply_storage_label_to_previously_uploaded assets": "*註:執行套用儲存標籤前先上傳項目",
"notes": "提示",
"nothing_here_yet": "暫無訊息",
"notification_permission_dialog_content": "開啟通知,請前往「設定」,並選擇「允許」。",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "已將 {count, plural, other {# 個檔案}}重新指定給一位新人物",
"reassing_hint": "將選定的檔案分配給己存在的人物",
"recent": "最近",
"recent-albums": "最近相簿",
"recent_albums": "最近相簿",
"recent_searches": "最近搜尋項目",
"recently_added": "近期新增",
"recently_added_page_title": "最近新增",

View File

@@ -1485,7 +1485,6 @@
"not_available": "不适用",
"not_in_any_album": "不在任何相册中",
"not_selected": "未选择",
"note_apply_storage_label_to_previously_uploaded assets": "提示:要将存储标签应用于之前上传的项目,需要运行",
"notes": "提示",
"nothing_here_yet": "这里什么都没有",
"notification_permission_dialog_content": "要启用通知,请转到“设置”,并选择“允许”。",
@@ -1681,7 +1680,7 @@
"reassigned_assets_to_new_person": "重新指派{count, plural, one {#个项目} other {#个项目}}到新的人物",
"reassing_hint": "指派选择的项目到已存在的人物",
"recent": "最近",
"recent-albums": "最近的相册",
"recent_albums": "最近的相册",
"recent_searches": "最近搜索",
"recently_added": "近期添加",
"recently_added_page_title": "最近添加",

View File

@@ -3,7 +3,99 @@
import 'dart:convert';
import 'dart:io';
const _kReservedWords = ['continue'];
const _kReservedWords = [
'abstract',
'as',
'assert',
'async',
'await',
'break',
'case',
'catch',
'class',
'const',
'continue',
'covariant',
'default',
'deferred',
'do',
'dynamic',
'else',
'enum',
'export',
'extends',
'extension',
'external',
'factory',
'false',
'final',
'finally',
'for',
'Function',
'get',
'hide',
'if',
'implements',
'import',
'in',
'interface',
'is',
'late',
'library',
'mixin',
'new',
'null',
'on',
'operator',
'part',
'required',
'rethrow',
'return',
'sealed',
'set',
'show',
'static',
'super',
'switch',
'sync',
'this',
'throw',
'true',
'try',
'typedef',
'var',
'void',
'when',
'while',
'with',
'yield',
];
const _kIntParamNames = [
'count',
'number',
'amount',
'total',
'index',
'size',
'length',
'width',
'height',
'year',
'month',
'day',
'hour',
'minute',
'second',
'page',
'limit',
'offset',
'max',
'min',
'id',
'num',
'quantity',
];
void main() async {
final sourceFile = File('../i18n/en.json');
@@ -15,49 +107,258 @@ void main() async {
final outputDir = Directory('lib/generated');
await outputDir.create(recursive: true);
final outputFile = File('lib/generated/intl_keys.g.dart');
await _generate(sourceFile, outputFile);
final content = await sourceFile.readAsString();
final translations = json.decode(content) as Map<String, dynamic>;
final outputFile = File('lib/generated/translations.g.dart');
await _generateTranslations(translations, outputFile);
print('Generated ${outputFile.path}');
}
Future<void> _generate(File source, File output) async {
final content = await source.readAsString();
final translations = json.decode(content) as Map<String, dynamic>;
class TranslationNode {
final String key;
final String? value;
final Map<String, TranslationNode> children;
final List<TranslationParam> params;
const TranslationNode({
required this.key,
this.value,
Map<String, TranslationNode>? children,
List<TranslationParam>? params,
}) : children = children ?? const {},
params = params ?? const [];
bool get isLeaf => value != null;
bool get hasParams => params.isNotEmpty;
}
class TranslationParam {
final String name;
final String type;
const TranslationParam(this.name, this.type);
}
Future<void> _generateTranslations(Map<String, dynamic> translations, File output) async {
final root = _buildTranslationTree('', translations);
final buffer = StringBuffer('''
// DO NOT EDIT. This is code generated via generate_keys.dart
abstract class IntlKeys {
''');
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/widgets.dart';
import 'package:intl/message_format.dart';
_writeKeys(buffer, translations);
buffer.writeln('}');
await output.writeAsString(buffer.toString());
extension TranslationsExtension on BuildContext {
Translations get t => Translations.of(this);
}
void _writeKeys(
StringBuffer buffer,
Map<String, dynamic> map, [
String prefix = '',
]) {
for (final entry in map.entries) {
final key = entry.key;
final value = entry.value;
class StaticTranslations {
StaticTranslations._();
static final instance = Translations._(null);
}
if (value is Map<String, dynamic>) {
_writeKeys(buffer, value, prefix.isEmpty ? key : '${prefix}_$key');
} else {
final name = _cleanName(prefix.isEmpty ? key : '${prefix}_$key');
final path = prefix.isEmpty ? key : '$prefix.$key'.replaceAll('_', '.');
buffer.writeln(' static const $name = \'$path\';');
abstract class _BaseTranslations {
BuildContext? get _context;
String _t(String key, [Map<String, Object>? args]) {
if (key.isEmpty) return '';
try {
final translated = key.tr(context: _context);
return args != null
? MessageFormat(translated, locale: Intl.defaultLocale ?? 'en').format(args)
: translated;
} catch (e) {
return key;
}
}
}
String _cleanName(String name) {
name = name.replaceAll(RegExp(r'[^a-zA-Z0-9_]'), '_');
if (RegExp(r'^[0-9]').hasMatch(name)) name = 'k_$name';
if (_kReservedWords.contains(name)) name = '${name}_';
class Translations extends _BaseTranslations {
@override
final BuildContext? _context;
Translations._(this._context);
static Translations of(BuildContext context) {
context.locale;
return Translations._(context);
}
''');
_generateClassMembers(buffer, root, ' ');
buffer.writeln('}');
_generateNestedClasses(buffer, root);
await output.writeAsString(buffer.toString());
}
TranslationNode _buildTranslationTree(String key, dynamic value) {
if (value is Map<String, dynamic>) {
final children = <String, TranslationNode>{};
for (final entry in value.entries) {
children[entry.key] = _buildTranslationTree(entry.key, entry.value);
}
return TranslationNode(key: key, children: children);
} else {
final stringValue = value.toString();
final params = _extractParams(stringValue);
return TranslationNode(key: key, value: stringValue, params: params);
}
}
List<TranslationParam> _extractParams(String value) {
final params = <String, TranslationParam>{};
final icuRegex = RegExp(r'\{(\w+),\s*(plural|select|number|date|time)([^}]*(?:\{[^}]*\}[^}]*)*)\}');
for (final match in icuRegex.allMatches(value)) {
final name = match.group(1)!;
final icuType = match.group(2)!;
final icuContent = match.group(3) ?? '';
if (params.containsKey(name)) continue;
String type;
if (icuType == 'plural' || icuType == 'number') {
type = 'int';
} else if (icuType == 'select') {
final hasTrueFalse = RegExp(r',\s*(true|false)\s*\{').hasMatch(icuContent);
type = hasTrueFalse ? 'bool' : 'String';
} else {
type = 'String';
}
params[name] = TranslationParam(name, type);
}
var cleanedValue = value;
var depth = 0;
var icuStart = -1;
for (var i = 0; i < value.length; i++) {
if (value[i] == '{') {
if (depth == 0) icuStart = i;
depth++;
} else if (value[i] == '}') {
depth--;
if (depth == 0 && icuStart >= 0) {
final block = value.substring(icuStart, i + 1);
if (RegExp(r'^\{\w+,').hasMatch(block)) {
cleanedValue = cleanedValue.replaceFirst(block, '');
}
icuStart = -1;
}
}
}
final simpleRegex = RegExp(r'\{(\w+)\}');
for (final match in simpleRegex.allMatches(cleanedValue)) {
final name = match.group(1)!;
if (params.containsKey(name)) continue;
String type;
if (_kIntParamNames.contains(name.toLowerCase())) {
type = 'int';
} else {
type = 'Object';
}
params[name] = TranslationParam(name, type);
}
return params.values.toList();
}
void _generateClassMembers(StringBuffer buffer, TranslationNode node, String indent, [String keyPrefix = '']) {
final sortedKeys = node.children.keys.toList()..sort();
for (final childKey in sortedKeys) {
final child = node.children[childKey]!;
final dartName = _escapeName(childKey);
final fullKey = keyPrefix.isEmpty ? childKey : '$keyPrefix.$childKey';
if (child.isLeaf) {
if (child.hasParams) {
_generateMethod(buffer, dartName, fullKey, child.params, indent);
} else {
_generateGetter(buffer, dartName, fullKey, indent);
}
} else {
final className = _toNestedClassName(keyPrefix, childKey);
buffer.writeln('${indent}late final $dartName = $className._(_context);');
}
}
}
void _generateGetter(StringBuffer buffer, String dartName, String translationKey, String indent) {
buffer.writeln('${indent}String get $dartName => _t(\'$translationKey\');');
}
void _generateMethod(
StringBuffer buffer,
String dartName,
String translationKey,
List<TranslationParam> params,
String indent,
) {
final paramList = params.map((p) => 'required ${p.type} ${_escapeName(p.name)}').join(', ');
final argsMap = params.map((p) => '\'${p.name}\': ${_escapeName(p.name)}').join(', ');
buffer.writeln('${indent}String $dartName({$paramList}) => _t(\'$translationKey\', {$argsMap});');
}
void _generateNestedClasses(StringBuffer buffer, TranslationNode node, [String keyPrefix = '']) {
final sortedKeys = node.children.keys.toList()..sort();
for (final childKey in sortedKeys) {
final child = node.children[childKey]!;
final fullKey = keyPrefix.isEmpty ? childKey : '$keyPrefix.$childKey';
if (!child.isLeaf && child.children.isNotEmpty) {
final className = _toNestedClassName(keyPrefix, childKey);
buffer.writeln();
buffer.writeln('class $className extends _BaseTranslations {');
buffer.writeln(' @override');
buffer.writeln(' final BuildContext? _context;');
buffer.writeln(' $className._(this._context);');
_generateClassMembers(buffer, child, ' ', fullKey);
buffer.writeln('}');
_generateNestedClasses(buffer, child, fullKey);
}
}
}
String _toNestedClassName(String prefix, String key) {
final parts = <String>[];
if (prefix.isNotEmpty) {
parts.addAll(prefix.split('.'));
}
parts.add(key);
final result = StringBuffer('_');
for (final part in parts) {
final words = part.split('_');
for (final word in words) {
if (word.isNotEmpty) {
result.write(word[0].toUpperCase());
if (word.length > 1) {
result.write(word.substring(1).toLowerCase());
}
}
}
}
result.write('Translations');
return result.toString();
}
String _escapeName(String name) {
if (_kReservedWords.contains(name)) {
return '$name\$';
}
if (RegExp(r'^[0-9]').hasMatch(name)) {
return 'k$name';
}
return name;
}

View File

@@ -16,9 +16,8 @@ import 'package:immich_mobile/constants/locales.dart';
import 'package:immich_mobile/domain/services/background_worker.service.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/generated/codegen_loader.g.dart';
import 'package:immich_mobile/generated/intl_keys.g.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/platform/background_worker_lock_api.g.dart';
import 'package:immich_mobile/providers/app_life_cycle.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.provider.dart';
@@ -217,8 +216,8 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
ref
.read(backgroundWorkerFgServiceProvider)
.saveNotificationMessage(
IntlKeys.uploading_media.t(),
IntlKeys.backup_background_service_default_notification.t(),
StaticTranslations.instance.uploading_media,
StaticTranslations.instance.backup_background_service_default_notification,
);
}
} else {

View File

@@ -10,7 +10,7 @@ import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/generated/intl_keys.g.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/backup/backup_toggle_button.widget.dart';
import 'package:immich_mobile/providers/background_sync.provider.dart';
import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
@@ -153,7 +153,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
Icon(Icons.warning_rounded, color: context.colorScheme.error, fill: 1),
const SizedBox(width: 8),
Text(
IntlKeys.backup_error_sync_failed.t(),
context.t.backup_error_sync_failed,
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.error),
textAlign: TextAlign.center,
),

View File

@@ -7,7 +7,7 @@ import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/generated/intl_keys.g.dart';
import 'package:immich_mobile/generated/translations.g.dart';
class SettingsHeader {
String key = "";
@@ -61,7 +61,7 @@ class HeaderSettingsPage extends HookConsumerWidget {
return Scaffold(
appBar: AppBar(
title: const Text(IntlKeys.headers_settings_tile_title).tr(),
title: Text(context.t.headers_settings_tile_title),
centerTitle: false,
actions: [
IconButton(

View File

@@ -5,7 +5,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/generated/intl_keys.g.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/providers/album/album.provider.dart';
import 'package:immich_mobile/providers/partner.provider.dart';
import 'package:immich_mobile/providers/search/people.provider.dart';
@@ -41,13 +41,13 @@ class LibraryPage extends ConsumerWidget {
ActionButton(
onPressed: () => context.pushRoute(const FavoritesRoute()),
icon: Icons.favorite_outline_rounded,
label: IntlKeys.favorites.tr(),
label: context.t.favorites,
),
const SizedBox(width: 8),
ActionButton(
onPressed: () => context.pushRoute(const ArchiveRoute()),
icon: Icons.archive_outlined,
label: IntlKeys.archived.tr(),
label: context.t.archived,
),
],
),
@@ -58,14 +58,14 @@ class LibraryPage extends ConsumerWidget {
ActionButton(
onPressed: () => context.pushRoute(const SharedLinkRoute()),
icon: Icons.link_outlined,
label: IntlKeys.shared_links.tr(),
label: context.t.shared_links,
),
SizedBox(width: trashEnabled ? 8 : 0),
trashEnabled
? ActionButton(
onPressed: () => context.pushRoute(const TrashRoute()),
icon: Icons.delete_outline_rounded,
label: IntlKeys.trash.tr(),
label: context.t.trash,
)
: const SizedBox.shrink(),
],
@@ -120,26 +120,20 @@ class QuickAccessButtons extends ConsumerWidget {
),
),
leading: const Icon(Icons.folder_outlined, size: 26),
title: Text(
IntlKeys.folders.tr(),
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500),
),
title: Text(context.t.folders, style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500)),
onTap: () => context.pushRoute(FolderRoute()),
),
ListTile(
leading: const Icon(Icons.lock_outline_rounded, size: 26),
title: Text(
IntlKeys.locked_folder.tr(),
context.t.locked_folder,
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500),
),
onTap: () => context.pushRoute(const LockedRoute()),
),
ListTile(
leading: const Icon(Icons.group_outlined, size: 26),
title: Text(
IntlKeys.partners.tr(),
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500),
),
title: Text(context.t.partners, style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500)),
onTap: () => context.pushRoute(const PartnerRoute()),
),
PartnerList(partners: partners),
@@ -235,7 +229,7 @@ class PeopleCollectionCard extends ConsumerWidget {
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
IntlKeys.people.tr(),
context.t.people,
style: context.textTheme.titleSmall?.copyWith(
color: context.colorScheme.onSurface,
fontWeight: FontWeight.w500,
@@ -295,7 +289,7 @@ class LocalAlbumsCollectionCard extends HookConsumerWidget {
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
IntlKeys.on_this_device.tr(),
context.t.on_this_device,
style: context.textTheme.titleSmall?.copyWith(
color: context.colorScheme.onSurface,
fontWeight: FontWeight.w500,
@@ -346,7 +340,7 @@ class PlacesCollectionCard extends StatelessWidget {
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
IntlKeys.places.tr(),
context.t.places,
style: context.textTheme.titleSmall?.copyWith(
color: context.colorScheme.onSurface,
fontWeight: FontWeight.w500,

View File

@@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/trash_bottom_sheet.widget.dart';
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
@@ -43,9 +44,7 @@ class DriftTrashPage extends StatelessWidget {
return SliverPadding(
padding: const EdgeInsets.all(16.0),
sliver: SliverToBoxAdapter(
child: const Text("trash_page_info").t(context: context, args: {"days": "$trashDays"}),
),
sliver: SliverToBoxAdapter(child: Text(context.t.trash_page_info(days: trashDays))),
);
},
),

View File

@@ -1,9 +1,8 @@
import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/generated/intl_keys.g.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/routing/router.dart';
class CustomProxyHeaderSettings extends StatelessWidget {
@@ -15,11 +14,11 @@ class CustomProxyHeaderSettings extends StatelessWidget {
contentPadding: const EdgeInsets.symmetric(horizontal: 20),
dense: true,
title: Text(
IntlKeys.advanced_settings_proxy_headers_title.tr(),
context.t.advanced_settings_proxy_headers_title,
style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500),
),
subtitle: Text(
IntlKeys.advanced_settings_proxy_headers_subtitle.tr(),
context.t.advanced_settings_proxy_headers_subtitle,
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary),
),
onTap: () => context.pushRoute(const HeaderSettingsRoute()),

View File

@@ -37,7 +37,7 @@ translation:
dart run easy_localization:generate -S ../i18n
dart run bin/generate_keys.dart
dart format lib/generated/codegen_loader.g.dart
dart format lib/generated/intl_keys.g.dart
dart format lib/generated/translations.g.dart
analyze:
dart analyze --fatal-infos

View File

@@ -32,13 +32,7 @@ depends = [
[tasks."codegen:translation"]
alias = "translation"
description = "Generate translations from i18n JSONs"
run = [
{ task = "//i18n:format-fix" },
{ tasks = [
"i18n:loader",
"i18n:keys",
] },
]
run = [{ task = "//i18n:format-fix" }, { tasks = ["i18n:loader", "i18n:keys"] }]
[tasks."codegen:app-icon"]
description = "Generate app icons"
@@ -158,10 +152,10 @@ run = [
description = "Generate i18n keys"
hide = true
sources = ["i18n/en.json"]
outputs = "lib/generated/intl_keys.g.dart"
outputs = "lib/generated/translations.g.dart"
run = [
"dart run bin/generate_keys.dart",
"dart format lib/generated/intl_keys.g.dart",
"dart format lib/generated/translations.g.dart",
]
[tasks."analyze:dart"]

View File

@@ -37,7 +37,7 @@
<span class="hidden md:block absolute start-1 h-full">
<button
type="button"
aria-label={$t('recent-albums')}
aria-label={$t('recent_albums')}
class="relative flex cursor-default pt-4 pb-4 select-none justify-center hover:cursor-pointer hover:bg-subtle hover:fill-gray hover:text-immich-primary dark:text-immich-dark-fg dark:hover:bg-immich-dark-gray dark:hover:text-immich-dark-primary rounded h-fill"
onclick={() => (dropdownOpen = !dropdownOpen)}
>