feat(studio): MCP suggestions + Approvals/Audit/Settings i18n (v0.26.0)
- Add curated catalogue of 9 official Anthropic MCP servers as click-to-prefill chips in the Add-MCP-server dialog. Operator still confirms via "Add + discover"; nothing is auto-spawned, preserving the regulated-environment trust model. - Localize Approvals page: pending/history empty states, status pills, payload preview, approve/reject toasts, reject dialog, history detail dialog, expires-in pill. - Localize Audit page: filter chips, clear-log dialog and toasts, no-events / hub-unreachable empty states, live-status bar with pluralized event count, hash-chain-verified badge, System AI panel (cached pill, latency, regenerate tooltip, asking state), event-detail dialog actions. - Localize Settings dialog: hub-endpoint section, channel blurb + popup-menu items, System AI panel headers and off-blurb, MCP/N8N panel headers + pluralized counts + refresh/add/remove tooltips, Add-MCP and Add-n8n dialogs (intro, suggestions label, all field labels and hints, save buttons, toasts). Field labels that map directly to JSON keys (event_id, flow, step, module, provider, endpoint, model) stay English by design — they're technical identifiers, not UI copy. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
349619d68e
commit
d25b4c87ae
9 changed files with 2022 additions and 209 deletions
|
|
@ -284,6 +284,288 @@ abstract class AppLocalizations {
|
|||
/// **'App language. Affects every page; bilingual store entries also flip via this toggle.'**
|
||||
String get settingsLanguageHint;
|
||||
|
||||
/// No description provided for @settingsHubEndpointHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Where should Studio connect? Default is the local hub at 127.0.0.1:50051.'**
|
||||
String get settingsHubEndpointHint;
|
||||
|
||||
/// No description provided for @settingsTlsSubtitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'https/grpc-secure'**
|
||||
String get settingsTlsSubtitle;
|
||||
|
||||
/// No description provided for @settingsPortError.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'port must be 1–65535'**
|
||||
String get settingsPortError;
|
||||
|
||||
/// No description provided for @channelsBlurb.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Switch hub channel (writes ~/.fai/current-channel and restarts the daemon). Connect just changes Studio\'s wire.'**
|
||||
String get channelsBlurb;
|
||||
|
||||
/// No description provided for @channelsActionsTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Channel actions'**
|
||||
String get channelsActionsTooltip;
|
||||
|
||||
/// No description provided for @systemAiHeader.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'SYSTEM AI'**
|
||||
String get systemAiHeader;
|
||||
|
||||
/// No description provided for @systemAiEnabled.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'enabled'**
|
||||
String get systemAiEnabled;
|
||||
|
||||
/// No description provided for @systemAiOff.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'off'**
|
||||
String get systemAiOff;
|
||||
|
||||
/// No description provided for @systemAiEdit.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Edit…'**
|
||||
String get systemAiEdit;
|
||||
|
||||
/// No description provided for @systemAiConfigure.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Configure…'**
|
||||
String get systemAiConfigure;
|
||||
|
||||
/// No description provided for @systemAiOffBlurb.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Off — failure explanations on the audit page are disabled. Click Configure… to pick a provider (Ollama / OpenAI / LM Studio / vLLM / Custom). Operator config is rewritten in place; no daemon restart needed.'**
|
||||
String get systemAiOffBlurb;
|
||||
|
||||
/// No description provided for @mcpServersCount.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{n} {n, plural, =1{server} other{servers}}'**
|
||||
String mcpServersCount(int n);
|
||||
|
||||
/// No description provided for @mcpRediscoverTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Re-run discovery'**
|
||||
String get mcpRediscoverTooltip;
|
||||
|
||||
/// No description provided for @mcpAddTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add MCP server'**
|
||||
String get mcpAddTooltip;
|
||||
|
||||
/// No description provided for @mcpRemoveTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Remove server'**
|
||||
String get mcpRemoveTooltip;
|
||||
|
||||
/// No description provided for @mcpToolsCount.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{n} {n, plural, =1{tool} other{tools}}'**
|
||||
String mcpToolsCount(int n);
|
||||
|
||||
/// No description provided for @n8nEndpointsCount.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{n} {n, plural, =1{endpoint} other{endpoints}}'**
|
||||
String n8nEndpointsCount(int n);
|
||||
|
||||
/// No description provided for @n8nWorkflowsCount.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{n} {n, plural, =1{workflow} other{workflows}}'**
|
||||
String n8nWorkflowsCount(int n);
|
||||
|
||||
/// No description provided for @n8nRediscoverTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Re-run discovery'**
|
||||
String get n8nRediscoverTooltip;
|
||||
|
||||
/// No description provided for @n8nAddTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add n8n endpoint'**
|
||||
String get n8nAddTooltip;
|
||||
|
||||
/// No description provided for @n8nRemoveTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Remove endpoint'**
|
||||
String get n8nRemoveTooltip;
|
||||
|
||||
/// No description provided for @addMcpTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add MCP server'**
|
||||
String get addMcpTitle;
|
||||
|
||||
/// No description provided for @addMcpIntro.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Tools the server advertises via `tools/list` appear in the Store as `mcp.<name>.<tool>` capabilities.'**
|
||||
String get addMcpIntro;
|
||||
|
||||
/// No description provided for @addMcpSuggestionsLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Suggested servers — click to pre-fill'**
|
||||
String get addMcpSuggestionsLabel;
|
||||
|
||||
/// No description provided for @addMcpNameLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Name (no dots)'**
|
||||
String get addMcpNameLabel;
|
||||
|
||||
/// No description provided for @addMcpNameHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'filesystem'**
|
||||
String get addMcpNameHint;
|
||||
|
||||
/// No description provided for @addMcpEndpointLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Endpoint'**
|
||||
String get addMcpEndpointLabel;
|
||||
|
||||
/// No description provided for @addMcpEndpointHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'http://127.0.0.1:3001/mcp'**
|
||||
String get addMcpEndpointHint;
|
||||
|
||||
/// No description provided for @addMcpApiKeyLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'API key env var (optional)'**
|
||||
String get addMcpApiKeyLabel;
|
||||
|
||||
/// No description provided for @addMcpApiKeyHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'MCP_FILESYSTEM_TOKEN'**
|
||||
String get addMcpApiKeyHint;
|
||||
|
||||
/// No description provided for @addMcpNotesLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Notes (optional)'**
|
||||
String get addMcpNotesLabel;
|
||||
|
||||
/// No description provided for @addMcpAddButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add + discover'**
|
||||
String get addMcpAddButton;
|
||||
|
||||
/// No description provided for @addN8nTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add n8n endpoint'**
|
||||
String get addN8nTitle;
|
||||
|
||||
/// No description provided for @addN8nIntro.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Active workflows surface in the Store as `n8n.<name>.<workflow_slug>` capabilities.'**
|
||||
String get addN8nIntro;
|
||||
|
||||
/// No description provided for @addN8nNameLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Name (no dots)'**
|
||||
String get addN8nNameLabel;
|
||||
|
||||
/// No description provided for @addN8nNameHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'ops'**
|
||||
String get addN8nNameHint;
|
||||
|
||||
/// No description provided for @addN8nBaseUrlLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Base URL (without /api/v1)'**
|
||||
String get addN8nBaseUrlLabel;
|
||||
|
||||
/// No description provided for @addN8nBaseUrlHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'https://n8n.example.com'**
|
||||
String get addN8nBaseUrlHint;
|
||||
|
||||
/// No description provided for @addN8nApiKeyLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'API key env var (optional)'**
|
||||
String get addN8nApiKeyLabel;
|
||||
|
||||
/// No description provided for @addN8nApiKeyHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'N8N_OPS_KEY'**
|
||||
String get addN8nApiKeyHint;
|
||||
|
||||
/// No description provided for @addN8nNotesLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Notes (optional)'**
|
||||
String get addN8nNotesLabel;
|
||||
|
||||
/// No description provided for @addN8nAddButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add + discover'**
|
||||
String get addN8nAddButton;
|
||||
|
||||
/// No description provided for @addedMcpToast.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Added MCP server \"{name}\".'**
|
||||
String addedMcpToast(String name);
|
||||
|
||||
/// No description provided for @addedN8nToast.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Added n8n endpoint \"{name}\".'**
|
||||
String addedN8nToast(String name);
|
||||
|
||||
/// No description provided for @addFailedToast.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add failed: {error}'**
|
||||
String addFailedToast(String error);
|
||||
|
||||
/// No description provided for @removeFailedToast.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Remove failed: {error}'**
|
||||
String removeFailedToast(String error);
|
||||
|
||||
/// No description provided for @refreshFailedToast.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Refresh failed: {error}'**
|
||||
String refreshFailedToast(String error);
|
||||
|
||||
/// No description provided for @channelsHeader.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
@ -440,6 +722,192 @@ abstract class AppLocalizations {
|
|||
/// **'Run a flow to populate the audit stream.\nEvents appear here within seconds.'**
|
||||
String get auditNoEventsHint;
|
||||
|
||||
/// No description provided for @auditFilterAll.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'all'**
|
||||
String get auditFilterAll;
|
||||
|
||||
/// No description provided for @auditFilterFlow.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'flow'**
|
||||
String get auditFilterFlow;
|
||||
|
||||
/// No description provided for @auditFilterStep.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'step'**
|
||||
String get auditFilterStep;
|
||||
|
||||
/// No description provided for @auditFilterModule.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'module'**
|
||||
String get auditFilterModule;
|
||||
|
||||
/// No description provided for @auditClearLogTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Clear log (local/dev channels only)'**
|
||||
String get auditClearLogTooltip;
|
||||
|
||||
/// No description provided for @auditClearedToast.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Cleared {n} events on channel \"{channel}\". Chain reseeded with marker.'**
|
||||
String auditClearedToast(int n, String channel);
|
||||
|
||||
/// No description provided for @auditClearFailed.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Clear failed: {detail}'**
|
||||
String auditClearFailed(String detail);
|
||||
|
||||
/// No description provided for @auditExplain.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Explain'**
|
||||
String get auditExplain;
|
||||
|
||||
/// No description provided for @auditReask.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Re-ask'**
|
||||
String get auditReask;
|
||||
|
||||
/// No description provided for @auditAsking.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Asking…'**
|
||||
String get auditAsking;
|
||||
|
||||
/// No description provided for @auditSystemAi.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'SYSTEM AI'**
|
||||
String get auditSystemAi;
|
||||
|
||||
/// No description provided for @auditCachedPill.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'cached'**
|
||||
String get auditCachedPill;
|
||||
|
||||
/// No description provided for @auditOriginalLatency.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'orig {ms} ms'**
|
||||
String auditOriginalLatency(int ms);
|
||||
|
||||
/// No description provided for @auditLatency.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{ms} ms'**
|
||||
String auditLatency(int ms);
|
||||
|
||||
/// No description provided for @auditRegenerateTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Regenerate — skip cache, ask the model again'**
|
||||
String get auditRegenerateTooltip;
|
||||
|
||||
/// No description provided for @auditLiveStatus.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'live · polling 2s · {n} {n, plural, =1{event} other{events}}'**
|
||||
String auditLiveStatus(int n);
|
||||
|
||||
/// No description provided for @auditDisconnected.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'disconnected · {error}'**
|
||||
String auditDisconnected(String error);
|
||||
|
||||
/// No description provided for @auditHashChainVerified.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'hash chain verified'**
|
||||
String get auditHashChainVerified;
|
||||
|
||||
/// No description provided for @auditDetailHeader.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'DETAIL'**
|
||||
String get auditDetailHeader;
|
||||
|
||||
/// No description provided for @auditAskingFull.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Asking the configured System AI…'**
|
||||
String get auditAskingFull;
|
||||
|
||||
/// No description provided for @auditFixLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'FIX'**
|
||||
String get auditFixLabel;
|
||||
|
||||
/// No description provided for @auditCachedTooltipKnown.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Served from the local cache. Originally generated on {at}{hits}.'**
|
||||
String auditCachedTooltipKnown(String at, String hits);
|
||||
|
||||
/// No description provided for @auditCachedTooltipUnknown.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Served from the local cache. Originally generated at unknown time{hits}.'**
|
||||
String auditCachedTooltipUnknown(String hits);
|
||||
|
||||
/// No description provided for @auditCachedTooltipHits.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **' · {n} hits'**
|
||||
String auditCachedTooltipHits(int n);
|
||||
|
||||
/// No description provided for @auditConfigureSystemAi.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Configure System AI in Settings (Cmd+,)'**
|
||||
String get auditConfigureSystemAi;
|
||||
|
||||
/// No description provided for @auditClearDialogTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Clear audit log?'**
|
||||
String get auditClearDialogTitle;
|
||||
|
||||
/// No description provided for @auditClearDialogBody.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Wipes every audit event on the active channel and seeds a fresh chain.reset marker carrying reviewer + reason. Refused on beta / production. Irreversible.'**
|
||||
String get auditClearDialogBody;
|
||||
|
||||
/// No description provided for @auditClearReviewerLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Reviewer'**
|
||||
String get auditClearReviewerLabel;
|
||||
|
||||
/// No description provided for @auditClearReasonLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Reason (recorded in chain.reset marker)'**
|
||||
String get auditClearReasonLabel;
|
||||
|
||||
/// No description provided for @auditClearReasonHelper.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Required — auditors will read this.'**
|
||||
String get auditClearReasonHelper;
|
||||
|
||||
/// No description provided for @auditClearLogButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Clear log'**
|
||||
String get auditClearLogButton;
|
||||
|
||||
/// No description provided for @modulesTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
@ -554,6 +1022,138 @@ abstract class AppLocalizations {
|
|||
/// **'All caught up. New `system.approval@^0` steps land here automatically.'**
|
||||
String get approvalsInboxHint;
|
||||
|
||||
/// No description provided for @approvalsReloadTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Reload'**
|
||||
String get approvalsReloadTooltip;
|
||||
|
||||
/// No description provided for @approvalsPillPending.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'pending'**
|
||||
String get approvalsPillPending;
|
||||
|
||||
/// No description provided for @approvalsPillApproved.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'approved'**
|
||||
String get approvalsPillApproved;
|
||||
|
||||
/// No description provided for @approvalsPillRejected.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'rejected'**
|
||||
String get approvalsPillRejected;
|
||||
|
||||
/// No description provided for @approvalsPillExpired.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'expired'**
|
||||
String get approvalsPillExpired;
|
||||
|
||||
/// No description provided for @approvalsPayloadPreview.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'PAYLOAD PREVIEW'**
|
||||
String get approvalsPayloadPreview;
|
||||
|
||||
/// No description provided for @approvalsApproveButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Approve'**
|
||||
String get approvalsApproveButton;
|
||||
|
||||
/// No description provided for @approvalsRejectButton.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Reject'**
|
||||
String get approvalsRejectButton;
|
||||
|
||||
/// No description provided for @approvalsRejectDialogTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Reject approval'**
|
||||
String get approvalsRejectDialogTitle;
|
||||
|
||||
/// No description provided for @approvalsRejectReasonLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Reason (recorded in audit log)'**
|
||||
String get approvalsRejectReasonLabel;
|
||||
|
||||
/// No description provided for @approvalsApprovedToast.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'approved · {flow} › {step}'**
|
||||
String approvalsApprovedToast(String flow, String step);
|
||||
|
||||
/// No description provided for @approvalsRejectedToast.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'rejected · {flow} › {step}'**
|
||||
String approvalsRejectedToast(String flow, String step);
|
||||
|
||||
/// No description provided for @approvalsApproveFailed.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'approve failed: {error}'**
|
||||
String approvalsApproveFailed(String error);
|
||||
|
||||
/// No description provided for @approvalsRejectFailed.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'reject failed: {error}'**
|
||||
String approvalsRejectFailed(String error);
|
||||
|
||||
/// No description provided for @approvalsHistoryEmpty.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No history yet'**
|
||||
String get approvalsHistoryEmpty;
|
||||
|
||||
/// No description provided for @approvalsHistoryEmptyHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Decided approvals (approved / rejected / expired) appear here.\nThe audit log keeps the full hash-chained record.'**
|
||||
String get approvalsHistoryEmptyHint;
|
||||
|
||||
/// No description provided for @approvalsDialogDecided.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'decided'**
|
||||
String get approvalsDialogDecided;
|
||||
|
||||
/// No description provided for @approvalsDialogCreated.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'created'**
|
||||
String get approvalsDialogCreated;
|
||||
|
||||
/// No description provided for @approvalsDialogReason.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'reason'**
|
||||
String get approvalsDialogReason;
|
||||
|
||||
/// No description provided for @approvalsDialogPrompt.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'PROMPT'**
|
||||
String get approvalsDialogPrompt;
|
||||
|
||||
/// No description provided for @approvalsExpiresIn.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{minutes}m'**
|
||||
String approvalsExpiresIn(int minutes);
|
||||
|
||||
/// No description provided for @approvalsExpiresInHours.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{hours}h'**
|
||||
String approvalsExpiresInHours(int hours);
|
||||
|
||||
/// No description provided for @doctorTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue