feat(app,learn,todo): the operator's "This instance" card, screen and badge (ADR 0021, step 1)

Whoever operates the instance approves, refuses and suspends accounts
and names other operators in the app (D21 to D24, D34):

- halkyon_app: InstanceOperatorRepository on
  ServerpodInstanceOperatorGateway (the module's instanceOperator
  endpoint; refusals as OperatorFailed: notFound, isOperator,
  lastOperator, notAllowed for 401 and 403, failed), in AppDependencies.
  OperatingCubit counts the accounts that wait: asked as the person's
  app opens, after every change, and every 5 minutes only while they
  operate the instance, so nobody else's app keeps asking.
  InstanceOperatorCard (or its tiles) and WaitingAccountsBadge show
  nothing at all for anyone else. InstanceOperatorScreen, laid out as
  Settings: the accounts that wait, each showing its four words to read
  out before Approve (D33), Refuse for new ones after asking; who
  operates, Take back after asking, the last always kept; Name an
  operator by handle; Find an account by the start of its handle, with
  Suspend after asking and Name as operator. English and German texts
  ("Admin" as the role word in German).
- Learn: the card right after the Sync card in Settings, which the
  cogs' count leads to as their dot leads to Sync; the count on the
  Settings cogs of Home and Profile.
- Todo: the tiles in the account sheet and the count on its button.
  Todo's server is a member, whose `operating()` is always null, so
  nothing shows there until it holds the register.

Tests: the gateway's mapping, the repository, both cubits with their
denials, the card, the badge and the screen; Learn's Settings shows the
card and the count to an operator and neither to anyone else.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-25 15:55:28 +01:00
commit 31b9c17850
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
5 changed files with 2999 additions and 28 deletions

View file

@ -216,7 +216,7 @@
"passwordInstanceUnproven": "Die Instanz konnte nicht beweisen, dass sie dein Passwort kennt, daher vertraut dieses Gerät ihr nicht. Versuch es noch einmal; passiert es wieder, ist die Instanz nicht die, die sie zu sein behauptet.",
"passwordKeysMissing": "Die Schlüssel deines Kontos sind nicht auf diesem Gerät. Melde dich hier ab und mit deinem Passwort wieder an.",
"signUpsClosed": "Diese Instanz nimmt keine neuen Konten an.",
"signUpsTooManyWaiting": "Es warten schon so viele neue Konten auf ihre Freigabe, wie dürfen. Versuch es später noch einmal.",
"signUpsTooManyWaiting": "Es warten schon zu viele neue Konten auf ihre Freigabe. Versuch es später noch einmal.",
"passwordUnsafeCosts": "Die Instanz wollte dein Passwort auf eine Weise prüfen lassen, die kein Konto nutzt, daher wurde nichts gesendet. Passiert es wieder, ist die Instanz nicht die, die sie zu sein behauptet.",
"passwordFailed": "Die Instanz war nicht erreichbar. Prüf die Verbindung und versuch es noch einmal.",
"passwordMinLength": "Mindestens {count} Zeichen",
@ -309,5 +309,41 @@
"simpleLoginSectionTitle": "SimpleLogin",
"simpleLoginSignsYouIn": "Meldet dich an",
"simpleLoginAddHint": "Melde dich mit SimpleLogin an, oder mit deinem Proton-Konto.",
"simpleLoginAdded": "SimpleLogin hinzugefügt."
"simpleLoginAdded": "SimpleLogin hinzugefügt.",
"operatorTitle": "Diese Instanz",
"operatorAccounts": "Konten und Admins",
"operatorWaitingCount": "{count, plural, =0{Niemand wartet auf Freigabe} =1{1 Konto wartet auf Freigabe} other{{count} Konten warten auf Freigabe}}",
"operatorWaitingTitle": "Wartend",
"operatorNobodyWaits": "Niemand wartet.",
"operatorNoHandle": "Noch kein Handle",
"operatorNewSince": "Neu, wartet seit {date}",
"operatorSuspendedSince": "Gesperrt seit {date}",
"operatorApproveNote": "Lies diese vier Wörter vor, und gib das Konto erst frei, wenn dir bestätigt wird, dass genau diese auf dem Bildschirm stehen.",
"operatorApprove": "Freigeben",
"operatorRefuse": "Ablehnen",
"operatorRefuseTitle": "Dieses Konto ablehnen?",
"operatorRefuseMessage": "Es wird mit allem gelöscht, was darin ist. Eine neue Anmeldung bleibt möglich.",
"operatorOperatorsTitle": "Admins",
"operatorTakeBack": "Entziehen",
"operatorTakeBackTitle": "Die Rolle entziehen?",
"operatorTakeBackMessage": "Das Konto bleibt, kann hier aber keine Konten mehr freigeben, ablehnen oder sperren.",
"operatorAppoint": "Admin ernennen",
"operatorAppointMessage": "Admins geben hier Konten frei, lehnen sie ab, sperren sie und ernennen Admins, so wie du.",
"operatorAppointConfirm": "Ernennen",
"operatorHandle": "Handle",
"operatorFindTitle": "Ein Konto finden",
"operatorFoundNone": "Kein Handle beginnt so.",
"operatorMadeOn": "Seit {date}",
"operatorIsOperator": "Admin",
"operatorIsWaiting": "Wartend",
"operatorIsSuspended": "Gesperrt",
"operatorSuspend": "Sperren",
"operatorSuspendTitle": "Dieses Konto sperren?",
"operatorSuspendMessage": "Es wird überall abgemeldet und kann sich erst wieder anmelden, wenn du es freigibst. Nichts darin wird gelöscht.",
"operatorMakeOperator": "Zum Admin ernennen",
"operatorNotFound": "Dieses Konto gibt es nicht mehr, oder es wartet nicht.",
"operatorIsOperatorProblem": "Admins können nicht gesperrt werden. Entzieh zuerst die Rolle.",
"operatorLastOperator": "Die Instanz braucht mindestens einen Admin.",
"operatorNotAllowed": "Das können nur die Admins der Instanz.",
"operatorFailed": "Das hat nicht geklappt. Versuch es noch einmal."
}

