feat(group): 1st implementation of Groups

this implements first version (manageable only by admin right now)

    routes:

        GET /api/groups
        List subject groups (paginated). Admin-only.

        POST /api/groups
        Create a new ReBAC subject group. Admin-only. The name must match the RFC 5321 local-part shape and be globally unique (case-insensitive).

        GET /api/groups/search
        Search non-virtual groups by name substring. Authenticated only (no admin role required) — backs the share-dialog recipient autocomplete.

        GET /api/groups/{id}
        Fetch a single group's details. Admin-only.

        DELETE /api/groups/{id}
        Delete a group. Cascades to `subject_group_members` (FK) and to `access_grants` rows referencing this group as a subject. Admin-only.

        PATCH /api/groups/{id}
        Update a group's metadata. Admin-only. v1 only persists name renames.

        GET /api/groups/{id}/effective-members
        List every user transitively reached through this group (members of members of members, etc.). Used by admin / audit tooling. Admin-only.

        GET /api/groups/{id}/members
        List the *direct* members of a group (one level only). Admin-only.

        POST /api/groups/{id}/members
        Add a member to a group. Exactly one of `user_id` / `group_id` must be provided. Adding a group-member runs a write-time cycle check and a nesting-depth check (max 8). Admin-only.

        DELETE /api/groups/{id}/members/group/{gid}
        Remove a nested group-member from a group. Admin-only.

        DELETE /api/groups/{id}/members/user/{uid}
        Remove a user-member from a group. Admin-only.

fix hurl

groups

round

