Add Administration, starting with accounts

An account whose Stalwart role manages accounts now finds Administration in
the account menu. It lists, searches, creates and edits accounts -- display
name, other addresses, role, storage limit -- sets a new password, and
deletes, each offered only when the role holds the matching permission.

The server keeps the permissions list from GET /api/account, which it
already called for the edition and threw the rest away. Everything else is
JMAP x:Account, x:Domain and x:Role calls through the existing /api/jmap
proxy, so nothing new is stored and Stalwart decides every call.

Stalwart checks a grant against the caller's permissions but not a password
change or a delete, so an account that outranks the viewer is shown
read-only. Your own password is changed in Settings, which re-seals the
session; changing it here would strand it.

The mock server gains a directory behind the same permission names, with
MOCK_ROLE choosing admin, tenant-admin, helpdesk or user.

68 new strings, translated in all nine catalogues; strings falling back to
English stay at 16.
This commit is contained in:
2026-09-13 15:11:55 -07:00
parent b0564679e6
commit 82e217155b
34 changed files with 2684 additions and 22 deletions
+71
View File
@@ -49,6 +49,75 @@ import type { Catalog } from "@/lib/i18n";
*/
export const catalog: Catalog = {
strings: {
// ── Administration: accounts ───────────────────────────────────
"Change your own password in {settings}.": "Свой пароль можно изменить в разделе {settings}.",
"Administration": "Администрирование",
"Directory": "Каталог",
"User": "Пользователь",
"Administrator": "Администратор",
"Custom role": "Особая роль",
"New account": "Новая учётная запись",
"The people who sign in to mail on the domains you manage.": "Люди, которые входят в почту на доменах, которыми вы управляете.",
"Search by name or address": "Поиск по имени или адресу",
"Search accounts": "Поиск учётных записей",
"No accounts match": "Нет подходящих учётных записей",
"No accounts yet": "Учётных записей пока нет",
"Nothing on your domains matches “{query}”.": "На ваших доменах нет совпадений с «{query}».",
"Open {address}": "Открыть {address}",
"{from}{to} of {total}": "{from}{to} из {total}",
"Previous page": "Предыдущая страница",
"Next page": "Следующая страница",
"Storage": "Хранилище",
"Groups": "Группы",
"{used} · no limit": "{used} · без ограничения",
"Profile": "Профиль",
"Domain": "Домен",
"No domains are available to create an account on.": "Нет доменов, на которых можно создать учётную запись.",
"Sign-in": "Вход",
"Other addresses": "Другие адреса",
"Not in any group": "Не состоит ни в одной группе",
"You can't change your own role.": "Нельзя изменить собственную роль.",
"Only roles whose permissions you hold yourself are offered. On an account inside a tenant, Administrator means administrator of that tenant.": "Предлагаются только роли, все разрешения которых есть у вас самих. Для учётной записи внутри арендатора «Администратор» означает администратора этого арендатора.",
"Limit in GB": "Ограничение в ГБ",
"No limit": "Без ограничения",
"This account has permissions yours doesn't, so you can view it but not change it.": "У этой учётной записи есть разрешения, которых нет у вашей, поэтому её можно просматривать, но не изменять.",
"Your role lets you view accounts but not change them.": "Ваша роль позволяет просматривать учётные записи, но не изменять их.",
"This account has permissions yours doesn't.": "У этой учётной записи есть разрешения, которых нет у вашей.",
"You can't delete the account you're signed in with.": "Нельзя удалить учётную запись, под которой вы вошли.",
"Create account": "Создать учётную запись",
"An account needs an address.": "Учётной записи нужен адрес.",
"Created {address}": "Учётная запись {address} создана",
"Saved {address}": "Учётная запись {address} сохранена",
"Generate a password": "Сгенерировать пароль",
"Pass it on some way other than email to this address.": "Передайте его любым способом, кроме письма на этот адрес.",
"This account has no password. It may sign in through a directory or single sign-on.": "У этой учётной записи нет пароля. Возможно, вход выполняется через каталог или единый вход.",
"Set a new password…": "Задать новый пароль…",
"{name} will be signed out of every app and device using the old password.": "Для {name} будет выполнен выход во всех приложениях и на всех устройствах, где используется старый пароль.",
"New password set for {address}": "Новый пароль для {address} задан",
"Set password": "Задать пароль",
"Remove {address}": "Удалить {address}",
"New address": "Новый адрес",
"another name": "другое имя",
"Mail to these addresses is delivered to this account. Changes apply when you save.": "Письма на эти адреса доставляются в эту учётную запись. Изменения вступят в силу после сохранения.",
"Deletes the mailbox and everything in it.": "Удаляет почтовый ящик и всё его содержимое.",
"Delete account…": "Удалить учётную запись…",
"Delete {address}?": "Удалить {address}?",
"This deletes the mail, calendars, contacts and files in this account. The server removes them in the background, and it can't be undone.": "Будут удалены почта, календари, контакты и файлы этой учётной записи. Сервер удалит их в фоновом режиме, отменить это нельзя.",
"Type {address} to confirm": "Введите {address} для подтверждения",
"Delete account": "Удалить учётную запись",
"Deleted {address}": "Учётная запись {address} удалена",
"The server did not say whether the account was created.": "Сервер не сообщил, создана ли учётная запись.",
"The mail server refused this. Your role may not allow it.": "Почтовый сервер отклонил это действие. Возможно, ваша роль его не допускает.",
"The mail server refused this: {reason}": "Почтовый сервер отклонил это действие: {reason}",
"That address is already in use on this server, as an account, a list or an alias.": "Этот адрес уже используется на сервере — учётной записью, списком или псевдонимом.",
"One of the chosen domain, role or group can't be used for this account.": "Выбранный домен, роль или группу нельзя использовать для этой учётной записи.",
"Your organisation has reached the number of accounts it is allowed.": "Ваша организация достигла допустимого числа учётных записей.",
"Something still depends on this, so the server kept it.": "От этого ещё что-то зависит, поэтому сервер это сохранил.",
"This account no longer exists. Someone may have deleted it.": "Этой учётной записи больше нет. Возможно, её кто-то удалил.",
"The password was not accepted: {reason}": "Пароль не принят: {reason}",
"The password was not accepted.": "Пароль не принят.",
"The mail server rejected a value: {reason}": "Почтовый сервер отклонил значение: {reason}",
"The mail server rejected a value.": "Почтовый сервер отклонил значение.",
"Go to folder…": "Перейти к папке…",
"Set for everyone here. You cannot change this.": "Задано для всех здесь. Изменить нельзя.",
"Export iCAL file": "Экспортировать файл iCAL",
@@ -1350,6 +1419,8 @@ export const catalog: Catalog = {
"no address": "нет адреса",
},
plurals: {
// ── Administration ────────────────────────────────────────────────
"{n} accounts": { one: "{n} учётная запись", few: "{n} учётные записи", many: "{n} учётных записей", other: "{n} учётной записи" },
// ── Third pass ─────────────────────────────────────────────────────
"Delete {n} items": { one: "Удалить {n} объект", few: "Удалить {n} объекта", many: "Удалить {n} объектов", other: "Удалить {n} объекта" },
"Delete {n} items?": { one: "Удалить {n} объект?", few: "Удалить {n} объекта?", many: "Удалить {n} объектов?", other: "Удалить {n} объекта?" },