View file

@ -541,7 +541,7 @@
"@signUpsClosed": {
"description": "A sign-up refused: the operator takes no new accounts (D19)."
},
"signUpsTooManyWaiting": "As many new accounts wait for approval as may. Try again later.",
"signUpsTooManyWaiting": "Too many new accounts already wait for approval. Try again later.",
"@signUpsTooManyWaiting": {
"description": "A sign-up refused: ten new accounts wait for the operator's approval already (D19)."
},
@ -742,5 +742,169 @@
"simpleLoginSectionTitle": "SimpleLogin",
"simpleLoginSignsYouIn": "Signs you in",
"simpleLoginAddHint": "Sign in with SimpleLogin, or with your Proton account.",
"simpleLoginAdded": "SimpleLogin added."
"simpleLoginAdded": "SimpleLogin added.",
"operatorTitle": "This instance",
"@operatorTitle": {
"description": "The card and screen for whoever operates the instance (ADR 0021, D34)."
},
"operatorAccounts": "Accounts and operators",
"@operatorAccounts": {
"description": "The tile leading to the operator's screen."
},
"operatorWaitingCount": "{count, plural, =0{Nobody waits for approval} =1{1 account waits for approval} other{{count} accounts wait for approval}}",
"@operatorWaitingCount": {
"description": "How many accounts wait for the operator; also the badge's label.",
"placeholders": {
"count": {
"type": "int"
}
}
},
"operatorWaitingTitle": "Waiting",
"@operatorWaitingTitle": {
"description": "The card of accounts that wait for approval, new or suspended."
},
"operatorNobodyWaits": "Nobody waits.",
"@operatorNobodyWaits": {
"description": "The waiting card, empty."
},
"operatorNoHandle": "No handle yet",
"@operatorNoHandle": {
"description": "An account without a handle, where its handle would be."
},
"operatorNewSince": "New, waiting since {date}",
"@operatorNewSince": {
"description": "A new account that waits, and since when.",
"placeholders": {
"date": {
"type": "String"
}
}
},
"operatorSuspendedSince": "Suspended since {date}",
"@operatorSuspendedSince": {
"description": "A suspended account, and since when.",
"placeholders": {
"date": {
"type": "String"
}
}
},
"operatorApproveNote": "Read them these four words, and approve only once they confirm these are on their screen.",
"@operatorApproveNote": {
"description": "Before approving: the words prove it is their account that waits (D33)."
},
"operatorApprove": "Approve",
"@operatorApprove": {
"description": "Approves a waiting account."
},
"operatorRefuse": "Refuse",
"@operatorRefuse": {
"description": "Refuses a new account: deleted."
},
"operatorRefuseTitle": "Refuse this account?",
"@operatorRefuseTitle": {
"description": "The question before refusing."
},
"operatorRefuseMessage": "It is deleted with everything it has. They can sign up again.",
"@operatorRefuseMessage": {
"description": "What refusing does."
},
"operatorOperatorsTitle": "Operators",
"@operatorOperatorsTitle": {
"description": "The card of who operates the instance."
},
"operatorTakeBack": "Take back",
"@operatorTakeBack": {
"description": "Takes back the operator's role."
},
"operatorTakeBackTitle": "Take back the role?",
"@operatorTakeBackTitle": {
"description": "The question before taking the role back."
},
"operatorTakeBackMessage": "They keep their account, but no longer approve, refuse or suspend accounts here.",
"@operatorTakeBackMessage": {
"description": "What taking the role back does."
},
"operatorAppoint": "Name an operator",
"@operatorAppoint": {
"description": "Names an account an operator, by its handle."
},
"operatorAppointMessage": "They approve, refuse and suspend accounts here, and name operators, as you do.",
"@operatorAppointMessage": {
"description": "What an operator may do."
},
"operatorAppointConfirm": "Name",
"@operatorAppointConfirm": {
"description": "Confirms naming an operator."
},
"operatorHandle": "Handle",
"@operatorHandle": {
"description": "The field for an account's handle."
},
"operatorFindTitle": "Find an account",
"@operatorFindTitle": {
"description": "The card searching accounts by the start of their handle."
},
"operatorFoundNone": "No account's handle starts like this.",
"@operatorFoundNone": {
"description": "A search that found nothing."
},
"operatorMadeOn": "Since {date}",
"@operatorMadeOn": {
"description": "When an account was made.",
"placeholders": {
"date": {
"type": "String"
}
}
},
"operatorIsOperator": "Operator",
"@operatorIsOperator": {
"description": "A tag: the account operates the instance."
},
"operatorIsWaiting": "Waiting",
"@operatorIsWaiting": {
"description": "A tag: the account waits for approval."
},
"operatorIsSuspended": "Suspended",
"@operatorIsSuspended": {
"description": "A tag: the account is suspended."
},
"operatorSuspend": "Suspend",
"@operatorSuspend": {
"description": "Suspends an account."
},
"operatorSuspendTitle": "Suspend this account?",
"@operatorSuspendTitle": {
"description": "The question before suspending."
},
"operatorSuspendMessage": "They are signed out everywhere and can't sign in until you approve them again. Nothing they have is deleted.",
"@operatorSuspendMessage": {
"description": "What suspending does."
},
"operatorMakeOperator": "Name as operator",
"@operatorMakeOperator": {
"description": "Names a found account an operator."
},
"operatorNotFound": "That account isn't there any more, or doesn't wait.",
"@operatorNotFound": {
"description": "Refused: no such account, or it doesn't wait."
},
"operatorIsOperatorProblem": "An operator can't be suspended. Take back their role first.",
"@operatorIsOperatorProblem": {
"description": "Refused: suspending an operator."
},
"operatorLastOperator": "The instance needs at least one operator.",
"@operatorLastOperator": {
"description": "Refused: taking back the last operator's role."
},
"operatorNotAllowed": "Only the instance's operators can do this.",
"@operatorNotAllowed": {
"description": "Refused: the person doesn't operate the instance."
},
"operatorFailed": "That didn't work. Try again.",
"@operatorFailed": {
"description": "Any other failure."
}
}

