// Message dictionary en (fallback language): same slugs across en/uk/ru.
export default {
"app.docTitle": "Synapse Admin",
"app.subtitle": "Gnexus notifications hub",
"app.loading": "Loading…",
"common.signOut": "Sign out",
"nav.dashboard": "Overview",
"nav.sources": "Sources",
"nav.types": "Types",
"nav.targets": "Targets",
"nav.rules": "Rules",
"nav.deliveries": "Deliveries",
"nav.mcpKeys": "MCP keys",
"nav.myEvents": "My events",
"nav.settings": "Settings",
"settings.language": "Interface language",
"settings.languageAuto": "Auto",
"settings.languageHelp": "“Auto” means the gnexus-auth account language; a choice here overrides it for Synapse only and survives sign-out.",
"settings.languageSaved": "Language changed",
"dashboard.title": "Overview",
"dashboard.subtitle": "Notification hub status",
"dashboard.loaderChecking": "Checking the service…",
"dashboard.errorUnavailable": "Service unavailable: {message}",
"dashboard.metricService": "Service",
"dashboard.getStartTitle": "Where to start",
"dashboard.getStartText": "Setup order: Sources — register a service and issue it an API key; Targets — where to deliver (internal log, a service over s2s); Rules — which event goes to which target. The Deliveries view shows what actually went out.",
"deliveries.title": "Deliveries",
"deliveries.subtitle": "Attempt log: channel, target, status, retries and the text actually sent to the channel",
"deliveries.filterAll": "all",
"deliveries.filterStatus": "Status",
"deliveries.filterChannel": "Channel",
"deliveries.refresh": "Refresh",
"deliveries.loading": "Loading…",
"deliveries.empty": "No deliveries yet",
"deliveries.colTime": "Time",
"deliveries.colEvent": "Event",
"deliveries.colEventHint": "ID of the event that produced this delivery",
"deliveries.colChannel": "Channel",
"deliveries.colTarget": "Target",
"deliveries.colStatus": "Status",
"deliveries.colStatusHint": "delivered — sent; pending — waiting to send or retry; skipped — filtered out as noise; failed — retries exhausted",
"deliveries.colAttempts": "Attempts",
"deliveries.colAttemptsHint": "How many times a send was attempted (retries 30s → 2min → 10min → 30min)",
"deliveries.colError": "Error",
"deliveries.colMessage": "Message",
"denied.cardTitle": "Access denied",
"denied.cardText": "Synapse settings are available to the admin role and above; the personal area is available via the «My events» link. You usually land here only from an outdated link to the admin section.",
"denied.backToLogin": "Back to sign-in",
"login.title": "Welcome to Synapse",
"login.subtitle": "Sign in to get access to the notification hub",
"login.signInButton": "Sign in with GNEXUS",
"oauth.checkingLabel": "Checking sign-in…",
"myEvents.title": "My events",
"myEvents.subtitle": "Events routed to you personally by routing rules: what happened and what was said about it",
"myEvents.loading": "Loading…",
"myEvents.empty": "No events addressed to you yet: they appear when a routing rule sends an event to the user channel",
"myEvents.colTime": "Time",
"myEvents.colEvent": "Event",
"myEvents.colPriority": "Priority",
"myEvents.priorityTip": "Event priority from the envelope: low, normal, high, critical",
"myEvents.colMessage": "Message",
"sources.pageTitle": "Sources",
"sources.pageSubtitle": "Services that send events to the hub. Description, keys and types live on the source page",
"sources.toastCreated": "Source created",
"sources.toastDeleted": "Source deleted",
"sources.createButton": "Source",
"sources.loading": "Loading…",
"sources.empty": "No sources yet — create the first one",
"sources.colSlug": "Slug",
"sources.colSlugHelp": "The source name in an event (the source field of the envelope). Click opens the source page",
"sources.colLabel": "Label",
"sources.colCreated": "Created",
"sources.rowDelete": "Delete source",
"sources.createTitle": "New source",
"sources.formSlugLabel": "Slug (name)",
"sources.formSlugHelp": "For example monitoring; only a-z 0-9 . _ -",
"sources.formLabelHelp": "Human-readable name",
"sources.formDescriptionLabel": "Description",
"sources.formDescriptionHelp": "What this service is — shown both to humans and to AI agents in the admin panel",
"sources.cancel": "Cancel",
"sources.create": "Create",
"sources.confirmTitle": "Delete source?",
"sources.confirmMessage": "Source \"{name}\" will be deleted together with its types and keys. If the source has events, the deletion will be rejected.",
"sources.delete": "Delete",
"sourceDetail.notFound": "Source not found",
"sourceDetail.toastKeyRevoked": "Key revoked",
"sourceDetail.toastDeleted": "Source deleted",
"sourceDetail.backToList": "Back to sources",
"sourceDetail.kicker": "Synapse · Source",
"sourceDetail.actions": "Actions",
"sourceDetail.issueKey": "Issue key",
"sourceDetail.deleteSource": "Delete source",
"sourceDetail.loading": "Loading…",
"sourceDetail.aboutTitle": "About the service",
"sourceDetail.dtSlug": "Slug",
"sourceDetail.dtName": "Label",
"sourceDetail.dtDescription": "Description",
"sourceDetail.dtCreated": "Created",
"sourceDetail.keysTitle": "API keys",
"sourceDetail.tokenLabel": "Token",
"sourceDetail.tokenNote": " is shown only once at issue — Synapse stores only the sha256 hash.",
"sourceDetail.keysEmpty": "No keys yet — issue the first one",
"sourceDetail.colKey": "Key",
"sourceDetail.colTail": "Tail",
"sourceDetail.colCreatedHelp": "When the key was issued",
"sourceDetail.colUsed": "Last used",
"sourceDetail.colUsedHelp": "Latest event sent with this key",
"sourceDetail.colStatus": "Status",
"sourceDetail.keyRevoked": "revoked",
"sourceDetail.keyActive": "active",
"sourceDetail.revoke": "Revoke",
"sourceDetail.typesTitle": "Event types",
"sourceDetail.allTypes": "All types",
"sourceDetail.typesEmpty": "No types registered — an event with an unfamiliar triple will be rejected with 422",
"sourceDetail.colSubject": "Subject",
"sourceDetail.colSubjectHelp": "Event entity: container, issue, build…",
"sourceDetail.colAction": "Action",
"sourceDetail.colActionHelp": "What happened: down, created, resolved…",
"sourceDetail.colTypeCreatedHelp": "When the type was registered",
"sourceDetail.tokenModalTitle": "Token — shown only once",
"sourceDetail.tokenModalText": "The token will not be shown again: Synapse stores only the sha256 hash. Copy it now and hand it to the source owner.",
"sourceDetail.copy": "Copy",
"sourceDetail.done": "Done",
"sourceDetail.confirmTitle": "Delete source?",
"sourceDetail.confirmMessage": "Source \"{name}\" will be deleted together with its types and keys. If the source has events, the deletion will be rejected.",
"sourceDetail.delete": "Delete",
"sourceDetail.cancel": "Cancel",
"types.pickSource": "— select a source —",
"types.toastCreated": "Type created",
"types.toastDeleted": "Type deleted",
"types.pageTitle": "Types",
"types.pageSubtitle": "The (source, subject, action) registry. An event with an unregistered triple is rejected with 422",
"types.createButton": "Type",
"types.loading": "Loading…",
"types.empty": "No types yet — create the first one",
"types.colSource": "Source",
"types.colSubject": "Subject",
"types.colAction": "Action",
"types.colCreated": "Created",
"types.rowDelete": "Delete type",
"types.createTitle": "New type",
"types.formSourceLabel": "Source",
"types.formSubjectHelp": "Entity: container, issue, build…",
"types.formActionHelp": "What happened: down, created, resolved…",
"types.cancel": "Cancel",
"types.create": "Create",
"types.confirmTitle": "Delete type?",
"types.confirmMessage": "Type ({name}, {subject}, {action}) will be deleted — events with this triple will be rejected with 422.",
"types.delete": "Delete",
"targets.invalidConfigJson": "Config is not valid JSON",
"targets.toastCreated": "Target created",
"targets.toastDeleted": "Target deleted",
"targets.title": "Targets",
"targets.subtitle": "Where deliveries go: TG chats, SMTP, s2s endpoints. Channel credentials live only in .env (gnexus-creds)",
"targets.createButton": "Add target",
"targets.loading": "Loading…",
"targets.empty": "No targets yet — for example, create a target for internal_log",
"targets.colChannel": "Channel",
"targets.colName": "Name",
"targets.colCreatedAt": "Created",
"targets.rowDelete": "Delete target",
"targets.modalCreate": "New target",
"targets.formChannel": "Channel",
"targets.formName": "Name",
"targets.formDescription": "Description",
"targets.formConfigLabel": "Config (JSON)",
"targets.nameHelp": "e.g. infra-alerts",
"targets.descriptionHelp": "What this target is for (for the AI agent and for humans)",
"targets.configHelp": "For s2s: {\"endpoint\":\"http://…\",\"token_ref\":\"navi-rei\"}; for TG: {\"chat_id\":\"@…\"}",
"targets.cancel": "Cancel",
"targets.create": "Create",
"targets.confirmTitle": "Delete target?",
"targets.confirmMessage": "Target “{name}” ({channel}) will be deleted. References from rules and deliveries will be cleared; the history is kept.",
"targets.confirmDelete": "Delete",
"targetDetail.notFound": "Target not found",
"targetDetail.invalidConfigJson": "Config is not valid JSON",
"targetDetail.toastSaved": "Saved",
"targetDetail.toastEnabled": "Target enabled",
"targetDetail.toastDisabled": "Target disabled",
"targetDetail.toastDeleted": "Target deleted",
"targetDetail.hintS2s": "system-to-system: Synapse signs the event and sends it to the target's endpoint. The secret lives in the worker's .env under the name S2S_SECRET_<TOKEN_REF>.",
"targetDetail.hintTelegram": "Telegram channel (#29, not implemented yet). The config stores the chat identifier.",
"targetDetail.hintEmail": "Email channel (#29, not implemented yet). The config stores addresses/subject.",
"targetDetail.hintInternalLog": "Synapse internal log: the delivery is written to the DB as a degradation record and for audit.",
"targetDetail.backLink": "Back to targets",
"targetDetail.kickerTarget": "Target",
"targetDetail.unnamed": "…",
"targetDetail.enabled": "On",
"targetDetail.disabled": "Off",
"targetDetail.statusOn": "On",
"targetDetail.statusOff": "Off",
"targetDetail.actions": "Actions",
"targetDetail.edit": "Edit",
"targetDetail.delete": "Delete",
"targetDetail.loading": "Loading…",
"targetDetail.about": "About the target",
"targetDetail.fieldChannel": "Channel",
"targetDetail.fieldStatus": "Status",
"targetDetail.fieldName": "Name",
"targetDetail.fieldDescription": "Description",
"targetDetail.fieldCreatedAt": "Created",
"targetDetail.configTitle": "Config",
"targetDetail.copy": "Copy",
"targetDetail.configNote": "Delivery endpoint identifiers. Secrets and credentials never go into the config — only into .env (gnexus-creds).",
"targetDetail.modalEdit": "Edit target",
"targetDetail.formName": "Name",
"targetDetail.nameHelp": "Shown in rules and in the delivery log",
"targetDetail.formDescription": "Description",
"targetDetail.descriptionHelp": "What this target is for (for the AI agent and for humans)",
"targetDetail.formConfigLabel": "Config (JSON)",
"targetDetail.configExample": "e.g. {\"endpoint\":\"http://…\",\"token_ref\":\"navi-rei\"}",
"targetDetail.credsNote": "Credentials never go into the config — only into .env (gnexus-creds)",
"targetDetail.cancel": "Cancel",
"targetDetail.save": "Save",
"targetDetail.confirmTitle": "Delete target?",
"targetDetail.confirmMessage": "Target “{name}” will be deleted. References from rules and deliveries will be cleared; the delivery history is kept.",
"targetDetail.confirmDelete": "Delete",
"rules.weightTip": "Weight defines the order rules are applied in first-match mode (ROUTING_MATCH_MODE=first): lower means more important and fires earlier. In all-match mode it does not affect the result.",
"rules.throttleTip": "Decimation: at most one live delivery to this target per N seconds. Suppressed deliveries get the skipped status, critical always passes.",
"rules.toastCreated": "Rule created",
"rules.toastEnabled": "Rule enabled",
"rules.toastDisabled": "Rule disabled",
"rules.toastDeleted": "Rule deleted",
"rules.title": "Rules",
"rules.subtitle": "Every event is run through the rules: when the conditions match, a delivery is created to the action's channels. The throttle cuts repeats, critical always passes",
"rules.createButton": "Rule",
"rules.loading": "Loading…",
"rules.emptyText": "No rules yet — an event matching no rule is only recorded in the delivery history",
"rules.colName": "Rule",
"rules.colWeight": "Weight",
"rules.colThrottle": "Throttle",
"rules.colActions": "Actions",
"rules.actionsTip": "Where to deliver: a channel and a target. internal_log without a target writes the Synapse journal. Conditions live on the rule page",
"rules.colEnabled": "On/off",
"rules.secondsShort": "s",
"rules.deleteRule": "Delete rule",
"rules.newRuleTitle": "New rule",
"rules.cancel": "Cancel",
"rules.create": "Create",
"rules.deleteTitle": "Delete rule?",
"rules.deleteMessage": "Rule «{name}» will be deleted together with its actions. The delivery history will remain.",
"rules.delete": "Delete",
"ruleDetail.condSource": "Source: the source name from the registry",
"ruleDetail.condSubjects": "Event subjects (any of)",
"ruleDetail.condActions": "Event actions (any of)",
"ruleDetail.condPriorityMin": "Minimum priority (low/normal/high/critical)",
"ruleDetail.condPayload": "Payload field requirements (all listed must match; a list value = any of them)",
"ruleDetail.notFound": "Rule not found",
"ruleDetail.toastEnabled": "Rule enabled",
"ruleDetail.toastDisabled": "Rule disabled",
"ruleDetail.toastSaved": "Saved",
"ruleDetail.toastDeleted": "Rule deleted",
"ruleDetail.weightTip": "Weight defines the order rules are applied in first-match mode (ROUTING_MATCH_MODE=first): lower means more important and fires earlier. In all-match mode it does not affect the result.",
"ruleDetail.throttleTip": "Decimation: at most one live delivery to this target per N seconds. Suppressed deliveries get the skipped status, critical always passes.",
"ruleDetail.backToList": "Back to the rule list",
"ruleDetail.kicker": "Synapse · Rule",
"ruleDetail.noName": "…",
"ruleDetail.subtitle": "Conditions → routing actions",
"ruleDetail.enabled": "Enabled",
"ruleDetail.disabled": "Disabled",
"ruleDetail.actionsLabel": "Actions",
"ruleDetail.edit": "Edit",
"ruleDetail.delete": "Delete",
"ruleDetail.loading": "Loading…",
"ruleDetail.paramsTitle": "Parameters",
"ruleDetail.statusLabel": "Status",
"ruleDetail.stateOn": "enabled",
"ruleDetail.stateOff": "disabled",
"ruleDetail.weightLabel": "Weight",
"ruleDetail.throttleLabel": "Throttle",
"ruleDetail.createdLabel": "Created",
"ruleDetail.secondsShort": "s",
"ruleDetail.conditionsTitle": "Conditions",
"ruleDetail.conditionsNote": "An event matches the rule only when every condition below matches. With none listed, the rule matches any event.",
"ruleDetail.templateTitle": "Message template",
"ruleDetail.templateNote1": "Jinja2 text that goes into the channel:",
"ruleDetail.templateNote2": "substitutes a value from the event payload. If no template is set, an action below may have its own.",
"ruleDetail.templateEmpty": "— not set",
"ruleDetail.actionsTitle": "Actions",
"ruleDetail.actionsNote": "When an event matches the conditions, a delivery is created for each action. internal_log writes to the Synapse journal (audit and degradation), s2s sends a signed request to the service; the telegram/email channels come with #29 and are not working yet.",
"ruleDetail.withoutTarget": "no target",
"ruleDetail.actionTemplate": "action template:",
"ruleDetail.noTemplate": "template not set",
"ruleDetail.editTitle": "Edit rule",
"ruleDetail.cancel": "Cancel",
"ruleDetail.save": "Save",
"ruleDetail.deleteTitle": "Delete rule?",
"ruleDetail.deleteMessage": "Rule «{name}» will be deleted together with its actions. The delivery history will remain.",
"ruleForm.priorityAny": "— any —",
"ruleForm.weightTip": "Weight defines the order rules are applied in first-match mode (ROUTING_MATCH_MODE=first): lower means more important and fires earlier. In all-match mode it does not affect the result.",
"ruleForm.throttleTip": "Decimation: at most one live delivery to this target per N seconds. Suppressed deliveries get the skipped status, critical always passes.",
"ruleForm.anySource": "— any source —",
"ruleForm.errName": "Set a rule name",
"ruleForm.errPayloadJson": "Payload requirements are not valid JSON",
"ruleForm.errNoActions": "Add at least one action — where to deliver",
"ruleForm.nameLabel": "Name",
"ruleForm.nameHelp": "How the rule is titled in the list, e.g. «containers down»",
"ruleForm.weightLabel": "Weight",
"ruleForm.throttleLabel": "Throttle, sec",
"ruleForm.conditionsTitle": "Conditions",
"ruleForm.conditionsNote": "The rule applies to an event only when all set conditions match. An empty condition set matches everything.",
"ruleForm.sourceLabel": "Source",
"ruleForm.subjectsHelp": "Subjects, comma-separated: container, build…; empty = any",
"ruleForm.actionsHelp": "Event actions, comma-separated: down, created…; empty = any",
"ruleForm.payloadLabel": "Payload requirements (JSON)",
"ruleForm.payloadHelp": "E.g. {\"host\": [\"melody\",\"pilar\"]} — the event must carry host melody or pilar; empty = no requirement",
"ruleForm.actionsTitle": "Actions",
"ruleForm.actionsNote": "What happens when the rule matches: a delivery is created in each channel below. internal_log without a target is a Synapse journal entry (audit); user is the personal log of the user from payload.user_id; s2s sends a signed request to the service; the telegram/email channels come with #29 and are not working yet.",
"ruleForm.tplLabel": "Default template (Jinja2)",
"ruleForm.tplHelp": "{{ payload.field }} — a value from the event payload, e.g. \"Container {{ payload.container }} is down\"; an action may have its own template",
"ruleForm.channelLabel": "Channel",
"ruleForm.targetLabel": "Target",
"ruleForm.noTarget": "— no target —",
"ruleForm.removeAction": "Remove action",
"ruleForm.addAction": "Action",
"ruleForm.errTitle": "Form error",
"settings.title": "Settings",
"settings.subtitleAdmin": "Personal push subscription and Synapse configuration (overrides .env defaults)",
"settings.subtitleUser": "Personal: push notification subscription for this browser",
"settings.loading": "Loading…",
"settings.toastDeviceRemoved": "Subscription removed",
"settings.toastNotConfigured": "Push is not configured yet — an admin needs to set the VAPID keys in settings",
"settings.toastPermissionDenied": "Notifications for this site are blocked in the browser — enable them in the site settings",
"settings.toastPushEnabled": "Push notifications enabled",
"settings.toastPushDisabled": "Push notifications disabled",
"settings.toastSaved": "Settings saved",
"settings.sectionRouting": "Routing",
"settings.sectionPush": "Web Push",
"settings.sectionTelegram": "Telegram",
"settings.sectionSmtp": "Email · SMTP",
"settings.deviceTip": "A device subscribed to your push notifications (one line — one browser). Remove the line if the device is gone.",
"settings.pushTitle": "Push notifications for this browser",
"settings.pushUnsupportedTitle": "Push is unavailable",
"settings.pushUnsupportedText": "This browser does not support web-push (Service Worker and Notification API are required; available only on https/localhost pages).",
"settings.pushNotConfiguredTitle": "Server is not configured yet",
"settings.pushNotConfiguredText": "The admin has not set the VAPID keys yet — enable push once it is configured (admin: Settings → Web Push).",
"settings.permissionDeniedNote": "Notification permission is blocked — enable it in the browser's site settings.",
"settings.permissionUnsupportedNote": "This browser does not support web-push.",
"settings.pushSwitchLabel": "Receive push notifications from Synapse",
"settings.pushActiveNote": "This browser's subscription is active",
"settings.pushInactiveNote": "Events addressed specifically to you (payload.user_id) will open as system notifications",
"settings.removeDeviceLabel": "Remove subscription",
"settings.secretSetPlaceholder": "••••• set — leave empty to keep unchanged",
"settings.notSetPlaceholder": "not set",
"settings.writeOnlyHelp": "write-only: {text}",
"settings.overrideButton": "Override defaults",
"settings.overrideHint": "Values set here override .env on the fly — no container restart needed",
"mcpKeys.title": "MCP keys",
"mcpKeys.subtitle": "Personal tokens for accessing the Synapse MCP server: an agent with a key acts under your role",
"mcpKeys.loading": "Loading…",
"mcpKeys.myKeys": "My keys",
"mcpKeys.tokenWord": "A token",
"mcpKeys.myKeysNote": "is shown once at issue time — Synapse stores only the sha256 hash. It acts under the owner's role at issue time: after a role change, issue a new key and revoke the old one. Up to 10 keys can be active at once.",
"mcpKeys.namePlaceholder": "Key name: “Navi rei agent”",
"mcpKeys.generate": "Generate key",
"mcpKeys.defaultName": "key",
"mcpKeys.toastRevoked": "Key revoked",
"mcpKeys.emptyOwn": "No keys yet — generate your first one and hand it to your AI agent",
"mcpKeys.colKey": "Key",
"mcpKeys.colTail": "Tail",
"mcpKeys.colRole": "Role",
"mcpKeys.colCreated": "Created",
"mcpKeys.colCreatedTip": "When the key was issued",
"mcpKeys.colUsed": "Used",
"mcpKeys.colUsedTip": "Last MCP request with this key",
"mcpKeys.colStatus": "Status",
"mcpKeys.badgeRevoked": "revoked",
"mcpKeys.badgeActive": "active",
"mcpKeys.revoke": "Revoke",
"mcpKeys.howToConnect": "How to connect an agent",
"mcpKeys.connectNoteBefore": "An MCP client (Claude Code, IDE, etc.) needs the endpoint URL",
"mcpKeys.connectNoteAfter": "of this Synapse and the Bearer key from the issue dialog: whoever holds the key acts under the owner's role (admin tools — admin+ roles only).",
"mcpKeys.copyConfig": "Copy config",
"mcpKeys.allKeysAdmin": "All keys (admin)",
"mcpKeys.allKeysNote": "Issuing is self-service (everyone does it on their own /mcp-keys page); here you get an overview of all keys and can revoke them, e.g. after a user's role change on gnexus-auth.",
"mcpKeys.emptyAll": "No personal keys yet — they will appear once users issue their own",
"mcpKeys.colOwner": "Owner",
"mcpKeys.modalTitle": "Token — shown only once",
"mcpKeys.modalAlert": "Configure your agent now: Synapse stores only the sha256 hash — the token will never be shown again.",
"mcpKeys.copy": "Copy",
"mcpKeys.done": "Done",
"mcpKeys.revokeConfirmTitle": "Revoke someone else's key?",
"mcpKeys.revokeConfirmMessage": "The key “{name}” ({owner}) will stop working for its agent. The user can issue a new one when needed.",
"mcpKeys.cancel": "Cancel",
'push.unsupported': 'The browser does not support web-push',
'push.swNotReady': 'Service worker is not ready yet (reload the page)',
};