E2C: Show snapshot error status (#91214)
* wip getError fn * Create show errors from all API requests * suppress error toasts from all e2c endpoints * require error severity
This commit is contained in:
@@ -18,7 +18,7 @@ function createBackendSrvBaseQuery({ baseURL }: { baseURL: string }): BaseQueryF
|
|||||||
getBackendSrv().fetch({
|
getBackendSrv().fetch({
|
||||||
...requestOptions,
|
...requestOptions,
|
||||||
url: baseURL + requestOptions.url,
|
url: baseURL + requestOptions.url,
|
||||||
showErrorAlert: requestOptions.showErrorAlert,
|
showErrorAlert: false,
|
||||||
data: requestOptions.body,
|
data: requestOptions.body,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,50 +8,39 @@ export const cloudMigrationAPI = generatedAPI.enhanceEndpoints({
|
|||||||
|
|
||||||
endpoints: {
|
endpoints: {
|
||||||
// Cloud-side - create token
|
// Cloud-side - create token
|
||||||
getCloudMigrationToken(endpoint) {
|
getCloudMigrationToken: {
|
||||||
suppressErrorsOnQuery(endpoint);
|
providesTags: ['cloud-migration-token'],
|
||||||
endpoint.providesTags = ['cloud-migration-token'];
|
|
||||||
},
|
},
|
||||||
createCloudMigrationToken(endpoint) {
|
createCloudMigrationToken: {
|
||||||
suppressErrorsOnQuery(endpoint);
|
invalidatesTags: ['cloud-migration-token'],
|
||||||
endpoint.invalidatesTags = ['cloud-migration-token'];
|
|
||||||
},
|
},
|
||||||
deleteCloudMigrationToken(endpoint) {
|
deleteCloudMigrationToken: {
|
||||||
suppressErrorsOnQuery(endpoint);
|
invalidatesTags: ['cloud-migration-token'],
|
||||||
endpoint.invalidatesTags = ['cloud-migration-token'];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// List Cloud Configs
|
// On-prem session management (entering token)
|
||||||
getSessionList: {
|
getSessionList: {
|
||||||
providesTags: ['cloud-migration-session'] /* should this be a -list? */,
|
providesTags: ['cloud-migration-session'] /* should this be a -list? */,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Create Cloud Config
|
|
||||||
createSession(endpoint) {
|
|
||||||
suppressErrorsOnQuery(endpoint);
|
|
||||||
endpoint.invalidatesTags = ['cloud-migration-session'];
|
|
||||||
},
|
|
||||||
|
|
||||||
// Get one Cloud Config
|
|
||||||
getSession: {
|
getSession: {
|
||||||
providesTags: ['cloud-migration-session'],
|
providesTags: ['cloud-migration-session'],
|
||||||
},
|
},
|
||||||
|
createSession: {
|
||||||
// Delete one Cloud Config
|
invalidatesTags: ['cloud-migration-session'],
|
||||||
|
},
|
||||||
deleteSession: {
|
deleteSession: {
|
||||||
invalidatesTags: ['cloud-migration-session', 'cloud-migration-snapshot'],
|
invalidatesTags: ['cloud-migration-session', 'cloud-migration-snapshot'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// Snapshot management
|
// Snapshot management
|
||||||
getSnapshot: {
|
|
||||||
providesTags: ['cloud-migration-snapshot'],
|
|
||||||
},
|
|
||||||
getShapshotList: {
|
getShapshotList: {
|
||||||
providesTags: ['cloud-migration-snapshot'],
|
providesTags: ['cloud-migration-snapshot'],
|
||||||
},
|
},
|
||||||
createSnapshot(endpoint) {
|
getSnapshot: {
|
||||||
suppressErrorsOnQuery(endpoint);
|
providesTags: ['cloud-migration-snapshot'],
|
||||||
endpoint.invalidatesTags = ['cloud-migration-snapshot'];
|
},
|
||||||
|
createSnapshot: {
|
||||||
|
invalidatesTags: ['cloud-migration-snapshot'],
|
||||||
},
|
},
|
||||||
uploadSnapshot: {
|
uploadSnapshot: {
|
||||||
invalidatesTags: ['cloud-migration-snapshot'],
|
invalidatesTags: ['cloud-migration-snapshot'],
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { skipToken } from '@reduxjs/toolkit/query/react';
|
import { skipToken } from '@reduxjs/toolkit/query/react';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { Alert, Box, Stack, Text } from '@grafana/ui';
|
import { AlertVariant, Box, Stack, Text } from '@grafana/ui';
|
||||||
import { Trans, t } from 'app/core/internationalization';
|
import { Trans, t } from 'app/core/internationalization';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
GetSnapshotResponseDto,
|
||||||
SnapshotDto,
|
SnapshotDto,
|
||||||
useCancelSnapshotMutation,
|
useCancelSnapshotMutation,
|
||||||
useCreateSnapshotMutation,
|
useCreateSnapshotMutation,
|
||||||
@@ -81,10 +82,12 @@ function useGetLatestSnapshot(sessionUid?: string, page = 1) {
|
|||||||
skipPollingIfUnfocused: true,
|
skipPollingIfUnfocused: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isError = listResult.isError || snapshotResult.isError;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const shouldPoll = SHOULD_POLL_STATUSES.includes(snapshotResult.data?.status);
|
const shouldPoll = !isError && SHOULD_POLL_STATUSES.includes(snapshotResult.data?.status);
|
||||||
setShouldPoll(shouldPoll);
|
setShouldPoll(shouldPoll);
|
||||||
}, [snapshotResult?.data?.status]);
|
}, [snapshotResult?.data?.status, isError]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...snapshotResult,
|
...snapshotResult,
|
||||||
@@ -100,7 +103,7 @@ function useGetLatestSnapshot(sessionUid?: string, page = 1) {
|
|||||||
|
|
||||||
// isSuccess and isUninitialised should always be from snapshotResult
|
// isSuccess and isUninitialised should always be from snapshotResult
|
||||||
// as only the 'final' values from those are important
|
// as only the 'final' values from those are important
|
||||||
isError: listResult.isError || snapshotResult.isError,
|
isError,
|
||||||
isLoading: listResult.isLoading || snapshotResult.isLoading,
|
isLoading: listResult.isLoading || snapshotResult.isLoading,
|
||||||
isFetching: listResult.isFetching || snapshotResult.isFetching,
|
isFetching: listResult.isFetching || snapshotResult.isFetching,
|
||||||
};
|
};
|
||||||
@@ -131,11 +134,22 @@ export const Page = () => {
|
|||||||
snapshot.isLoading ||
|
snapshot.isLoading ||
|
||||||
disconnectResult.isLoading;
|
disconnectResult.isLoading;
|
||||||
|
|
||||||
const showBuildSnapshot = !snapshot.isLoading && !snapshot.data;
|
const showBuildSnapshot = !snapshot.isError && !snapshot.isLoading && !snapshot.data;
|
||||||
const showBuildingSnapshot = SNAPSHOT_BUILDING_STATUSES.includes(status);
|
const showBuildingSnapshot = SNAPSHOT_BUILDING_STATUSES.includes(status);
|
||||||
const showUploadSnapshot = status === 'PENDING_UPLOAD' || SNAPSHOT_UPLOADING_STATUSES.includes(status);
|
const showUploadSnapshot =
|
||||||
|
!snapshot.isError && (status === 'PENDING_UPLOAD' || SNAPSHOT_UPLOADING_STATUSES.includes(status));
|
||||||
const showRebuildSnapshot = SNAPSHOT_REBUILD_STATUSES.includes(status);
|
const showRebuildSnapshot = SNAPSHOT_REBUILD_STATUSES.includes(status);
|
||||||
|
|
||||||
|
const error = getError({
|
||||||
|
snapshot: snapshot.data,
|
||||||
|
getSnapshotError: snapshot.error,
|
||||||
|
getSessionError: session.error,
|
||||||
|
createSnapshotError: createSnapshotResult.error,
|
||||||
|
uploadSnapshotError: uploadSnapshotResult.error,
|
||||||
|
cancelSnapshotError: cancelSnapshotResult.error,
|
||||||
|
disconnectSnapshotError: disconnectResult.error,
|
||||||
|
});
|
||||||
|
|
||||||
const handleDisconnect = useCallback(async () => {
|
const handleDisconnect = useCallback(async () => {
|
||||||
if (sessionUid) {
|
if (sessionUid) {
|
||||||
performDisconnect({ uid: sessionUid });
|
performDisconnect({ uid: sessionUid });
|
||||||
@@ -173,34 +187,7 @@ export const Page = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack direction="column" gap={4}>
|
<Stack direction="column" gap={2}>
|
||||||
{/* TODO: show errors from all mutation's in a... modal? */}
|
|
||||||
|
|
||||||
{createSnapshotResult.isError && (
|
|
||||||
<AlertWithTraceID
|
|
||||||
error={createSnapshotResult.error}
|
|
||||||
severity="error"
|
|
||||||
title={t('migrate-to-cloud.summary.run-migration-error-title', 'Error creating snapshot')}
|
|
||||||
>
|
|
||||||
<Text element="p">
|
|
||||||
<Trans i18nKey="migrate-to-cloud.summary.run-migration-error-description">
|
|
||||||
See the Grafana server logs for more details
|
|
||||||
</Trans>
|
|
||||||
</Text>
|
|
||||||
</AlertWithTraceID>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{disconnectResult.isError && (
|
|
||||||
<Alert
|
|
||||||
severity="error"
|
|
||||||
title={t('migrate-to-cloud.summary.disconnect-error-title', 'There was an error disconnecting')}
|
|
||||||
>
|
|
||||||
<Trans i18nKey="migrate-to-cloud.summary.disconnect-error-description">
|
|
||||||
See the Grafana server logs for more details
|
|
||||||
</Trans>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{session.data && (
|
{session.data && (
|
||||||
<MigrationSummary
|
<MigrationSummary
|
||||||
session={session.data}
|
session={session.data}
|
||||||
@@ -218,6 +205,12 @@ export const Page = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<AlertWithTraceID severity={error.severity} title={error.title} error={error.error}>
|
||||||
|
<Text element="p">{error.body}</Text>
|
||||||
|
</AlertWithTraceID>
|
||||||
|
)}
|
||||||
|
|
||||||
{(showBuildSnapshot || showBuildingSnapshot) && (
|
{(showBuildSnapshot || showBuildingSnapshot) && (
|
||||||
<Box display="flex" justifyContent="center" paddingY={10}>
|
<Box display="flex" justifyContent="center" paddingY={10}>
|
||||||
{showBuildSnapshot && (
|
{showBuildSnapshot && (
|
||||||
@@ -258,3 +251,113 @@ export const Page = () => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface GetErrorProps {
|
||||||
|
snapshot: GetSnapshotResponseDto | undefined;
|
||||||
|
getSessionError: unknown; // From getLatestSessionQuery
|
||||||
|
getSnapshotError: unknown; // From getLatestSnapshotQuery
|
||||||
|
createSnapshotError: unknown; // From createSnapshotMutation
|
||||||
|
uploadSnapshotError: unknown; // From uploadSnapshotMutation
|
||||||
|
cancelSnapshotError: unknown; // From cancelSnapshotMutation
|
||||||
|
disconnectSnapshotError: unknown; // From disconnectMutation
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ErrorDescription {
|
||||||
|
title: string;
|
||||||
|
body: string;
|
||||||
|
severity: AlertVariant;
|
||||||
|
error?: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getError(props: GetErrorProps): ErrorDescription | undefined {
|
||||||
|
const {
|
||||||
|
snapshot,
|
||||||
|
getSnapshotError,
|
||||||
|
getSessionError,
|
||||||
|
createSnapshotError,
|
||||||
|
uploadSnapshotError,
|
||||||
|
cancelSnapshotError,
|
||||||
|
disconnectSnapshotError,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const seeLogs = t('migrate-to-cloud.onprem.error-see-server-logs', 'See the Grafana server logs for more details');
|
||||||
|
|
||||||
|
if (getSessionError) {
|
||||||
|
return {
|
||||||
|
severity: 'error',
|
||||||
|
title: t('migrate-to-cloud.onprem.get-session-error-title', 'Error loading migration configuration'),
|
||||||
|
body: seeLogs,
|
||||||
|
error: getSessionError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getSnapshotError) {
|
||||||
|
return {
|
||||||
|
severity: 'error',
|
||||||
|
title: t('migrate-to-cloud.onprem.get-snapshot-error-title', 'Error loading snapshot'),
|
||||||
|
body: seeLogs,
|
||||||
|
error: getSnapshotError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disconnectSnapshotError) {
|
||||||
|
return {
|
||||||
|
severity: 'warning',
|
||||||
|
title: t('migrate-to-cloud.onprem.disconnect-error-title', 'Error disconnecting'),
|
||||||
|
body: seeLogs,
|
||||||
|
error: disconnectSnapshotError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createSnapshotError) {
|
||||||
|
return {
|
||||||
|
severity: 'warning',
|
||||||
|
title: t('migrate-to-cloud.onprem.create-snapshot-error-title', 'Error creating snapshot'),
|
||||||
|
body: seeLogs,
|
||||||
|
error: createSnapshotError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uploadSnapshotError) {
|
||||||
|
return {
|
||||||
|
severity: 'warning',
|
||||||
|
title: t('migrate-to-cloud.onprem.upload-snapshot-error-title', 'Error uploading snapshot'),
|
||||||
|
body: seeLogs,
|
||||||
|
error: uploadSnapshotError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancelSnapshotError) {
|
||||||
|
return {
|
||||||
|
severity: 'warning',
|
||||||
|
title: t('migrate-to-cloud.onprem.cancel-snapshot-error-title', 'Error cancelling creating snapshot'),
|
||||||
|
body: seeLogs,
|
||||||
|
error: cancelSnapshotError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshot?.status === 'ERROR') {
|
||||||
|
return {
|
||||||
|
severity: 'warning',
|
||||||
|
title: t('migrate-to-cloud.onprem.snapshot-error-status-title', 'Error migrating resources'),
|
||||||
|
body: t(
|
||||||
|
'migrate-to-cloud.onprem.snapshot-error-status-body',
|
||||||
|
'There was an error creating the snapshot or starting the migration process. See the Grafana server logs for more details'
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const errorCount = snapshot?.stats?.statuses?.['ERROR'] ?? 0;
|
||||||
|
if (snapshot?.status === 'FINISHED' && errorCount > 0) {
|
||||||
|
return {
|
||||||
|
severity: 'warning',
|
||||||
|
title: t('migrate-to-cloud.onprem.some-resources-errored-title', 'Resource migration complete'),
|
||||||
|
body: t(
|
||||||
|
'migrate-to-cloud.onprem.some-resources-errored-body',
|
||||||
|
'The migration has completed, but some items could not be migrated to the cloud stack. Check the failed resources for more details'
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,9 +15,13 @@ export function AlertWithTraceID(props: AlertWithTraceIDProps) {
|
|||||||
<Stack direction="column" gap={1}>
|
<Stack direction="column" gap={1}>
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
{/* Deliberately don't want to translate 'Trace ID' */}
|
{traceID && (
|
||||||
{/* eslint-disable-next-line @grafana/no-untranslated-strings */}
|
/* Deliberately don't want to translate 'Trace ID' */
|
||||||
{traceID && <Text element="p">Trace ID: {traceID}</Text>}
|
/* eslint-disable-next-line @grafana/no-untranslated-strings */
|
||||||
|
<Text element="p" color="secondary" variant="bodySmall">
|
||||||
|
Trace ID: {traceID}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Alert>
|
</Alert>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1111,6 +1111,19 @@
|
|||||||
"modal-title": "Migration token created",
|
"modal-title": "Migration token created",
|
||||||
"status": "Current status: <2></2>"
|
"status": "Current status: <2></2>"
|
||||||
},
|
},
|
||||||
|
"onprem": {
|
||||||
|
"cancel-snapshot-error-title": "Error cancelling creating snapshot",
|
||||||
|
"create-snapshot-error-title": "Error creating snapshot",
|
||||||
|
"disconnect-error-title": "Error disconnecting",
|
||||||
|
"error-see-server-logs": "See the Grafana server logs for more details",
|
||||||
|
"get-session-error-title": "Error loading migration configuration",
|
||||||
|
"get-snapshot-error-title": "Error loading snapshot",
|
||||||
|
"snapshot-error-status-body": "There was an error creating the snapshot or starting the migration process. See the Grafana server logs for more details",
|
||||||
|
"snapshot-error-status-title": "Error migrating resources",
|
||||||
|
"some-resources-errored-body": "The migration has completed, but some items could not be migrated to the cloud stack. Check the failed resources for more details",
|
||||||
|
"some-resources-errored-title": "Resource migration complete",
|
||||||
|
"upload-snapshot-error-title": "Error uploading snapshot"
|
||||||
|
},
|
||||||
"pdc": {
|
"pdc": {
|
||||||
"body": "Exposing your data sources to the internet can raise security concerns. Private data source connect (PDC) allows Grafana Cloud to access your existing data sources over a secure network tunnel.",
|
"body": "Exposing your data sources to the internet can raise security concerns. Private data source connect (PDC) allows Grafana Cloud to access your existing data sources over a secure network tunnel.",
|
||||||
"link-title": "Learn about PDC",
|
"link-title": "Learn about PDC",
|
||||||
@@ -1154,13 +1167,9 @@
|
|||||||
"summary": {
|
"summary": {
|
||||||
"cancel-snapshot": "Cancel snapshot",
|
"cancel-snapshot": "Cancel snapshot",
|
||||||
"disconnect": "Disconnect",
|
"disconnect": "Disconnect",
|
||||||
"disconnect-error-description": "See the Grafana server logs for more details",
|
|
||||||
"disconnect-error-title": "There was an error disconnecting",
|
|
||||||
"errored-resource-count": "Errors",
|
"errored-resource-count": "Errors",
|
||||||
"page-loading": "Loading...",
|
"page-loading": "Loading...",
|
||||||
"rebuild-snapshot": "Rebuild snapshot",
|
"rebuild-snapshot": "Rebuild snapshot",
|
||||||
"run-migration-error-description": "See the Grafana server logs for more details",
|
|
||||||
"run-migration-error-title": "Error creating snapshot",
|
|
||||||
"snapshot-date": "Snapshot timestamp",
|
"snapshot-date": "Snapshot timestamp",
|
||||||
"snapshot-not-created": "Not yet created",
|
"snapshot-not-created": "Not yet created",
|
||||||
"start-migration": "Build snapshot",
|
"start-migration": "Build snapshot",
|
||||||
|
|||||||
@@ -1111,6 +1111,19 @@
|
|||||||
"modal-title": "Mįģřäŧįőʼn ŧőĸęʼn čřęäŧęđ",
|
"modal-title": "Mįģřäŧįőʼn ŧőĸęʼn čřęäŧęđ",
|
||||||
"status": "Cūřřęʼnŧ şŧäŧūş: <2></2>"
|
"status": "Cūřřęʼnŧ şŧäŧūş: <2></2>"
|
||||||
},
|
},
|
||||||
|
"onprem": {
|
||||||
|
"cancel-snapshot-error-title": "Ēřřőř čäʼnčęľľįʼnģ čřęäŧįʼnģ şʼnäpşĥőŧ",
|
||||||
|
"create-snapshot-error-title": "Ēřřőř čřęäŧįʼnģ şʼnäpşĥőŧ",
|
||||||
|
"disconnect-error-title": "Ēřřőř đįşčőʼnʼnęčŧįʼnģ",
|
||||||
|
"error-see-server-logs": "Ŝęę ŧĥę Ğřäƒäʼnä şęřvęř ľőģş ƒőř mőřę đęŧäįľş",
|
||||||
|
"get-session-error-title": "Ēřřőř ľőäđįʼnģ mįģřäŧįőʼn čőʼnƒįģūřäŧįőʼn",
|
||||||
|
"get-snapshot-error-title": "Ēřřőř ľőäđįʼnģ şʼnäpşĥőŧ",
|
||||||
|
"snapshot-error-status-body": "Ŧĥęřę ŵäş äʼn ęřřőř čřęäŧįʼnģ ŧĥę şʼnäpşĥőŧ őř şŧäřŧįʼnģ ŧĥę mįģřäŧįőʼn přőčęşş. Ŝęę ŧĥę Ğřäƒäʼnä şęřvęř ľőģş ƒőř mőřę đęŧäįľş",
|
||||||
|
"snapshot-error-status-title": "Ēřřőř mįģřäŧįʼnģ řęşőūřčęş",
|
||||||
|
"some-resources-errored-body": "Ŧĥę mįģřäŧįőʼn ĥäş čőmpľęŧęđ, þūŧ şőmę įŧęmş čőūľđ ʼnőŧ þę mįģřäŧęđ ŧő ŧĥę čľőūđ şŧäčĸ. Cĥęčĸ ŧĥę ƒäįľęđ řęşőūřčęş ƒőř mőřę đęŧäįľş",
|
||||||
|
"some-resources-errored-title": "Ŗęşőūřčę mįģřäŧįőʼn čőmpľęŧę",
|
||||||
|
"upload-snapshot-error-title": "Ēřřőř ūpľőäđįʼnģ şʼnäpşĥőŧ"
|
||||||
|
},
|
||||||
"pdc": {
|
"pdc": {
|
||||||
"body": "Ēχpőşįʼnģ yőūř đäŧä şőūřčęş ŧő ŧĥę įʼnŧęřʼnęŧ čäʼn řäįşę şęčūřįŧy čőʼnčęřʼnş. Přįväŧę đäŧä şőūřčę čőʼnʼnęčŧ (PĐC) äľľőŵş Ğřäƒäʼnä Cľőūđ ŧő äččęşş yőūř ęχįşŧįʼnģ đäŧä şőūřčęş ővęř ä şęčūřę ʼnęŧŵőřĸ ŧūʼnʼnęľ.",
|
"body": "Ēχpőşįʼnģ yőūř đäŧä şőūřčęş ŧő ŧĥę įʼnŧęřʼnęŧ čäʼn řäįşę şęčūřįŧy čőʼnčęřʼnş. Přįväŧę đäŧä şőūřčę čőʼnʼnęčŧ (PĐC) äľľőŵş Ğřäƒäʼnä Cľőūđ ŧő äččęşş yőūř ęχįşŧįʼnģ đäŧä şőūřčęş ővęř ä şęčūřę ʼnęŧŵőřĸ ŧūʼnʼnęľ.",
|
||||||
"link-title": "Ŀęäřʼn äþőūŧ PĐC",
|
"link-title": "Ŀęäřʼn äþőūŧ PĐC",
|
||||||
@@ -1154,13 +1167,9 @@
|
|||||||
"summary": {
|
"summary": {
|
||||||
"cancel-snapshot": "Cäʼnčęľ şʼnäpşĥőŧ",
|
"cancel-snapshot": "Cäʼnčęľ şʼnäpşĥőŧ",
|
||||||
"disconnect": "Đįşčőʼnʼnęčŧ",
|
"disconnect": "Đįşčőʼnʼnęčŧ",
|
||||||
"disconnect-error-description": "Ŝęę ŧĥę Ğřäƒäʼnä şęřvęř ľőģş ƒőř mőřę đęŧäįľş",
|
|
||||||
"disconnect-error-title": "Ŧĥęřę ŵäş äʼn ęřřőř đįşčőʼnʼnęčŧįʼnģ",
|
|
||||||
"errored-resource-count": "Ēřřőřş",
|
"errored-resource-count": "Ēřřőřş",
|
||||||
"page-loading": "Ŀőäđįʼnģ...",
|
"page-loading": "Ŀőäđįʼnģ...",
|
||||||
"rebuild-snapshot": "Ŗęþūįľđ şʼnäpşĥőŧ",
|
"rebuild-snapshot": "Ŗęþūįľđ şʼnäpşĥőŧ",
|
||||||
"run-migration-error-description": "Ŝęę ŧĥę Ğřäƒäʼnä şęřvęř ľőģş ƒőř mőřę đęŧäįľş",
|
|
||||||
"run-migration-error-title": "Ēřřőř čřęäŧįʼnģ şʼnäpşĥőŧ",
|
|
||||||
"snapshot-date": "Ŝʼnäpşĥőŧ ŧįmęşŧämp",
|
"snapshot-date": "Ŝʼnäpşĥőŧ ŧįmęşŧämp",
|
||||||
"snapshot-not-created": "Ńőŧ yęŧ čřęäŧęđ",
|
"snapshot-not-created": "Ńőŧ yęŧ čřęäŧęđ",
|
||||||
"start-migration": "ßūįľđ şʼnäpşĥőŧ",
|
"start-migration": "ßūįľđ şʼnäpşĥőŧ",
|
||||||
|
|||||||
Reference in New Issue
Block a user