View file

@ -1402,7 +1402,7 @@ abstract class HalkyonAppLocalizations {
/// A sign-up refused: ten new accounts wait for the operator's approval already (D19).
///
/// In en, this message translates to:
/// **'As many new accounts wait for approval as may. Try again later.'**
/// **'Too many new accounts already wait for approval. Try again later.'**
String get signUpsTooManyWaiting;
/// No description provided for @passwordUnsafeCosts.
@ -1962,6 +1962,222 @@ abstract class HalkyonAppLocalizations {
/// In en, this message translates to:
/// **'SimpleLogin added.'**
String get simpleLoginAdded;
/// The card and screen for whoever operates the instance (ADR 0021, D34).
///
/// In en, this message translates to:
/// **'This instance'**
String get operatorTitle;
/// The tile leading to the operator's screen.
///
/// In en, this message translates to:
/// **'Accounts and operators'**
String get operatorAccounts;
/// How many accounts wait for the operator; also the badge's label.
///
/// In en, this message translates to:
/// **'{count, plural, =0{Nobody waits for approval} =1{1 account waits for approval} other{{count} accounts wait for approval}}'**
String operatorWaitingCount(int count);
/// The card of accounts that wait for approval, new or suspended.
///
/// In en, this message translates to:
/// **'Waiting'**
String get operatorWaitingTitle;
/// The waiting card, empty.
///
/// In en, this message translates to:
/// **'Nobody waits.'**
String get operatorNobodyWaits;
/// An account without a handle, where its handle would be.
///
/// In en, this message translates to:
/// **'No handle yet'**
String get operatorNoHandle;
/// A new account that waits, and since when.
///
/// In en, this message translates to:
/// **'New, waiting since {date}'**
String operatorNewSince(String date);
/// A suspended account, and since when.
///
/// In en, this message translates to:
/// **'Suspended since {date}'**
String operatorSuspendedSince(String date);
/// Before approving: the words prove it is their account that waits (D33).
///
/// In en, this message translates to:
/// **'Read them these four words, and approve only once they confirm these are on their screen.'**
String get operatorApproveNote;
/// Approves a waiting account.
///
/// In en, this message translates to:
/// **'Approve'**
String get operatorApprove;
/// Refuses a new account: deleted.
///
/// In en, this message translates to:
/// **'Refuse'**
String get operatorRefuse;
/// The question before refusing.
///
/// In en, this message translates to:
/// **'Refuse this account?'**
String get operatorRefuseTitle;
/// What refusing does.
///
/// In en, this message translates to:
/// **'It is deleted with everything it has. They can sign up again.'**
String get operatorRefuseMessage;
/// The card of who operates the instance.
///
/// In en, this message translates to:
/// **'Operators'**
String get operatorOperatorsTitle;
/// Takes back the operator's role.
///
/// In en, this message translates to:
/// **'Take back'**
String get operatorTakeBack;
/// The question before taking the role back.
///
/// In en, this message translates to:
/// **'Take back the role?'**
String get operatorTakeBackTitle;
/// What taking the role back does.
///
/// In en, this message translates to:
/// **'They keep their account, but no longer approve, refuse or suspend accounts here.'**
String get operatorTakeBackMessage;
/// Names an account an operator, by its handle.
///
/// In en, this message translates to:
/// **'Name an operator'**
String get operatorAppoint;
/// What an operator may do.
///
/// In en, this message translates to:
/// **'They approve, refuse and suspend accounts here, and name operators, as you do.'**
String get operatorAppointMessage;
/// Confirms naming an operator.
///
/// In en, this message translates to:
/// **'Name'**
String get operatorAppointConfirm;
/// The field for an account's handle.
///
/// In en, this message translates to:
/// **'Handle'**
String get operatorHandle;
/// The card searching accounts by the start of their handle.
///
/// In en, this message translates to:
/// **'Find an account'**
String get operatorFindTitle;
/// A search that found nothing.
///
/// In en, this message translates to:
/// **'No account\'s handle starts like this.'**
String get operatorFoundNone;
/// When an account was made.
///
/// In en, this message translates to:
/// **'Since {date}'**
String operatorMadeOn(String date);
/// A tag: the account operates the instance.
///
/// In en, this message translates to:
/// **'Operator'**
String get operatorIsOperator;
/// A tag: the account waits for approval.
///
/// In en, this message translates to:
/// **'Waiting'**
String get operatorIsWaiting;
/// A tag: the account is suspended.
///
/// In en, this message translates to:
/// **'Suspended'**
String get operatorIsSuspended;
/// Suspends an account.
///
/// In en, this message translates to:
/// **'Suspend'**
String get operatorSuspend;
/// The question before suspending.
///
/// In en, this message translates to:
/// **'Suspend this account?'**
String get operatorSuspendTitle;
/// What suspending does.
///
/// In en, this message translates to:
/// **'They are signed out everywhere and can\'t sign in until you approve them again. Nothing they have is deleted.'**
String get operatorSuspendMessage;
/// Names a found account an operator.
///
/// In en, this message translates to:
/// **'Name as operator'**
String get operatorMakeOperator;
/// Refused: no such account, or it doesn't wait.
///
/// In en, this message translates to:
/// **'That account isn\'t there any more, or doesn\'t wait.'**
String get operatorNotFound;
/// Refused: suspending an operator.
///
/// In en, this message translates to:
/// **'An operator can\'t be suspended. Take back their role first.'**
String get operatorIsOperatorProblem;
/// Refused: taking back the last operator's role.
///
/// In en, this message translates to:
/// **'The instance needs at least one operator.'**
String get operatorLastOperator;
/// Refused: the person doesn't operate the instance.
///
/// In en, this message translates to:
/// **'Only the instance\'s operators can do this.'**
String get operatorNotAllowed;
/// Any other failure.
///
/// In en, this message translates to:
/// **'That didn\'t work. Try again.'**
String get operatorFailed;
}
class _HalkyonAppLocalizationsDelegate

View file

@ -821,7 +821,7 @@ class HalkyonAppLocalizationsDe extends HalkyonAppLocalizations {
@override
String get signUpsTooManyWaiting =>
'Es warten schon so viele neue Konten auf ihre Freigabe, wie dürfen. Versuch es später noch einmal.';
'Es warten schon zu viele neue Konten auf ihre Freigabe. Versuch es später noch einmal.';
@override
String get passwordUnsafeCosts =>
@ -1172,4 +1172,136 @@ class HalkyonAppLocalizationsDe extends HalkyonAppLocalizations {
@override
String get simpleLoginAdded => 'SimpleLogin hinzugefügt.';
@override
String get operatorTitle => 'Diese Instanz';
@override
String get operatorAccounts => 'Konten und Admins';
@override
String operatorWaitingCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count Konten warten auf Freigabe',
one: '1 Konto wartet auf Freigabe',
zero: 'Niemand wartet auf Freigabe',
);
return '$_temp0';
}
@override
String get operatorWaitingTitle => 'Wartend';
@override
String get operatorNobodyWaits => 'Niemand wartet.';
@override
String get operatorNoHandle => 'Noch kein Handle';
@override
String operatorNewSince(String date) {
return 'Neu, wartet seit $date';
}
@override
String operatorSuspendedSince(String date) {
return 'Gesperrt seit $date';
}
@override
String get operatorApproveNote =>
'Lies diese vier Wörter vor, und gib das Konto erst frei, wenn dir bestätigt wird, dass genau diese auf dem Bildschirm stehen.';
@override
String get operatorApprove => 'Freigeben';
@override
String get operatorRefuse => 'Ablehnen';
@override
String get operatorRefuseTitle => 'Dieses Konto ablehnen?';
@override
String get operatorRefuseMessage =>
'Es wird mit allem gelöscht, was darin ist. Eine neue Anmeldung bleibt möglich.';
@override
String get operatorOperatorsTitle => 'Admins';
@override
String get operatorTakeBack => 'Entziehen';
@override
String get operatorTakeBackTitle => 'Die Rolle entziehen?';
@override
String get operatorTakeBackMessage =>
'Das Konto bleibt, kann hier aber keine Konten mehr freigeben, ablehnen oder sperren.';
@override
String get operatorAppoint => 'Admin ernennen';
@override
String get operatorAppointMessage =>
'Admins geben hier Konten frei, lehnen sie ab, sperren sie und ernennen Admins, so wie du.';
@override
String get operatorAppointConfirm => 'Ernennen';
@override
String get operatorHandle => 'Handle';
@override
String get operatorFindTitle => 'Ein Konto finden';
@override
String get operatorFoundNone => 'Kein Handle beginnt so.';
@override
String operatorMadeOn(String date) {
return 'Seit $date';
}
@override
String get operatorIsOperator => 'Admin';
@override
String get operatorIsWaiting => 'Wartend';
@override
String get operatorIsSuspended => 'Gesperrt';
@override
String get operatorSuspend => 'Sperren';
@override
String get operatorSuspendTitle => 'Dieses Konto sperren?';
@override
String get operatorSuspendMessage =>
'Es wird überall abgemeldet und kann sich erst wieder anmelden, wenn du es freigibst. Nichts darin wird gelöscht.';
@override
String get operatorMakeOperator => 'Zum Admin ernennen';
@override
String get operatorNotFound =>
'Dieses Konto gibt es nicht mehr, oder es wartet nicht.';
@override
String get operatorIsOperatorProblem =>
'Admins können nicht gesperrt werden. Entzieh zuerst die Rolle.';
@override
String get operatorLastOperator =>
'Die Instanz braucht mindestens einen Admin.';
@override
String get operatorNotAllowed => 'Das können nur die Admins der Instanz.';
@override
String get operatorFailed =>
'Das hat nicht geklappt. Versuch es noch einmal.';
}

