Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
973 changes: 973 additions & 0 deletions console/app/pages/admin/onboarding.vue

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions console/app/utils/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ export const ADMIN_VIEW: NavSection = {
labelKey: 'nav.adminView',
adminOnly: true,
entries: [
{
to: '/admin/onboarding',
labelKey: 'nav.onboarding',
// A door with an arrow going into it: a bot being let into a server,
// which is the one step of this page that happens anywhere else.
// Deliberately not a cog — the cog is Bot Settings, and this page is
// not a second place to configure a guild but the place where a
// guild becomes configurable at all.
icon: 'M10 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h5v-2H5V5h5V3Zm5.6 3.6-1.4 1.4 3 3H8v2h9.2l-3 3 1.4 1.4L21 12l-5.4-5.4Z',
adminOnly: true,
},
{
to: '/admin/bot-settings',
labelKey: 'nav.botSettings',
Expand Down
574 changes: 574 additions & 0 deletions console/app/utils/onboarding.ts

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions console/i18n/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ matches the file that renders it:
| `recordings.*` | `pages/recordings/*` and the components under them |
| `calendar.*` | `pages/calendar.vue`, the heatmap and the timeline |
| `settings.*` | `pages/settings.vue` — a person's own settings |
| `admin.onboarding.*` | `pages/admin/onboarding.vue`, `utils/onboarding.ts` |
| `admin.settings.*` | `pages/admin/bot-settings.vue` |
| `admin.destinations.*` | `pages/admin/destinations.vue`, `utils/exportTargets.ts`, the two `ExportTarget*` components |
| `admin.consents.*` | `pages/admin/consents.vue` |
Expand Down Expand Up @@ -77,6 +78,14 @@ scope on a roster row — so that the sweep has less to do rather than more.
New strings on that page go through `$t` from now on; the existing ones move
when the sweep reaches them.

`admin.onboarding.*` is complete from the start for the same reason
`admin.destinations.*` is, and nothing under it will ever be reached by the
sweep. Three of its sentences carry a value the API composed rather than one
this console decided — the bot's own failure text, a channel's name, a
Discord id — and each of those is rendered beside a translated sentence
instead of inside one, because a sentence with somebody else's prose glued
into the middle of it cannot be re-ordered in German.

`admin.destinations.*` is the one administrative namespace that is complete
from the start, because the page under it is new: nothing on
`/admin/destinations` was ever hard-coded English, so there is nothing there
Expand Down
93 changes: 92 additions & 1 deletion console/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"queue": "Warteschlange",
"reporting": "Auswertung",
"consents": "Einwilligungen",
"destinations": "Ziele"
"destinations": "Ziele",
"onboarding": "Server-Einrichtung"
},
"auth": {
"signIn": "Anmelden",
Expand Down Expand Up @@ -741,6 +742,96 @@
"fallbackInUse": "Hier ist kein Ziel eingeschaltet, deshalb veröffentlicht dieser Server weiterhin dorthin, wohin document_target in den Bot-Einstellungen zeigt: ein Outline-Dokument je Besprechung. Ein hier eingeschaltetes Ziel übernimmt das vollständig.",
"fallbackReplaced": "Dieser Server veröffentlicht an das eine Ziel oben, und document_target in den Bot-Einstellungen wird dafür nicht mehr benutzt — die Ziele hier ersetzen jene Einstellung, statt sie zu ergänzen. | Dieser Server veröffentlicht an die {count} Ziele oben, und document_target in den Bot-Einstellungen wird dafür nicht mehr benutzt — die Ziele hier ersetzen jene Einstellung, statt sie zu ergänzen.",
"fallbackLink": "Bot-Einstellungen öffnen"
},
"onboarding": {
"title": "Einen Server einrichten",
"intro": "Sturnus wird eingerichtet, indem der Bot darum gebeten wird. Diese Konsole besitzt kein Discord-Token und wird nie eines besitzen, also hält sie fest, was gelten soll; der nächste Durchlauf des Bots — etwa zehn Sekunden — setzt es um und trägt das Ergebnis zurück.",
"inviteHeading": "1. Den Bot in den Server holen",
"inviteBody": "Der einzige Schritt, der wirklich im Browser stattfindet, und der Schritt, auf den alle übrigen warten. Solange der Bot nicht im Server ist, spiegelt er nichts, und alles Weitere hat nichts anzuzeigen.",
"inviteAction": "Sturnus zu einem Server hinzufügen",
"inviteNewTab": "Öffnet Discord in einem neuen Tab",
"inviteFailed": "Der Einladungslink konnte nicht gelesen werden.",
"inviteMissingHeading": "Diese Installation hat keinen Einladungslink",
"inviteMissingBody": "Hier ist keine Discord-Anwendungs-ID hinterlegt, aus der sich ein Link bauen ließe. Stattdessen einen im URL-Generator von Discord mit den beiden Werten unten erzeugen — oder beim Betrieb dieser Installation {variable} setzen lassen.",
"inviteScopes": "Anzuhakende Scopes",
"invitePermissions": "Berechtigungen, als die Zahl aus dem Generator von Discord",
"roleOrderHeading": "Vor dem Verlassen von Discord: eine Rolle verschieben",
"roleOrder": "„Rollen verwalten“ in der Einladung genügt allein nicht. Die eigene Rolle des Bots muss in den Servereinstellungen → Rollen über der Einwilligungsrolle stehen, sonst verweigert Discord deren Anlage — und keine Berechtigungszahl kann das ausdrücken, weshalb auch ein Server mit sämtlichen erteilten Berechtigungen hier scheitern kann. Das geht zuletzt schief und lässt sich am leichtesten erledigen, solange Discord ohnehin offen ist.",
"serverHeading": "2. Den Server auswählen",
"whichServer": "Welcher Server",
"serversFailed": "Die Serverliste konnte nicht gelesen werden.",
"noneYetHeading": "Noch kein Server zum Einrichten",
"noneYetBody": "Ein Server erscheint hier, sobald der Bot ihm beigetreten ist und ihn einmal erfasst hat — etwa zehn Sekunden nach Annahme der Einladung.",
"noneYetRole": "Ist der Bot schon länger im Server, prüfen, ob das hier angemeldete Konto die Rolle besitzt, die {setting} benennt.",
"configureHeading": "3. Festlegen, was aufgezeichnet wird",
"configureBody": "Ein angehakter Kanal bedeutet zwei Berechtigungsausnahmen darin: „Sprechen“ für {'@'}everyone verboten, „Sprechen“ für die Einwilligungsrolle erlaubt. Dieses Paar ist der gesamte Einwilligungsschutz — es macht aus dem Aufgezeichnetwerden etwas, wofür man sich entscheidet, statt etwas, das einem widerfährt.",
"channelsLabel": "Aufzuzeichnende Kanäle",
"alreadyRecorded": "wird bereits aufgezeichnet",
"alreadyRecordedNote": "Was dieser Server bereits aufzeichnet, ist angehakt und lässt sich hier nicht abwählen, denn das Einrichten ergänzt diese Liste und nimmt nie etwas davon weg. Einen Kanal entfernt man über {setting} in den Bot-Einstellungen.",
"staleHeading": "{count} aufgezeichneter Kanal fehlt im Spiegel | {count} aufgezeichnete Kanäle fehlen im Spiegel",
"staleBody": "Der Bot sieht sie nicht, und eine Anfrage, die einen für den Bot unsichtbaren Kanal nennt, scheitert im Ganzen — deshalb lässt diese Anfrage sie weg. Bei Gelegenheit über {setting} in den Bot-Einstellungen entfernen.",
"waitingHeading": "Diesen Server hat noch niemand angesehen",
"waitingBody": "Es wurde noch nichts darüber gespiegelt, deshalb gibt es keine Kanalliste anzuzeigen. Das ist kein Server ohne Räume, sondern ein Server, den noch nichts gelesen hat. Die Seite fragt weiter nach und ergänzt sich von selbst.",
"emptyHeading": "Dieser Server hat keine Sprachkanäle",
"emptyBody": "Der Bot hat ihn erfasst und keine gefunden — das ist also der Server, wie er ist, und keine Liste, die nicht geladen hat. Einen Sprachkanal in Discord anlegen; er erscheint hier nach dem nächsten Durchlauf.",
"unreadableHeading": "Die Kanalnamen konnten nicht gelesen werden",
"unreadableBody": "Der Bot hat diesen Server erfasst, es gibt also eine Kanalliste; diese Konsole konnte sie nur nicht abrufen. Am Server selbst ist nichts falsch.",
"roleNameLabel": "Einwilligungsrolle",
"roleNameHint": "Leer lassen, um die vorhandene Rolle dieses Servers zu behalten oder Sturnus eine anlegen zu lassen, falls keine da ist. Ein Name verlangt genau die so benannte Rolle und legt sie an, wenn es keine gibt — verglichen wird exakt, denn „Aufgezeichnet“ und „aufgezeichnet“ sind in Discord zwei verschiedene Rollen.",
"roleNamePlaceholder": "Leer lassen, um nichts zu benennen",
"needChannel": "Mindestens einen Kanal anhaken. Eine Anfrage ohne Kanal wird abgelehnt.",
"roleTooLong": "Discord erlaubt höchstens {limit} Zeichen in einem Rollennamen.",
"submit": "Den Bot bitten, diesen Server einzurichten",
"submitting": "Wird angefragt …",
"requestHeading": "4. Was daraus wurde",
"loading": "Einrichtung dieses Servers wird gelesen",
"loadFailed": "Die Einrichtung dieses Servers konnte nicht gelesen werden.",
"status": {
"waiting": "wartet",
"stalled": "nicht begonnen",
"good": "erledigt",
"bad": "gescheitert",
"neutral": "ersetzt",
"unknown": "Ergebnis {status}"
},
"heading": {
"waiting": "Angefragt, und es wird auf den Bot gewartet",
"stalled": "Daran wird vorerst nichts arbeiten",
"good": "Dieser Server ist eingerichtet",
"bad": "Der Bot konnte es nicht zu Ende bringen",
"neutral": "Diese Anfrage wurde ersetzt, bevor irgendetwas daran geschah",
"unknown": "Auf eine Weise abgeschlossen, für die diese Seite kein Wort hat"
},
"waitingNote": "Der Bot nimmt neue Anfragen in seinem normalen Durchlauf auf, binnen etwa zehn Sekunden. Diese Seite wartet auf die Antwort.",
"stalledNote": "Über diesen Server wurde noch nie etwas gespiegelt, und das ist dieselbe Tatsache wie: der Bot ist nicht darin. Eine Anfrage in einem Server, dem der Bot nicht beigetreten ist, wird gar nicht erst versucht — sie wartet, ohne zu scheitern, bis der Bot ankommt. Schritt 1 ist es, worauf sie wartet.",
"appliedNote": "Die Einwilligungsrolle, die Sprechen-Ausnahmen in jedem angefragten Kanal und die Liste der aufgezeichneten Kanäle wurden alle geschrieben.",
"appliedNext": "Zwei Dinge entscheidet das Einrichten nie: wohin ein Protokoll veröffentlicht wird und auf welche Datenschutzerklärung sich die Einwilligung in diesem Server bezieht. Beides wird auf den Seiten unten gesetzt, und ohne beides ist die Aufzeichnung nicht fertig eingerichtet.",
"failedTerminal": "Ein Versuch schließt eine Anfrage ab, wie er auch ausgegangen ist — diese hier ist also vorbei, nichts läuft im Hintergrund nach, und es gibt keine Wartezeit abzusitzen. Beheben, was der Bericht unten benennt, und erneut anfragen: das ist eine neue Anfrage und wird als eigene festgehalten.",
"supersededNote": "Eine neuere Anfrage traf ein, bevor der Bot diese hier erreichte, deshalb wurde sie nie versucht und hat am Server nichts verändert. Es ist nichts schiefgegangen. Zwei Aussagen darüber, was gelten soll, ergänzen sich nicht, also gewinnt die neueste vollständig — beide nacheinander anzuwenden hätte auf der älteren geendet, und das wäre eine Korrektur, die von dem Fehler überschrieben wird, den sie korrigiert.",
"unknownNote": "Der Bot hat ein Ergebnis vermerkt, das es beim Schreiben dieser Seite noch nicht gab. Abgeschlossen ist es in jedem Fall; der hier laufende Bot ist neuer als diese Konsole.",
"replacedYours": "Das ist nicht die aus diesem Browser abgeschickte Anfrage. Danach hat jemand anderes angefragt, und die neueste Anfrage ist die, nach der der Bot handelt — was folgt, beschreibt also deren Verlauf.",
"askedByYou": "Eigene Anfrage",
"askedBy": "Angefragt von {who}",
"askedByUnresolved": "Angefragt von {id}, wofür der Spiegel dieses Servers keinen Namen hat",
"askedAt": "Angefragt {moment}",
"settledAt": "Abgeschlossen {moment}",
"askedChannelsLabel": "Angefragte Kanäle",
"askedRoleLabel": "Angefragte Einwilligungsrolle",
"askedRoleNone": "Keine benannt, womit die vorhandene Rolle des Servers bleibt",
"errorHeading": "Was der Bot berichtet hat, in seinen eigenen Worten",
"resubmitReplaces": "Eine erneute Anfrage ersetzt die laufende, statt sich dahinter einzureihen — der Bot wendet die neueste an und legt die übrigen beiseite. Einen vertippten Kanal zu korrigieren heißt also nicht, einen Durchlauf abwarten zu müssen.",
"resubmitAfterFailure": "Erneut anzufragen ist der Weg, einer behobenen Berechtigung einen weiteren Versuch zu geben. Von selbst wiederholt sich nichts.",
"resubmitAgain": "Eine erneute Anfrage schreibt einen neuen Eintrag, den der Bot im nächsten Durchlauf anwendet.",
"watchingLive": "Wird alle paar Sekunden geprüft",
"watchingStopped": "Die Prüfung wurde nach fünf Minuten beendet. Verloren ist nichts — unten erneut nachsehen.",
"refresh": "Jetzt nachsehen",
"toBotSettings": "Bot-Einstellungen",
"toDestinations": "Ziele",
"errorRefused": "Die API hat die Anfrage abgelehnt.",
"errorSession": "Diese Sitzung ist beendet. Bitte neu anmelden.",
"errorGone": "Dieser Server antwortet, als gäbe es ihn nicht — dieselbe Antwort gilt für einen Server, den hier niemand verwaltet. Prüfen, ob der Bot noch darin ist.",
"errorUnreachable": "Die API war nicht erreichbar.",
"errorStatus": "Die API hat mit {status} geantwortet."
}
},
"ui": {
Expand Down
Loading
Loading