groups
This commit is contained in:
Edouard Vanbelle
2026-05-30 23:35:47 +02:00
parent 41356b6490
commit 09985f8a95
54 changed files with 6421 additions and 145 deletions
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "فاتح",
"dark": "داكن",
"auto": "مثل النظام"
}
},
"manage_groups": "إدارة المجموعات"
},
"share": {
"dialogTitle": "رابط المشاركة",
@@ -336,7 +337,13 @@
"move_error": "خطأ في النقل",
"empty_name": "لا يمكن أن يكون الاسم فارغاً",
"name_exists": "ملف أو مجلد بهذا الاسم موجود بالفعل",
"generic_error": "حدث خطأ"
"generic_error": "حدث خطأ",
"group_name_invalid": "يجب أن يتطابق اسم المجموعة مع صيغة بادئة البريد الإلكتروني (حروف، أرقام، نقطة، شرطة، شرطة سفلية؛ 1–64 حرفًا).",
"group_cycle": "سينشئ هذا العضو مرجعًا دائريًا بين المجموعات.",
"group_depth_exceeded": "تتجاوز عمق التعشيش الحد الأقصى المسموح (8).",
"group_virtual_immutable": "مجموعة «Internal» تدار من قبل النظام ولا يمكن تعديلها.",
"group_not_found": "المجموعة غير موجودة.",
"group_name_taken": "توجد بالفعل مجموعة بهذا الاسم."
},
"breadcrumb": {
"home": "الرئيسية"
@@ -755,5 +762,31 @@
"today": "اليوم",
"last7days": "آخر 7 أيام",
"last30days": "آخر 30 يومًا"
},
"groups": {
"title": "إدارة المجموعات",
"create_button": "إنشاء مجموعة",
"create_dialog_title": "مجموعة جديدة",
"edit_dialog_title": "إعادة تسمية المجموعة",
"name_label": "الاسم",
"name_placeholder": "engineering",
"description_label": "الوصف (اختياري)",
"members_section": "الأعضاء",
"add_member_placeholder": "إضافة مستخدم أو مجموعة…",
"no_members": "لا يوجد أعضاء بعد.",
"remove_member": "إزالة",
"delete_group": "حذف المجموعة",
"delete_confirm": "حذف المجموعة \"{name}\"؟ سيتم إلغاء الصلاحيات المرتبطة بهذه المجموعة.",
"empty_state": "لا توجد مجموعات بعد.",
"load_more": "تحميل المزيد",
"back_to_list": "رجوع",
"loading": "جارٍ التحميل…",
"virtual_badge": "النظام",
"member_count_zero": "لا يوجد أعضاء",
"member_count_one": "عضو واحد",
"member_count_other": "{count} أعضاء",
"delete_confirm_label": "اكتب اسم المجموعة للتأكيد:",
"delete_confirm_mismatch": "اكتب اسم المجموعة كما هو للتأكيد.",
"virtual_internal_name": "داخلي"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "Hell",
"dark": "Dunkel",
"auto": "Wie System"
}
},
"manage_groups": "Gruppen verwalten"
},
"share": {
"dialogTitle": "Link teilen",
@@ -336,7 +337,13 @@
"move_error": "Fehler beim Verschieben",
"empty_name": "Der Name darf nicht leer sein",
"name_exists": "Eine Datei oder ein Ordner mit diesem Namen existiert bereits",
"generic_error": "Ein Fehler ist aufgetreten"
"generic_error": "Ein Fehler ist aufgetreten",
"group_name_invalid": "Der Gruppenname muss dem E-Mail-Präfix-Format entsprechen (Buchstaben, Ziffern, Punkt, Bindestrich, Unterstrich; 1–64 Zeichen).",
"group_cycle": "Dieses Mitglied würde einen Gruppen-Zirkelbezug erzeugen.",
"group_depth_exceeded": "Die Verschachtelungstiefe überschreitet das zulässige Maximum (8).",
"group_virtual_immutable": "Die Gruppe „Internal“ wird vom System verwaltet und kann nicht geändert werden.",
"group_not_found": "Gruppe nicht gefunden.",
"group_name_taken": "Eine Gruppe mit diesem Namen existiert bereits."
},
"breadcrumb": {
"home": "Startseite"
@@ -755,5 +762,31 @@
"today": "Heute",
"last7days": "Letzte 7 Tage",
"last30days": "Letzte 30 Tage"
},
"groups": {
"title": "Gruppen verwalten",
"create_button": "Gruppe erstellen",
"create_dialog_title": "Neue Gruppe",
"edit_dialog_title": "Gruppe umbenennen",
"name_label": "Name",
"name_placeholder": "engineering",
"description_label": "Beschreibung (optional)",
"members_section": "Mitglieder",
"add_member_placeholder": "Benutzer oder Gruppe hinzufügen…",
"no_members": "Noch keine Mitglieder.",
"remove_member": "Entfernen",
"delete_group": "Gruppe löschen",
"delete_confirm": "Die Gruppe „{name}\" löschen? Auf diese Gruppe verweisende Berechtigungen werden widerrufen.",
"empty_state": "Noch keine Gruppen.",
"load_more": "Mehr laden",
"back_to_list": "Zurück",
"loading": "Wird geladen…",
"virtual_badge": "System",
"member_count_zero": "Keine Mitglieder",
"member_count_one": "1 Mitglied",
"member_count_other": "{count} Mitglieder",
"delete_confirm_label": "Tippe den Gruppennamen zur Bestätigung ein:",
"delete_confirm_mismatch": "Tippe den Gruppennamen exakt zur Bestätigung ein.",
"virtual_internal_name": "Intern"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "Light",
"dark": "Dark",
"auto": "Like OS"
}
},
"manage_groups": "Manage groups"
},
"share": {
"dialogTitle": "Share Link",
@@ -336,7 +337,13 @@
"move_error": "Error moving",
"empty_name": "Name cannot be empty",
"name_exists": "A file or folder with that name already exists",
"generic_error": "An error has occurred"
"generic_error": "An error has occurred",
"group_name_invalid": "Group name must match the email-prefix format (letters, digits, dot, dash, underscore; 1–64 chars).",
"group_cycle": "This member would create a circular group reference.",
"group_depth_exceeded": "This nesting depth exceeds the maximum allowed (8).",
"group_virtual_immutable": "The 'Internal' group is system-managed and cannot be modified.",
"group_not_found": "Group not found.",
"group_name_taken": "A group with this name already exists."
},
"breadcrumb": {
"home": "Home"
@@ -755,5 +762,31 @@
"today": "Today",
"last7days": "Last 7 days",
"last30days": "Last 30 days"
},
"groups": {
"title": "Manage groups",
"create_button": "Create group",
"create_dialog_title": "New group",
"edit_dialog_title": "Rename group",
"name_label": "Name",
"name_placeholder": "engineering",
"description_label": "Description (optional)",
"members_section": "Members",
"add_member_placeholder": "Add a user or group…",
"no_members": "No members yet.",
"remove_member": "Remove",
"delete_group": "Delete group",
"delete_confirm": "Delete the group \"{name}\"? Grants referencing this group will be revoked.",
"empty_state": "No groups yet.",
"load_more": "Load more",
"back_to_list": "Back",
"loading": "Loading…",
"virtual_badge": "System",
"member_count_zero": "no members",
"member_count_one": "1 member",
"member_count_other": "{count} members",
"delete_confirm_label": "Type the group name to confirm:",
"delete_confirm_mismatch": "Type the group name exactly to confirm.",
"virtual_internal_name": "Internal"
}
}
+35 -2
View File
@@ -250,7 +250,8 @@
"light": "Claro",
"dark": "Oscuro",
"auto": "Como el sistema"
}
},
"manage_groups": "Gestionar grupos"
},
"files": {
"name": "Nombre",
@@ -336,7 +337,13 @@
"move_error": "Error al mover",
"empty_name": "El nombre no puede estar vacío",
"name_exists": "Ya existe un archivo o carpeta con ese nombre",
"generic_error": "Ha ocurrido un error"
"generic_error": "Ha ocurrido un error",
"group_name_invalid": "El nombre del grupo debe seguir el formato de prefijo de correo (letras, dígitos, punto, guión, guion bajo; 1–64 caracteres).",
"group_cycle": "Este miembro creaería una referencia circular entre grupos.",
"group_depth_exceeded": "Esta profundidad de anidamiento excede el máximo permitido (8).",
"group_virtual_immutable": "El grupo «Internal» es gestionado por el sistema y no se puede modificar.",
"group_not_found": "Grupo no encontrado.",
"group_name_taken": "Ya existe un grupo con este nombre."
},
"breadcrumb": {
"home": "Inicio"
@@ -755,5 +762,31 @@
"today": "Hoy",
"last7days": "Últimos 7 días",
"last30days": "Últimos 30 días"
},
"groups": {
"title": "Gestionar grupos",
"create_button": "Crear grupo",
"create_dialog_title": "Nuevo grupo",
"edit_dialog_title": "Renombrar grupo",
"name_label": "Nombre",
"name_placeholder": "ingenieria",
"description_label": "Descripción (opcional)",
"members_section": "Miembros",
"add_member_placeholder": "Añadir un usuario o grupo…",
"no_members": "Aún no hay miembros.",
"remove_member": "Eliminar",
"delete_group": "Eliminar grupo",
"delete_confirm": "¿Eliminar el grupo «{name}»? Se revocarán las concesiones que hagan referencia a este grupo.",
"empty_state": "Aún no hay grupos.",
"load_more": "Cargar más",
"back_to_list": "Volver",
"loading": "Cargando…",
"virtual_badge": "Sistema",
"member_count_zero": "Sin miembros",
"member_count_one": "1 miembro",
"member_count_other": "{count} miembros",
"delete_confirm_label": "Escribe el nombre del grupo para confirmar:",
"delete_confirm_mismatch": "Escribe el nombre del grupo exactamente para confirmar.",
"virtual_internal_name": "Interno"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "روشن",
"dark": "تاریک",
"auto": "مانند سیستم"
}
},
"manage_groups": "مدیریت گروه‌ها"
},
"share": {
"dialogTitle": "پیوند هم‌رسانی",
@@ -336,7 +337,13 @@
"move_error": "خطا در انتقال",
"empty_name": "نام نمی‌تواند خالی باشد",
"name_exists": "پرونده یا پوشه‌ای با این نام قبلا وجود دارد",
"generic_error": "خطایی رخ داده است"
"generic_error": "خطایی رخ داده است",
"group_name_invalid": "نام گروه باید با قالب پیشوند ایمیل مطابقت داشته باشد (حروف، ارقام، نقطه، خط تیره، زیرخط؛ 1–64 نویسه).",
"group_cycle": "این عضو باعث ایجاد ارجاع چرخه‌ای بین گروه‌ها می‌شود.",
"group_depth_exceeded": "عمق تودرتو بیش از حداکثر مجاز (8) است.",
"group_virtual_immutable": "گروه «Internal» توسط سامانه مدیریت می‌شود و قابل تغییر نیست.",
"group_not_found": "گروه پیدا نشد.",
"group_name_taken": "گروهی با این نام پیش‌از این وجود دارد."
},
"breadcrumb": {
"home": "صفحه اصلی"
@@ -755,5 +762,31 @@
"today": "امروز",
"last7days": "۷ روز گذشته",
"last30days": "۳۰ روز گذشته"
},
"groups": {
"title": "مدیریت گروه‌ها",
"create_button": "ایجاد گروه",
"create_dialog_title": "گروه جدید",
"edit_dialog_title": "تغییر نام گروه",
"name_label": "نام",
"name_placeholder": "engineering",
"description_label": "توضیحات (اختیاری)",
"members_section": "اعضا",
"add_member_placeholder": "افزودن کاربر یا گروه…",
"no_members": "هنوز عضوی وجود ندارد.",
"remove_member": "حذف",
"delete_group": "حذف گروه",
"delete_confirm": "گروه «{name}» حذف شود؟ مجوزهای مرتبط با این گروه باطل خواهند شد.",
"empty_state": "هنوز گروهی وجود ندارد.",
"load_more": "بارگیری بیشتر",
"back_to_list": "بازگشت",
"loading": "در حال بارگذاری…",
"virtual_badge": "سامانه",
"member_count_zero": "بدون عضو",
"member_count_one": "۱ عضو",
"member_count_other": "{count} عضو",
"delete_confirm_label": "نام گروه را برای تأیید وارد کنید:",
"delete_confirm_mismatch": "نام گروه را دقیقاً برای تأیید وارد کنید.",
"virtual_internal_name": "داخلی"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "Clair",
"dark": "Sombre",
"auto": "Comme le système"
}
},
"manage_groups": "Gérer les groupes"
},
"share": {
"dialogTitle": "Lien de partage",
@@ -336,7 +337,13 @@
"move_error": "Erreur lors du déplacement",
"empty_name": "Le nom ne peut pas être vide",
"name_exists": "Un fichier ou dossier portant ce nom existe déjà",
"generic_error": "Une erreur est survenue"
"generic_error": "Une erreur est survenue",
"group_name_invalid": "Le nom du groupe doit respecter le format préfixe d'email (lettres, chiffres, point, tiret, souligné ; 1–64 caractères).",
"group_cycle": "Ce membre créerait une référence circulaire entre groupes.",
"group_depth_exceeded": "Cette profondeur d'imbrication dépasse le maximum autorisé (8).",
"group_virtual_immutable": "Le groupe « Internal » est géré par le système et ne peut pas être modifié.",
"group_not_found": "Groupe introuvable.",
"group_name_taken": "Un groupe portant ce nom existe déjà."
},
"breadcrumb": {
"home": "Accueil"
@@ -755,5 +762,31 @@
"today": "Aujourd'hui",
"last7days": "7 derniers jours",
"last30days": "30 derniers jours"
},
"groups": {
"title": "Gérer les groupes",
"create_button": "Créer un groupe",
"create_dialog_title": "Nouveau groupe",
"edit_dialog_title": "Renommer le groupe",
"name_label": "Nom",
"name_placeholder": "ingenierie",
"description_label": "Description (facultatif)",
"members_section": "Membres",
"add_member_placeholder": "Ajouter un utilisateur ou un groupe…",
"no_members": "Aucun membre pour le moment.",
"remove_member": "Retirer",
"delete_group": "Supprimer le groupe",
"delete_confirm": "Supprimer le groupe « {name} » ? Les autorisations associées à ce groupe seront révoquées.",
"empty_state": "Aucun groupe pour le moment.",
"load_more": "Charger plus",
"back_to_list": "Retour",
"loading": "Chargement…",
"virtual_badge": "Système",
"member_count_zero": "Aucun membre",
"member_count_one": "1 membre",
"member_count_other": "{count} membres",
"delete_confirm_label": "Tapez le nom du groupe pour confirmer :",
"delete_confirm_mismatch": "Tapez le nom du groupe exactement pour confirmer.",
"virtual_internal_name": "Interne"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "हल्का",
"dark": "गहरा",
"auto": "सिस्टम जैसा"
}
},
"manage_groups": "समूह प्रबंधित करें"
},
"share": {
"dialogTitle": "शेयर लिंक",
@@ -336,7 +337,13 @@
"move_error": "ले जाने में त्रुटि",
"empty_name": "नाम खाली नहीं हो सकता",
"name_exists": "इस नाम की फ़ाइल या फ़ोल्डर पहले से मौजूद है",
"generic_error": "एक त्रुटि हुई है"
"generic_error": "एक त्रुटि हुई है",
"group_name_invalid": "समूह का नाम ईमेल उपसर्ग प्रारूप के अनुरूप होना चाहिए (अक्षर, अंक, बिंदु, डैश, अंडरस्कोर; 1–64 वर्ण).",
"group_cycle": "यह सदस्य समूहों के बीच चक्रीय संदर्भ बनाएगा।",
"group_depth_exceeded": "यह नेस्टिंग गहराई अनुमत अधिकतम (8) से अधिक है।",
"group_virtual_immutable": "«Internal» समूह सिस्टम द्वारा प्रबंधित है और इसे संशोधित नहीं किया जा सकता।",
"group_not_found": "समूह नहीं मिला।",
"group_name_taken": "इस नाम का एक समूह पहले से मौजूद है।"
},
"breadcrumb": {
"home": "होम"
@@ -755,5 +762,31 @@
"today": "आज",
"last7days": "पिछले 7 दिन",
"last30days": "पिछले 30 दिन"
},
"groups": {
"title": "समूह प्रबंधित करें",
"create_button": "समूह बनाएँ",
"create_dialog_title": "नया समूह",
"edit_dialog_title": "समूह का नाम बदलें",
"name_label": "नाम",
"name_placeholder": "engineering",
"description_label": "विवरण (वैकल्पिक)",
"members_section": "सदस्य",
"add_member_placeholder": "उपयोगकर्ता या समूह जोड़ें…",
"no_members": "अभी तक कोई सदस्य नहीं।",
"remove_member": "हटाएँ",
"delete_group": "समूह हटाएँ",
"delete_confirm": "समूह \"{name}\" को हटाएँ? इस समूह से जुड़ी अनुमतियाँ रद्द कर दी जाएँगी।",
"empty_state": "अभी तक कोई समूह नहीं।",
"load_more": "और लोड करें",
"back_to_list": "वापस",
"loading": "लोड हो रहा है…",
"virtual_badge": "सिस्टम",
"member_count_zero": "कोई सदस्य नहीं",
"member_count_one": "1 सदस्य",
"member_count_other": "{count} सदस्य",
"delete_confirm_label": "पुष्टि के लिए समूह का नाम लिखें:",
"delete_confirm_mismatch": "पुष्टि के लिए समूह का नाम बिल्कुल वैसा ही लिखें।",
"virtual_internal_name": "आंतरिक"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "Chiaro",
"dark": "Scuro",
"auto": "Come il sistema"
}
},
"manage_groups": "Gestisci gruppi"
},
"share": {
"dialogTitle": "Link di condivisione",
@@ -336,7 +337,13 @@
"move_error": "Errore durante lo spostamento",
"empty_name": "Il nome non può essere vuoto",
"name_exists": "Un file o una cartella con quel nome esiste già",
"generic_error": "Si è verificato un errore"
"generic_error": "Si è verificato un errore",
"group_name_invalid": "Il nome del gruppo deve rispettare il formato del prefisso email (lettere, cifre, punto, trattino, trattino basso; 1–64 caratteri).",
"group_cycle": "Questo membro creerebbe un riferimento circolare tra gruppi.",
"group_depth_exceeded": "Questa profondità di annidamento supera il massimo consentito (8).",
"group_virtual_immutable": "Il gruppo «Internal» è gestito dal sistema e non può essere modificato.",
"group_not_found": "Gruppo non trovato.",
"group_name_taken": "Un gruppo con questo nome esiste già."
},
"breadcrumb": {
"home": "Home"
@@ -755,5 +762,31 @@
"today": "Oggi",
"last7days": "Ultimi 7 giorni",
"last30days": "Ultimi 30 giorni"
},
"groups": {
"title": "Gestisci gruppi",
"create_button": "Crea gruppo",
"create_dialog_title": "Nuovo gruppo",
"edit_dialog_title": "Rinomina gruppo",
"name_label": "Nome",
"name_placeholder": "ingegneria",
"description_label": "Descrizione (opzionale)",
"members_section": "Membri",
"add_member_placeholder": "Aggiungi un utente o un gruppo…",
"no_members": "Nessun membro al momento.",
"remove_member": "Rimuovi",
"delete_group": "Elimina gruppo",
"delete_confirm": "Eliminare il gruppo \"{name}\"? Le autorizzazioni che fanno riferimento a questo gruppo saranno revocate.",
"empty_state": "Nessun gruppo al momento.",
"load_more": "Carica altro",
"back_to_list": "Indietro",
"loading": "Caricamento…",
"virtual_badge": "Sistema",
"member_count_zero": "Nessun membro",
"member_count_one": "1 membro",
"member_count_other": "{count} membri",
"delete_confirm_label": "Digita il nome del gruppo per confermare:",
"delete_confirm_mismatch": "Digita esattamente il nome del gruppo per confermare.",
"virtual_internal_name": "Interno"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "ライト",
"dark": "ダーク",
"auto": "システムに合わせる"
}
},
"manage_groups": "グループを管理"
},
"share": {
"dialogTitle": "共有リンク",
@@ -336,7 +337,13 @@
"move_error": "移動エラー",
"empty_name": "名前を空にすることはできません",
"name_exists": "同じ名前のファイルまたはフォルダが既に存在します",
"generic_error": "エラーが発生しました"
"generic_error": "エラーが発生しました",
"group_name_invalid": "グループ名はメールプレフィックス形式に一致している必要があります(文字、数字、ドット、ダッシュ、アンダースコア;1~64文字)。",
"group_cycle": "このメンバーはグループ間で循環参照を作成します。",
"group_depth_exceeded": "ネストの深さが許容されている最大値(8)を超えています。",
"group_virtual_immutable": "「Internal」グループはシステム管理であり、変更できません。",
"group_not_found": "グループが見つかりません。",
"group_name_taken": "この名前のグループはすでに存在します。"
},
"breadcrumb": {
"home": "ホーム"
@@ -755,5 +762,31 @@
"today": "今日",
"last7days": "過去7日間",
"last30days": "過去30日間"
},
"groups": {
"title": "グループを管理",
"create_button": "グループを作成",
"create_dialog_title": "新規グループ",
"edit_dialog_title": "グループ名を変更",
"name_label": "名前",
"name_placeholder": "engineering",
"description_label": "説明(任意)",
"members_section": "メンバー",
"add_member_placeholder": "ユーザーまたはグループを追加…",
"no_members": "メンバーはまだいません。",
"remove_member": "削除",
"delete_group": "グループを削除",
"delete_confirm": "グループ「{name}」を削除しますか?このグループを参照しているすべての権限が取り消されます。",
"empty_state": "グループはまだありません。",
"load_more": "もっと読み込む",
"back_to_list": "戻る",
"loading": "読み込み中…",
"virtual_badge": "システム",
"member_count_zero": "メンバーなし",
"member_count_one": "1 メンバー",
"member_count_other": "{count} メンバー",
"delete_confirm_label": "確認のためにグループ名を入力してください:",
"delete_confirm_mismatch": "確認のためにグループ名を正確に入力してください。",
"virtual_internal_name": "内部"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "라이트",
"dark": "다크",
"auto": "시스템과 동일"
}
},
"manage_groups": "그룹 관리"
},
"share": {
"dialogTitle": "공유 링크",
@@ -336,7 +337,13 @@
"move_error": "이동 오류",
"empty_name": "이름은 비워둘 수 없습니다",
"name_exists": "같은 이름의 파일 또는 폴더가 이미 존재합니다",
"generic_error": "오류가 발생했습니다"
"generic_error": "오류가 발생했습니다",
"group_name_invalid": "그룹 이름은 이메일 접두사 형식과 일치해야 합니다(문자, 숫자, 점, 대시, 밑줄; 1–64자).",
"group_cycle": "이 구성원은 그룹 간 순환 참조를 만들 것입니다.",
"group_depth_exceeded": "중첩 깊이가 허용 최대값(8)을 초과합니다.",
"group_virtual_immutable": "«Internal» 그룹은 시스템이 관리하며 수정할 수 없습니다.",
"group_not_found": "그룹을 찾을 수 없습니다.",
"group_name_taken": "이 이름의 그룹이 이미 존재합니다."
},
"breadcrumb": {
"home": "홈"
@@ -755,5 +762,31 @@
"today": "오늘",
"last7days": "최근 7일",
"last30days": "최근 30일"
},
"groups": {
"title": "그룹 관리",
"create_button": "그룹 생성",
"create_dialog_title": "새 그룹",
"edit_dialog_title": "그룹 이름 변경",
"name_label": "이름",
"name_placeholder": "engineering",
"description_label": "설명(선택사항)",
"members_section": "구성원",
"add_member_placeholder": "사용자 또는 그룹 추가…",
"no_members": "아직 구성원이 없습니다.",
"remove_member": "제거",
"delete_group": "그룹 삭제",
"delete_confirm": "\"{name}\" 그룹을 삭제하시겠습니까? 이 그룹을 참조하는 모든 권한이 해제됩니다.",
"empty_state": "아직 그룹이 없습니다.",
"load_more": "더 보기",
"back_to_list": "뒤로",
"loading": "로딩 중…",
"virtual_badge": "시스템",
"member_count_zero": "구성원 없음",
"member_count_one": "구성원 1명",
"member_count_other": "구성원 {count}명",
"delete_confirm_label": "확인을 위해 그룹 이름을 입력하세요:",
"delete_confirm_mismatch": "확인을 위해 그룹 이름을 정확히 입력하세요.",
"virtual_internal_name": "내부"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "Licht",
"dark": "Donker",
"auto": "Zoals systeem"
}
},
"manage_groups": "Groepen beheren"
},
"share": {
"dialogTitle": "Deellink",
@@ -336,7 +337,13 @@
"move_error": "Fout bij verplaatsen",
"empty_name": "Naam mag niet leeg zijn",
"name_exists": "Een bestand of map met deze naam bestaat al",
"generic_error": "Er is een fout opgetreden"
"generic_error": "Er is een fout opgetreden",
"group_name_invalid": "De groepsnaam moet voldoen aan het e-mailprefix-formaat (letters, cijfers, punt, streepje, underscore; 1–64 tekens).",
"group_cycle": "Dit lid zou een circulaire groepsverwijzing veroorzaken.",
"group_depth_exceeded": "Deze nestdiepte overschrijdt het maximum (8).",
"group_virtual_immutable": "De groep 'Internal' wordt door het systeem beheerd en kan niet worden gewijzigd.",
"group_not_found": "Groep niet gevonden.",
"group_name_taken": "Er bestaat al een groep met deze naam."
},
"breadcrumb": {
"home": "Start"
@@ -755,5 +762,31 @@
"today": "Vandaag",
"last7days": "Afgelopen 7 dagen",
"last30days": "Afgelopen 30 dagen"
},
"groups": {
"title": "Groepen beheren",
"create_button": "Groep maken",
"create_dialog_title": "Nieuwe groep",
"edit_dialog_title": "Groep hernoemen",
"name_label": "Naam",
"name_placeholder": "engineering",
"description_label": "Beschrijving (optioneel)",
"members_section": "Leden",
"add_member_placeholder": "Een gebruiker of groep toevoegen…",
"no_members": "Nog geen leden.",
"remove_member": "Verwijderen",
"delete_group": "Groep verwijderen",
"delete_confirm": "De groep \"{name}\" verwijderen? Aan deze groep gekoppelde rechten worden ingetrokken.",
"empty_state": "Nog geen groepen.",
"load_more": "Meer laden",
"back_to_list": "Terug",
"loading": "Bezig met laden…",
"virtual_badge": "Systeem",
"member_count_zero": "Geen leden",
"member_count_one": "1 lid",
"member_count_other": "{count} leden",
"delete_confirm_label": "Typ de groepsnaam ter bevestiging:",
"delete_confirm_mismatch": "Typ de groepsnaam exact om te bevestigen.",
"virtual_internal_name": "Intern"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "Jasny",
"dark": "Ciemny",
"auto": "Jak system"
}
},
"manage_groups": "Zarządzaj grupami"
},
"share": {
"dialogTitle": "Link udostępniania",
@@ -336,7 +337,13 @@
"move_error": "Błąd podczas przenoszenia",
"empty_name": "Nazwa nie może być pusta",
"name_exists": "Plik lub folder o tej nazwie już istnieje",
"generic_error": "Wystąpił błąd"
"generic_error": "Wystąpił błąd",
"group_name_invalid": "Nazwa grupy musi spełniać format prefiksu e-mail (litery, cyfry, kropka, myślnik, podkreślnik; 1–64 znaków).",
"group_cycle": "Ten członek utworzyłby cykliczne odwołanie między grupami.",
"group_depth_exceeded": "Ta głębokość zagnieżdżenia przekracza maksymalną dozwoloną (8).",
"group_virtual_immutable": "Grupa „Internal” jest zarządzana przez system i nie może być modyfikowana.",
"group_not_found": "Grupa nie znaleziona.",
"group_name_taken": "Grupa o tej nazwie już istnieje."
},
"breadcrumb": {
"home": "Strona główna"
@@ -755,5 +762,31 @@
"today": "Dzisiaj",
"last7days": "Ostatnie 7 dni",
"last30days": "Ostatnie 30 dni"
},
"groups": {
"title": "Zarządzaj grupami",
"create_button": "Utwórz grupę",
"create_dialog_title": "Nowa grupa",
"edit_dialog_title": "Zmień nazwę grupy",
"name_label": "Nazwa",
"name_placeholder": "inzynieria",
"description_label": "Opis (opcjonalny)",
"members_section": "Członkowie",
"add_member_placeholder": "Dodaj użytkownika lub grupę…",
"no_members": "Brak członków.",
"remove_member": "Usuń",
"delete_group": "Usuń grupę",
"delete_confirm": "Usunąć grupę „{name}\"? Uprawnienia odwołujące się do tej grupy zostaną cofnięte.",
"empty_state": "Brak grup.",
"load_more": "Załaduj więcej",
"back_to_list": "Wstecz",
"loading": "Ładowanie…",
"virtual_badge": "System",
"member_count_zero": "Brak członków",
"member_count_one": "1 członek",
"member_count_other": "{count} członków",
"delete_confirm_label": "Wpisz nazwę grupy, aby potwierdzić:",
"delete_confirm_mismatch": "Wpisz nazwę grupy dokładnie, aby potwierdzić.",
"virtual_internal_name": "Wewnętrzni"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "Claro",
"dark": "Escuro",
"auto": "Como o sistema"
}
},
"manage_groups": "Gerenciar grupos"
},
"share": {
"dialogTitle": "Link de compartilhamento",
@@ -336,7 +337,13 @@
"move_error": "Erro ao mover",
"empty_name": "O nome não pode estar vazio",
"name_exists": "Já existe um arquivo ou pasta com esse nome",
"generic_error": "Ocorreu um erro"
"generic_error": "Ocorreu um erro",
"group_name_invalid": "O nome do grupo deve seguir o formato de prefixo de e-mail (letras, dígitos, ponto, hífen, sublinhado; 1–64 caracteres).",
"group_cycle": "Este membro criaria uma referência circular entre grupos.",
"group_depth_exceeded": "Esta profundidade de aninhamento excede o máximo permitido (8).",
"group_virtual_immutable": "O grupo «Internal» é gerenciado pelo sistema e não pode ser modificado.",
"group_not_found": "Grupo não encontrado.",
"group_name_taken": "Já existe um grupo com este nome."
},
"breadcrumb": {
"home": "Início"
@@ -755,5 +762,31 @@
"today": "Hoje",
"last7days": "Últimos 7 dias",
"last30days": "Últimos 30 dias"
},
"groups": {
"title": "Gerenciar grupos",
"create_button": "Criar grupo",
"create_dialog_title": "Novo grupo",
"edit_dialog_title": "Renomear grupo",
"name_label": "Nome",
"name_placeholder": "engenharia",
"description_label": "Descrição (opcional)",
"members_section": "Membros",
"add_member_placeholder": "Adicionar um usuário ou grupo…",
"no_members": "Ainda não há membros.",
"remove_member": "Remover",
"delete_group": "Excluir grupo",
"delete_confirm": "Excluir o grupo \"{name}\"? As concessões que referenciam este grupo serão revogadas.",
"empty_state": "Ainda não há grupos.",
"load_more": "Carregar mais",
"back_to_list": "Voltar",
"loading": "Carregando…",
"virtual_badge": "Sistema",
"member_count_zero": "Sem membros",
"member_count_one": "1 membro",
"member_count_other": "{count} membros",
"delete_confirm_label": "Digite o nome do grupo para confirmar:",
"delete_confirm_mismatch": "Digite o nome do grupo exatamente para confirmar.",
"virtual_internal_name": "Interno"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "Светлая",
"dark": "Тёмная",
"auto": "Как в системе"
}
},
"manage_groups": "Управление группами"
},
"share": {
"dialogTitle": "Ссылка для обмена",
@@ -336,7 +337,13 @@
"move_error": "Ошибка перемещения",
"empty_name": "Имя не может быть пустым",
"name_exists": "Файл или папка с таким именем уже существует",
"generic_error": "Произошла ошибка"
"generic_error": "Произошла ошибка",
"group_name_invalid": "Имя группы должно соответствовать формату префикса эл. почты (буквы, цифры, точка, дефис, подчёркивание; 1–64 символов).",
"group_cycle": "Этот участник создаст циклическую ссылку между группами.",
"group_depth_exceeded": "Глубина вложенности превышает допустимый максимум (8).",
"group_virtual_immutable": "Группа «Internal» управляется системой и не может быть изменена.",
"group_not_found": "Группа не найдена.",
"group_name_taken": "Группа с таким именем уже существует."
},
"breadcrumb": {
"home": "Главная"
@@ -755,5 +762,31 @@
"today": "Сегодня",
"last7days": "Последние 7 дней",
"last30days": "Последние 30 дней"
},
"groups": {
"title": "Управление группами",
"create_button": "Создать группу",
"create_dialog_title": "Новая группа",
"edit_dialog_title": "Переименовать группу",
"name_label": "Имя",
"name_placeholder": "инженеры",
"description_label": "Описание (необязательно)",
"members_section": "Участники",
"add_member_placeholder": "Добавить пользователя или группу…",
"no_members": "Пока нет участников.",
"remove_member": "Удалить",
"delete_group": "Удалить группу",
"delete_confirm": "Удалить группу «{name}»? Все привязанные к ней разрешения будут отозваны.",
"empty_state": "Пока нет групп.",
"load_more": "Загрузить ещё",
"back_to_list": "Назад",
"loading": "Загрузка…",
"virtual_badge": "Системная",
"member_count_zero": "Нет участников",
"member_count_one": "1 участник",
"member_count_other": "{count} участников",
"delete_confirm_label": "Введите имя группы для подтверждения:",
"delete_confirm_mismatch": "Введите имя группы точно для подтверждения.",
"virtual_internal_name": "Внутренние"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "淺色",
"dark": "深色",
"auto": "跟隨系統"
}
},
"manage_groups": "管理群組"
},
"share": {
"dialogTitle": "共享連結",
@@ -336,7 +337,13 @@
"move_error": "移動時出錯",
"empty_name": "名稱不能為空",
"name_exists": "已存在同名檔案或資料夾",
"generic_error": "發生錯誤"
"generic_error": "發生錯誤",
"group_name_invalid": "群組名稱必須符合電子郵件前綴格式(字母、數字、點、連字符、下劃線;1–64 個字元)。",
"group_cycle": "此成員會在群組之間形成循環參照。",
"group_depth_exceeded": "嵌套深度超過允許的最大值(8)。",
"group_virtual_immutable": "「Internal」群組由系統管理,無法修改。",
"group_not_found": "找不到群組。",
"group_name_taken": "已存在同名群組。"
},
"breadcrumb": {
"home": "主頁"
@@ -755,5 +762,31 @@
"today": "今天",
"last7days": "近7天",
"last30days": "近30天"
},
"groups": {
"title": "管理群組",
"create_button": "建立群組",
"create_dialog_title": "新群組",
"edit_dialog_title": "重新命名群組",
"name_label": "名稱",
"name_placeholder": "engineering",
"description_label": "描述(選填)",
"members_section": "成員",
"add_member_placeholder": "新增使用者或群組…",
"no_members": "尚無成員。",
"remove_member": "移除",
"delete_group": "刪除群組",
"delete_confirm": "刪除群組「{name}」?引用此群組的所有授權將被撤銷。",
"empty_state": "尚無群組。",
"load_more": "載入更多",
"back_to_list": "返回",
"loading": "載入中…",
"virtual_badge": "系統",
"member_count_zero": "無成員",
"member_count_one": "1 個成員",
"member_count_other": "{count} 個成員",
"delete_confirm_label": "請輸入群組名稱以確認:",
"delete_confirm_mismatch": "請準確輸入群組名稱以確認。",
"virtual_internal_name": "內部"
}
}
+35 -2
View File
@@ -131,7 +131,8 @@
"light": "浅色",
"dark": "深色",
"auto": "跟随系统"
}
},
"manage_groups": "管理群组"
},
"share": {
"dialogTitle": "共享链接",
@@ -336,7 +337,13 @@
"move_error": "移动时出错",
"empty_name": "名称不能为空",
"name_exists": "已存在同名文件或文件夹",
"generic_error": "发生错误"
"generic_error": "发生错误",
"group_name_invalid": "组名必须符合邮件前缀格式(字母、数字、点、连字符、下划线;1–64个字符)。",
"group_cycle": "此成员会在组之间形成循环引用。",
"group_depth_exceeded": "嵌套深度超出允许的最大值(8)。",
"group_virtual_immutable": "“Internal”组由系统管理,无法修改。",
"group_not_found": "未找到组。",
"group_name_taken": "同名组已存在。"
},
"breadcrumb": {
"home": "主页"
@@ -755,5 +762,31 @@
"today": "今天",
"last7days": "近7天",
"last30days": "近30天"
},
"groups": {
"title": "管理群组",
"create_button": "创建群组",
"create_dialog_title": "新群组",
"edit_dialog_title": "重命名群组",
"name_label": "名称",
"name_placeholder": "engineering",
"description_label": "描述(可选)",
"members_section": "成员",
"add_member_placeholder": "添加用户或群组…",
"no_members": "暂无成员。",
"remove_member": "移除",
"delete_group": "删除群组",
"delete_confirm": "删除群组 \"{name}\"?引用此群组的所有权限将被撤销。",
"empty_state": "暂无群组。",
"load_more": "加载更多",
"back_to_list": "返回",
"loading": "加载中…",
"virtual_badge": "系统",
"member_count_zero": "无成员",
"member_count_one": "1 个成员",
"member_count_other": "{count} 个成员",
"delete_confirm_label": "请输入群组名称以确认:",
"delete_confirm_mismatch": "请准确输入群组名称以确认。",
"virtual_internal_name": "内部"
}
}