diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-08-25 11:46:17 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-08-25 11:46:17 +0200 |
| commit | 2fcdd07d1e5d331ad02b723f1c45603a0989c264 (patch) | |
| tree | f606f01f5492648824876efe4c8a431d9b3a59d6 /packages/meshbay-hub/src/meshbay_hub/static/locales | |
| parent | d427118bd91d67f1a041e5daf267aebcd34ca9d7 (diff) | |
| download | meshbay-2fcdd07d1e5d331ad02b723f1c45603a0989c264.tar.gz | |
feat: add Photos group app
A new group application (docs/apps.md's plug-in mechanism), following the
plan in docs/photos.md. Unlike Videos/Music: several photo roots per group
instead of one (photo_roots is a set, one signed op replaces it whole),
a single album-grid view with no third-party matching step, and per-photo
info read from the file's own EXIF at index time — no metadata service,
no credential, no outbound network call at all.
Protocol (meshbay-common, MNP 0.10 -> 0.11, additive): `taken_at`/`camera`
on IndexEntry; `photo_roots`/`photo_roots_ack`; `OP_PHOTO_ROOTS`.
Node: roster.py stores photo_roots as a group_settings entry (JSON list,
same shape as enabled_apps); ops.py/webrtc_server.py validate and sign the
whole set in one op, same pattern as apps_enabled; a new PhotoEnricher
(indexer/enrich_photo.py) runs Pillow in its own small bounded pool,
separate from the video/audio pools, producing a resized thumbnail plus
the two EXIF fields — never GPS, checked by a grep-based regression test.
Client: photos-app.js — one album card per directory containing images,
a per-album photo grid, and a lightbox with next/previous (keyboard and
buttons), zoom in/out/fit/100% starting from the actual on-screen fit
percentage, and a "zip this album" button reusing files-app.js's own zip
mechanism (lifted into file-utils.js's downloadDirectory so both call the
same implementation). group-settings.js gets an add/remove multi-root
picker, distinct from Videos/Music's single-value one.
Bugs found and fixed before this ever shipped, worth keeping the story of:
- enrich_photo.py read width/height from the raw image *before* applying
EXIF orientation correction, and read DateTimeOriginal off the plain
0th-IFD Exif object — a real camera stores it in the Exif sub-IFD, which
Pillow only exposes via get_ifd(Exif). A flat, hand-built EXIF dict
round-trips through Pillow either way, which is exactly what would have
hidden both bugs; the regression test builds EXIF with piexif instead,
matching what real hardware produces.
- photos-app.js's album grouping stripped a trailing path segment from
entry.path under the assumption it still carried a filename — it
doesn't (files-app.js's own convention: e.path is already the
containing directory), so every album collapsed one level into its
parent. Found live against a real multi-folder library.
- transport.js's ADMIN_OP_TYPES allowlist (already the fix for an
identical bug on video_root/apps_enabled, see 4783d81) was missing
photo_roots: its admin_challenge matched no pending request and was
silently dropped, so saving a photo root just timed out after 30s with
no error.
- daemon.py pruned a thumbnail when its file left the index (root removed
or reconfigured) but never forgot the content hash was "already
attempted" — the same bytes reappearing under a renamed/relocated root
(an operator's real workflow) were then permanently skipped, forever,
with nothing to indicate why. Discarding the attempt alongside the
cache entry on prune is what makes pruning actually reversible.
- packages/meshbay-client's app:// protocol handler served every file
with no Cache-Control header, so Chromium was free to serve a stale
cached copy indefinitely — none of several `npm run sync-ui` + reload
cycles during development actually picked up the new code until the
renderer's disk cache was cleared by hand. Now sends Cache-Control:
no-store.
- the lightbox's zoomed image used flex centering (align-items/
justify-content: center) combined with overflow: auto — a well-known
trap where the browser centers overflowing content by shifting it, and
the leading half of that overflow (here, the top of a zoomed photo)
sits outside what the scrollport can actually reach. Reported live as
"unusable". Fixed by switching to top/left alignment once zoomed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TiZG4AuSnxHohQMpwTHTyL
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/locales')
10 files changed, 272 insertions, 10 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js index 83b5c1f..1e367fb 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js @@ -78,6 +78,7 @@ export default { 'group.tab_chat': 'Chat', 'group.tab_video': 'Videos', 'group.tab_music': 'Musik', + 'group.tab_photos': 'Fotos', 'group.tab_members': 'Mitglieder', 'group.tab_settings': "Einstellungen", 'members.danger_leave_hint': "Sie verlieren den Zugriff auf die Dateien und den Chat dieser Gruppe.", @@ -205,6 +206,24 @@ export default { 'music.player_queue': 'Aktuelle Wiedergabeliste', 'music.queue_title': 'Wird wiedergegeben', + // Photos + 'photo.empty': 'Keine Fotos gefunden.', + 'photo.no_roots_configured': 'Für diese Gruppe sind noch keine Fotos-Stammordner festgelegt — ein Operator kann welche in den Einstellungen auswählen.', + 'photo.root_album': '(oberste Ebene)', + 'photo.n_photos': { + one: '{n} Foto', + other: '{n} Fotos', + }, + 'photo.back': 'Zurück', + 'photo.prev': 'Vorherige (←)', + 'photo.next': 'Nächste (→)', + 'photo.zip_album': 'Album als ZIP herunterladen', + 'photo.zoom_in': 'Vergrößern', + 'photo.zoom_out': 'Verkleinern', + 'photo.zoom_fit_title': 'An Fenster anpassen', + 'photo.zoom_fit_label': 'Anpassen', + 'photo.zoom_100': 'Originalgröße (100 %)', + // LAN-Cast 'cast.start': 'Auf Gerät übertragen', 'cast.stop': 'Übertragung beenden', @@ -651,8 +670,15 @@ export default { 'settings_node.audio_root_none': '— keiner ausgewählt —', 'settings_node.audio_root_save': 'Speichern', 'settings_node.audio_root_change_confirm': 'Das Ändern des Musik-Stammordners ersetzt, was jedes Mitglied im Musik-Tab sieht. Fortfahren?', + 'settings_node.photo_roots_title': 'Fotos-Stammordner', + 'settings_node.photo_roots_hint': 'Welche Ordner die Fotos-App als Einstiegspunkte für diese Gruppe nutzt — eine Fotobibliothek ist oft auf mehrere Ordner verteilt, daher können mehrere ausgewählt werden. In Fotos wird nichts angezeigt, bis mindestens einer hinzugefügt wurde.', + 'settings_node.photo_roots_none': '— keiner ausgewählt —', + 'settings_node.photo_roots_add_placeholder': 'Ordner hinzufügen…', + 'settings_node.photo_roots_add': 'Hinzufügen', + 'settings_node.photo_roots_remove': 'Entfernen', + 'settings_node.photo_roots_save': 'Speichern', 'settings_node.directories_title': 'Verzeichnisse', - 'settings_node.directories_hint': 'Freigegebene Ordner und welchen davon die Videos- und Musik-Apps als eigenen Einstiegspunkt nutzen.', + 'settings_node.directories_hint': 'Freigegebene Ordner und welchen davon die Videos-, Musik- und Fotos-Apps als eigene(n) Einstiegspunkt(e) nutzen.', // Create-group wizard 'wizard.title': 'Gruppe erstellen', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js index 1101eb2..5aedd7a 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/en.js @@ -79,6 +79,7 @@ export default { 'group.tab_chat': 'Chat', 'group.tab_video': 'Videos', 'group.tab_music': 'Music', + 'group.tab_photos': 'Photos', 'group.tab_members': 'Members', 'group.tab_settings': "Settings", 'members.danger_leave_hint': "You will lose access to this group's files and chat.", @@ -203,6 +204,24 @@ export default { 'music.player_queue': 'Current queue', 'music.queue_title': 'Playing now', + // Photos + 'photo.empty': 'No photos found.', + 'photo.no_roots_configured': 'No Photos root folders are set for this group yet — an operator can choose some in Settings.', + 'photo.root_album': '(top level)', + 'photo.n_photos': { + one: '{n} photo', + other: '{n} photos', + }, + 'photo.back': 'Back', + 'photo.prev': 'Previous (←)', + 'photo.next': 'Next (→)', + 'photo.zip_album': 'Download album as zip', + 'photo.zoom_in': 'Zoom in', + 'photo.zoom_out': 'Zoom out', + 'photo.zoom_fit_title': 'Fit to window', + 'photo.zoom_fit_label': 'Fit', + 'photo.zoom_100': 'Actual size (100%)', + // LAN cast 'cast.start': 'Cast to device', 'cast.stop': 'Stop casting', @@ -476,8 +495,15 @@ export default { 'settings_node.audio_root_none': '— none chosen —', 'settings_node.audio_root_save': 'Save', 'settings_node.audio_root_change_confirm': 'Changing the Music root replaces what every member sees in the Music tab. Continue?', + 'settings_node.photo_roots_title': 'Photos root folders', + 'settings_node.photo_roots_hint': 'Which folder(s) the Photos app treats as entry points for this group — a photo library is often scattered across several folders, so more than one may be chosen. Nothing shows in Photos until at least one is added.', + 'settings_node.photo_roots_none': '— none chosen —', + 'settings_node.photo_roots_add_placeholder': 'Add a folder…', + 'settings_node.photo_roots_add': 'Add', + 'settings_node.photo_roots_remove': 'Remove', + 'settings_node.photo_roots_save': 'Save', 'settings_node.directories_title': 'Directories', - 'settings_node.directories_hint': 'Shared folders, and which of them the Videos and Music apps use as their own entry point.', + 'settings_node.directories_hint': 'Shared folders, and which of them the Videos, Music and Photos apps use as their own entry point(s).', // Members 'members.col_role': 'Role', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js index d9fd76f..46a4638 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/es.js @@ -76,6 +76,7 @@ export default { 'group.tab_chat': 'Chat', 'group.tab_video': 'Vídeos', 'group.tab_music': 'Música', + 'group.tab_photos': 'Fotos', 'group.tab_members': 'Miembros', 'group.tab_settings': "Ajustes", 'members.danger_leave_hint': "Perderá el acceso a los archivos y al chat de este grupo.", @@ -203,6 +204,24 @@ export default { 'music.player_queue': 'Cola actual', 'music.queue_title': 'Reproduciendo ahora', + // Photos + 'photo.empty': 'No se encontraron fotos.', + 'photo.no_roots_configured': 'Aún no se han definido carpetas raíz de Fotos para este grupo — un operador puede elegir algunas en Configuración.', + 'photo.root_album': '(nivel superior)', + 'photo.n_photos': { + one: '{n} foto', + other: '{n} fotos', + }, + 'photo.back': 'Atrás', + 'photo.prev': 'Anterior (←)', + 'photo.next': 'Siguiente (→)', + 'photo.zip_album': 'Descargar álbum como zip', + 'photo.zoom_in': 'Acercar', + 'photo.zoom_out': 'Alejar', + 'photo.zoom_fit_title': 'Ajustar a la ventana', + 'photo.zoom_fit_label': 'Ajustar', + 'photo.zoom_100': 'Tamaño real (100%)', + // LAN cast 'cast.start': 'Enviar a dispositivo', 'cast.stop': 'Detener envío', @@ -646,8 +665,15 @@ export default { 'settings_node.audio_root_none': '— ninguna elegida —', 'settings_node.audio_root_save': 'Guardar', 'settings_node.audio_root_change_confirm': 'Cambiar la raíz de Música reemplaza lo que ve cada miembro en la pestaña Música. ¿Continuar?', + 'settings_node.photo_roots_title': 'Carpetas raíz de Fotos', + 'settings_node.photo_roots_hint': 'Qué carpeta(s) trata la app Fotos como puntos de entrada para este grupo — una fototeca suele estar repartida en varias carpetas, así que se pueden elegir varias. No se muestra nada en Fotos hasta que se añada al menos una.', + 'settings_node.photo_roots_none': '— ninguna elegida —', + 'settings_node.photo_roots_add_placeholder': 'Añadir una carpeta…', + 'settings_node.photo_roots_add': 'Añadir', + 'settings_node.photo_roots_remove': 'Quitar', + 'settings_node.photo_roots_save': 'Guardar', 'settings_node.directories_title': 'Directorios', - 'settings_node.directories_hint': 'Carpetas compartidas, y cuál de ellas usan las apps de Vídeos y Música como su propio punto de entrada.', + 'settings_node.directories_hint': 'Carpetas compartidas, y cuál de ellas usan las apps de Vídeos, Música y Fotos como su(s) propio(s) punto(s) de entrada.', // Create group wizard 'wizard.title': 'Crear grupo', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js index 7e0b13f..5cd8894 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/fr.js @@ -77,6 +77,7 @@ export default { 'group.tab_chat': 'Discussion', 'group.tab_video': 'Vidéos', 'group.tab_music': 'Musique', + 'group.tab_photos': 'Photos', 'group.tab_members': 'Membres', 'group.tab_settings': "Paramètres", 'members.danger_leave_hint': "Vous perdrez l’accès aux fichiers et à la discussion de ce groupe.", @@ -204,6 +205,24 @@ export default { 'music.player_queue': 'File en cours', 'music.queue_title': 'En cours de lecture', + // Photos + 'photo.empty': 'Aucune photo trouvée.', + 'photo.no_roots_configured': "Aucun dossier racine des Photos n'est encore défini pour ce groupe — un opérateur peut en choisir dans les Paramètres.", + 'photo.root_album': '(niveau racine)', + 'photo.n_photos': { + one: '{n} photo', + other: '{n} photos', + }, + 'photo.back': 'Retour', + 'photo.prev': 'Précédent (←)', + 'photo.next': 'Suivant (→)', + 'photo.zip_album': "Télécharger l'album en zip", + 'photo.zoom_in': 'Zoomer', + 'photo.zoom_out': 'Dézoomer', + 'photo.zoom_fit_title': 'Ajuster à la fenêtre', + 'photo.zoom_fit_label': 'Ajusté', + 'photo.zoom_100': 'Taille réelle (100 %)', + // LAN cast 'cast.start': 'Diffuser sur un appareil', 'cast.stop': 'Arrêter la diffusion', @@ -662,8 +681,15 @@ export default { 'settings_node.audio_root_none': '— aucun choisi —', 'settings_node.audio_root_save': 'Enregistrer', 'settings_node.audio_root_change_confirm': 'Changer la racine de la Musique remplace ce que chaque membre voit dans l\'onglet Musique. Continuer ?', + 'settings_node.photo_roots_title': 'Dossiers racines des Photos', + 'settings_node.photo_roots_hint': 'Quel(s) dossier(s) l\'application Photos traite comme points d\'entrée pour ce groupe — une photothèque est souvent répartie sur plusieurs dossiers, donc plusieurs peuvent être choisis. Rien ne s\'affiche dans Photos tant qu\'aucun n\'est ajouté.', + 'settings_node.photo_roots_none': '— aucun choisi —', + 'settings_node.photo_roots_add_placeholder': 'Ajouter un dossier…', + 'settings_node.photo_roots_add': 'Ajouter', + 'settings_node.photo_roots_remove': 'Retirer', + 'settings_node.photo_roots_save': 'Enregistrer', 'settings_node.directories_title': 'Répertoires', - 'settings_node.directories_hint': 'Dossiers partagés, et lequel d\'entre eux les applications Vidéos et Musique utilisent comme leur propre point d\'entrée.', + 'settings_node.directories_hint': 'Dossiers partagés, et lequel d\'entre eux les applications Vidéos, Musique et Photos utilisent comme leur(s) propre(s) point(s) d\'entrée.', // Create group wizard 'wizard.title': 'Créer un groupe', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js index 7d2fada..26e4e8f 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/it.js @@ -77,6 +77,7 @@ export default { 'group.tab_chat': 'Chat', 'group.tab_video': 'Video', 'group.tab_music': 'Musica', + 'group.tab_photos': 'Foto', 'group.tab_members': 'Membri', 'group.tab_settings': "Impostazioni", 'members.danger_leave_hint': "Perderai l’accesso ai file e alla chat di questo gruppo.", @@ -204,6 +205,24 @@ export default { 'music.player_queue': 'Coda attuale', 'music.queue_title': 'In riproduzione', + // Photos + 'photo.empty': 'Nessuna foto trovata.', + 'photo.no_roots_configured': 'Per questo gruppo non sono ancora impostate cartelle radice di Foto — un operatore può sceglierne alcune nelle Impostazioni.', + 'photo.root_album': '(livello superiore)', + 'photo.n_photos': { + one: '{n} foto', + other: '{n} foto', + }, + 'photo.back': 'Indietro', + 'photo.prev': 'Precedente (←)', + 'photo.next': 'Successiva (→)', + 'photo.zip_album': "Scarica l'album come zip", + 'photo.zoom_in': 'Ingrandisci', + 'photo.zoom_out': 'Riduci', + 'photo.zoom_fit_title': 'Adatta alla finestra', + 'photo.zoom_fit_label': 'Adatta', + 'photo.zoom_100': 'Dimensione reale (100%)', + // LAN cast 'cast.start': 'Trasmetti al dispositivo', 'cast.stop': 'Interrompi trasmissione', @@ -660,8 +679,15 @@ export default { 'settings_node.audio_root_none': '— nessuna scelta —', 'settings_node.audio_root_save': 'Salva', 'settings_node.audio_root_change_confirm': 'Cambiare la radice di Musica sostituisce ciò che ogni membro vede nella scheda Musica. Continuare?', + 'settings_node.photo_roots_title': 'Cartelle radice di Foto', + 'settings_node.photo_roots_hint': "Quali cartelle l'app Foto considera come punti di ingresso per questo gruppo — una libreria fotografica è spesso distribuita su più cartelle, quindi se ne possono scegliere diverse. In Foto non viene mostrato nulla finché non ne viene aggiunta almeno una.", + 'settings_node.photo_roots_none': '— nessuna scelta —', + 'settings_node.photo_roots_add_placeholder': 'Aggiungi una cartella…', + 'settings_node.photo_roots_add': 'Aggiungi', + 'settings_node.photo_roots_remove': 'Rimuovi', + 'settings_node.photo_roots_save': 'Salva', 'settings_node.directories_title': 'Directory', - 'settings_node.directories_hint': 'Cartelle condivise, e quale di esse le app Video e Musica usano come proprio punto di ingresso.', + 'settings_node.directories_hint': 'Cartelle condivise, e quale di esse le app Video, Musica e Foto usano come proprio/i punto/i di ingresso.', // Create-group wizard 'wizard.title': 'Crea gruppo', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js index 38fb19b..903a902 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/ja.js @@ -75,6 +75,7 @@ export default { 'group.tab_chat': 'チャット', 'group.tab_video': '動画', 'group.tab_music': '音楽', + 'group.tab_photos': '写真', 'group.tab_members': 'メンバー', 'group.tab_settings': "設定", 'members.danger_leave_hint': "このグループのファイルとチャットにアクセスできなくなります。", @@ -201,6 +202,24 @@ export default { 'music.player_queue': '再生中のキュー', 'music.queue_title': '再生中', + // Photos + 'photo.empty': '写真が見つかりません。', + 'photo.no_roots_configured': 'このグループにはまだ写真のルートフォルダが設定されていません — 操作者が設定画面でいくつか選択できます。', + 'photo.root_album': '(トップレベル)', + 'photo.n_photos': { + one: '{n}枚', + other: '{n}枚', + }, + 'photo.back': '戻る', + 'photo.prev': '前へ(←)', + 'photo.next': '次へ(→)', + 'photo.zip_album': 'アルバムをzipでダウンロード', + 'photo.zoom_in': '拡大', + 'photo.zoom_out': '縮小', + 'photo.zoom_fit_title': 'ウィンドウに合わせる', + 'photo.zoom_fit_label': '合わせる', + 'photo.zoom_100': '実寸(100%)', + // LAN cast 'cast.start': 'デバイスにキャスト', 'cast.stop': 'キャストを停止', @@ -644,8 +663,15 @@ export default { 'settings_node.audio_root_none': '— 未選択 —', 'settings_node.audio_root_save': '保存', 'settings_node.audio_root_change_confirm': '音楽のルートフォルダを変更すると、全メンバーの音楽タブの表示内容が変わります。続行しますか?', + 'settings_node.photo_roots_title': '写真のルートフォルダ', + 'settings_node.photo_roots_hint': 'このグループで写真アプリの起点とするフォルダです。写真ライブラリは複数のフォルダに分かれていることが多いため、複数選択できます。少なくとも1つ追加されるまで、写真には何も表示されません。', + 'settings_node.photo_roots_none': '— 未選択 —', + 'settings_node.photo_roots_add_placeholder': 'フォルダを追加…', + 'settings_node.photo_roots_add': '追加', + 'settings_node.photo_roots_remove': '削除', + 'settings_node.photo_roots_save': '保存', 'settings_node.directories_title': 'ディレクトリ', - 'settings_node.directories_hint': '共有フォルダと、動画アプリ・音楽アプリがそれぞれの起点として使用するフォルダです。', + 'settings_node.directories_hint': '共有フォルダと、動画・音楽・写真の各アプリがそれぞれの起点として使用するフォルダです。', // Wizard 'wizard.title': 'グループを作成', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js index fdfcb89..217aead 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/nl.js @@ -78,6 +78,7 @@ export default { 'group.tab_chat': 'Chat', 'group.tab_video': "Video's", 'group.tab_music': 'Muziek', + 'group.tab_photos': "Foto's", 'group.tab_members': 'Leden', 'group.tab_settings': "Instellingen", 'members.danger_leave_hint': "U verliest de toegang tot de bestanden en de chat van deze groep.", @@ -205,6 +206,24 @@ export default { 'music.player_queue': 'Huidige wachtrij', 'music.queue_title': 'Nu aan het afspelen', + // Photos + 'photo.empty': "Geen foto's gevonden.", + 'photo.no_roots_configured': "Er zijn nog geen hoofdmappen voor Foto's ingesteld voor deze groep — een operator kan er enkele kiezen bij Instellingen.", + 'photo.root_album': '(hoofdniveau)', + 'photo.n_photos': { + one: '{n} foto', + other: "{n} foto's", + }, + 'photo.back': 'Terug', + 'photo.prev': 'Vorige (←)', + 'photo.next': 'Volgende (→)', + 'photo.zip_album': 'Album downloaden als zip', + 'photo.zoom_in': 'Inzoomen', + 'photo.zoom_out': 'Uitzoomen', + 'photo.zoom_fit_title': 'Passend maken', + 'photo.zoom_fit_label': 'Passend', + 'photo.zoom_100': 'Werkelijke grootte (100%)', + // LAN cast 'cast.start': 'Naar apparaat casten', 'cast.stop': 'Casten stoppen', @@ -662,8 +681,15 @@ export default { 'settings_node.audio_root_none': '— geen gekozen —', 'settings_node.audio_root_save': 'Opslaan', 'settings_node.audio_root_change_confirm': 'Het wijzigen van de hoofdmap voor Muziek vervangt wat elk lid ziet in het tabblad Muziek. Doorgaan?', + 'settings_node.photo_roots_title': "Hoofdmappen voor Foto's", + 'settings_node.photo_roots_hint': "Welke map(pen) de Foto's-app als startpunt gebruikt voor deze groep — een fotobibliotheek is vaak over meerdere mappen verspreid, dus er kunnen er meerdere gekozen worden. Er wordt niets getoond in Foto's totdat er minstens één is toegevoegd.", + 'settings_node.photo_roots_none': '— geen gekozen —', + 'settings_node.photo_roots_add_placeholder': 'Map toevoegen…', + 'settings_node.photo_roots_add': 'Toevoegen', + 'settings_node.photo_roots_remove': 'Verwijderen', + 'settings_node.photo_roots_save': 'Opslaan', 'settings_node.directories_title': 'Mappen', - 'settings_node.directories_hint': 'Gedeelde mappen, en welke daarvan de Video\'s- en Muziek-apps als eigen startpunt gebruiken.', + 'settings_node.directories_hint': 'Gedeelde mappen, en welke daarvan de Video\'s-, Muziek- en Foto\'s-apps als eigen startpunt(en) gebruiken.', // Create group wizard 'wizard.title': 'Groep aanmaken', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js index 8e7f636..25d67f9 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/pl.js @@ -82,6 +82,7 @@ export default { 'group.tab_chat': 'Czat', 'group.tab_video': 'Wideo', 'group.tab_music': 'Muzyka', + 'group.tab_photos': 'Zdjęcia', 'group.tab_members': 'Członkowie', 'group.tab_settings': "Ustawienia", 'members.danger_leave_hint': "Utracisz dostęp do plików i czatu tej grupy.", @@ -214,6 +215,26 @@ export default { 'music.player_queue': 'Aktualna kolejka', 'music.queue_title': 'Teraz odtwarzane', + // Photos + 'photo.empty': 'Nie znaleziono żadnych zdjęć.', + 'photo.no_roots_configured': 'Dla tej grupy nie wybrano jeszcze katalogów głównych Zdjęć — operator może wybrać kilka w Ustawieniach.', + 'photo.root_album': '(poziom główny)', + 'photo.n_photos': { + one: '{n} zdjęcie', + few: '{n} zdjęcia', + many: '{n} zdjęć', + other: '{n} zdjęcia', + }, + 'photo.back': 'Wstecz', + 'photo.prev': 'Poprzednie (←)', + 'photo.next': 'Następne (→)', + 'photo.zip_album': 'Pobierz album jako zip', + 'photo.zoom_in': 'Powiększ', + 'photo.zoom_out': 'Pomniejsz', + 'photo.zoom_fit_title': 'Dopasuj do okna', + 'photo.zoom_fit_label': 'Dopasuj', + 'photo.zoom_100': 'Rzeczywisty rozmiar (100%)', + // LAN cast 'cast.start': 'Przesyłaj na urządzenie', 'cast.stop': 'Zatrzymaj przesyłanie', @@ -687,8 +708,15 @@ export default { 'settings_node.audio_root_none': '— nie wybrano —', 'settings_node.audio_root_save': 'Zapisz', 'settings_node.audio_root_change_confirm': 'Zmiana katalogu głównego Muzyki zastępuje to, co widzi każdy członek w karcie Muzyka. Kontynuować?', + 'settings_node.photo_roots_title': 'Katalogi główne Zdjęć', + 'settings_node.photo_roots_hint': 'Które katalogi aplikacja Zdjęcia traktuje jako punkty wejścia dla tej grupy — biblioteka zdjęć jest często rozproszona w wielu katalogach, więc można wybrać kilka. W Zdjęciach nic się nie wyświetla, dopóki nie zostanie dodany co najmniej jeden.', + 'settings_node.photo_roots_none': '— nie wybrano —', + 'settings_node.photo_roots_add_placeholder': 'Dodaj katalog…', + 'settings_node.photo_roots_add': 'Dodaj', + 'settings_node.photo_roots_remove': 'Usuń', + 'settings_node.photo_roots_save': 'Zapisz', 'settings_node.directories_title': 'Katalogi', - 'settings_node.directories_hint': 'Katalogi udostępnione oraz to, który z nich aplikacje Wideo i Muzyka traktują jako własny punkt wejścia.', + 'settings_node.directories_hint': 'Katalogi udostępnione oraz to, który z nich aplikacje Wideo, Muzyka i Zdjęcia traktują jako własny punkt (punkty) wejścia.', // Create-group wizard 'wizard.title': 'Utwórz grupę', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js index 97786f4..c32ff63 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/pt-BR.js @@ -78,6 +78,7 @@ export default { 'group.tab_chat': 'Conversa', 'group.tab_video': 'Vídeos', 'group.tab_music': 'Música', + 'group.tab_photos': 'Fotos', 'group.tab_members': 'Membros', 'group.tab_settings': "Configurações", 'members.danger_leave_hint': "Você perderá o acesso aos arquivos e ao chat deste grupo.", @@ -205,6 +206,24 @@ export default { 'music.player_queue': 'Fila atual', 'music.queue_title': 'Tocando agora', + // Photos + 'photo.empty': 'Nenhuma foto encontrada.', + 'photo.no_roots_configured': 'Ainda não há pastas raiz de Fotos definidas para este grupo — um operador pode escolher algumas em Configurações.', + 'photo.root_album': '(nível superior)', + 'photo.n_photos': { + one: '{n} foto', + other: '{n} fotos', + }, + 'photo.back': 'Voltar', + 'photo.prev': 'Anterior (←)', + 'photo.next': 'Próxima (→)', + 'photo.zip_album': 'Baixar álbum como zip', + 'photo.zoom_in': 'Aumentar zoom', + 'photo.zoom_out': 'Diminuir zoom', + 'photo.zoom_fit_title': 'Ajustar à janela', + 'photo.zoom_fit_label': 'Ajustar', + 'photo.zoom_100': 'Tamanho real (100%)', + // LAN cast 'cast.start': 'Transmitir para dispositivo', 'cast.stop': 'Parar transmissão', @@ -647,8 +666,15 @@ export default { 'settings_node.audio_root_none': '— nenhuma escolhida —', 'settings_node.audio_root_save': 'Salvar', 'settings_node.audio_root_change_confirm': 'Alterar a raiz de Música substitui o que cada membro vê na aba Música. Continuar?', + 'settings_node.photo_roots_title': 'Pastas raiz de Fotos', + 'settings_node.photo_roots_hint': 'Quais pastas o app Fotos trata como pontos de entrada para este grupo — uma biblioteca de fotos costuma estar espalhada em várias pastas, então mais de uma pode ser escolhida. Nada é exibido em Fotos até que ao menos uma seja adicionada.', + 'settings_node.photo_roots_none': '— nenhuma escolhida —', + 'settings_node.photo_roots_add_placeholder': 'Adicionar uma pasta…', + 'settings_node.photo_roots_add': 'Adicionar', + 'settings_node.photo_roots_remove': 'Remover', + 'settings_node.photo_roots_save': 'Salvar', 'settings_node.directories_title': 'Diretórios', - 'settings_node.directories_hint': 'Pastas compartilhadas, e qual delas os apps Vídeos e Música tratam como seu próprio ponto de entrada.', + 'settings_node.directories_hint': 'Pastas compartilhadas, e qual delas os apps Vídeos, Música e Fotos tratam como seu(s) próprio(s) ponto(s) de entrada.', // Create group wizard 'wizard.title': 'Criar grupo', diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js index a26062d..ee0efdf 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/zh-CN.js @@ -75,6 +75,7 @@ export default { 'group.tab_chat': '聊天', 'group.tab_video': '视频', 'group.tab_music': '音乐', + 'group.tab_photos': '照片', 'group.tab_members': '成员', 'group.tab_settings': "设置", 'members.danger_leave_hint': "您将无法再访问该群组的文件和聊天。", @@ -198,6 +199,24 @@ export default { 'music.player_queue': '当前队列', 'music.queue_title': '正在播放', + // Photos + 'photo.empty': '未找到照片。', + 'photo.no_roots_configured': '此群组尚未设置照片根目录 — 操作员可以在设置中选择一些。', + 'photo.root_album': '(顶层)', + 'photo.n_photos': { + one: '{n} 张照片', + other: '{n} 张照片', + }, + 'photo.back': '返回', + 'photo.prev': '上一张(←)', + 'photo.next': '下一张(→)', + 'photo.zip_album': '将相册下载为 zip', + 'photo.zoom_in': '放大', + 'photo.zoom_out': '缩小', + 'photo.zoom_fit_title': '适应窗口', + 'photo.zoom_fit_label': '适应', + 'photo.zoom_100': '实际大小(100%)', + // LAN cast 'cast.start': '投射到设备', 'cast.stop': '停止投射', @@ -630,8 +649,15 @@ export default { 'settings_node.audio_root_none': '— 未选择 —', 'settings_node.audio_root_save': '保存', 'settings_node.audio_root_change_confirm': '更改音乐根目录会替换每位成员在“音乐”标签页中看到的内容。是否继续?', + 'settings_node.photo_roots_title': '照片根目录', + 'settings_node.photo_roots_hint': '该群组“照片”应用的入口文件夹 — 照片库通常分散在多个文件夹中,因此可以选择多个。在添加至少一个之前,“照片”中不会显示任何内容。', + 'settings_node.photo_roots_none': '— 未选择 —', + 'settings_node.photo_roots_add_placeholder': '添加文件夹…', + 'settings_node.photo_roots_add': '添加', + 'settings_node.photo_roots_remove': '移除', + 'settings_node.photo_roots_save': '保存', 'settings_node.directories_title': '目录', - 'settings_node.directories_hint': '共享文件夹,以及“视频”和“音乐”应用各自使用哪个作为入口。', + 'settings_node.directories_hint': '共享文件夹,以及“视频”“音乐”和“照片”应用各自使用哪个(些)作为入口。', // Create group wizard 'wizard.title': '创建群组', |