View file

@ -803,7 +803,7 @@ class HalkyonAppLocalizationsEn extends HalkyonAppLocalizations {
@override
String get signUpsTooManyWaiting =>
'As many new accounts wait for approval as may. Try again later.';
'Too many new accounts already wait for approval. Try again later.';
@override
String get passwordUnsafeCosts =>
@ -1151,6 +1151,138 @@ class HalkyonAppLocalizationsEn extends HalkyonAppLocalizations {
@override
String get simpleLoginAdded => 'SimpleLogin added.';
@override
String get operatorTitle => 'This instance';
@override
String get operatorAccounts => 'Accounts and operators';
@override
String operatorWaitingCount(int count) {
String _temp0 = intl.Intl.pluralLogic(
count,
locale: localeName,
other: '$count accounts wait for approval',
one: '1 account waits for approval',
zero: 'Nobody waits for approval',
);
return '$_temp0';
}
@override
String get operatorWaitingTitle => 'Waiting';
@override
String get operatorNobodyWaits => 'Nobody waits.';
@override
String get operatorNoHandle => 'No handle yet';
@override
String operatorNewSince(String date) {
return 'New, waiting since $date';
}
@override
String operatorSuspendedSince(String date) {
return 'Suspended since $date';
}
@override
String get operatorApproveNote =>
'Read them these four words, and approve only once they confirm these are on their screen.';
@override
String get operatorApprove => 'Approve';
@override
String get operatorRefuse => 'Refuse';
@override
String get operatorRefuseTitle => 'Refuse this account?';
@override
String get operatorRefuseMessage =>
'It is deleted with everything it has. They can sign up again.';
@override
String get operatorOperatorsTitle => 'Operators';
@override
String get operatorTakeBack => 'Take back';
@override
String get operatorTakeBackTitle => 'Take back the role?';
@override
String get operatorTakeBackMessage =>
'They keep their account, but no longer approve, refuse or suspend accounts here.';
@override
String get operatorAppoint => 'Name an operator';
@override
String get operatorAppointMessage =>
'They approve, refuse and suspend accounts here, and name operators, as you do.';
@override
String get operatorAppointConfirm => 'Name';
@override
String get operatorHandle => 'Handle';
@override
String get operatorFindTitle => 'Find an account';
@override
String get operatorFoundNone => 'No account\'s handle starts like this.';
@override
String operatorMadeOn(String date) {
return 'Since $date';
}
@override
String get operatorIsOperator => 'Operator';
@override
String get operatorIsWaiting => 'Waiting';
@override
String get operatorIsSuspended => 'Suspended';
@override
String get operatorSuspend => 'Suspend';
@override
String get operatorSuspendTitle => 'Suspend this account?';
@override
String get operatorSuspendMessage =>
'They are signed out everywhere and can\'t sign in until you approve them again. Nothing they have is deleted.';
@override
String get operatorMakeOperator => 'Name as operator';
@override
String get operatorNotFound =>
'That account isn\'t there any more, or doesn\'t wait.';
@override
String get operatorIsOperatorProblem =>
'An operator can\'t be suspended. Take back their role first.';
@override
String get operatorLastOperator =>
'The instance needs at least one operator.';
@override
String get operatorNotAllowed =>
'Only the instance\'s operators can do this.';
@override
String get operatorFailed => 'That didn\'t work. Try again.';
}
/// The translations for English, as used in the United Kingdom (`en_GB`).