i18n: fix critical untranslated strings across the UI
Some checks failed
Deploy to Production / Trigger production update (push) Failing after 10s
Some checks failed
Deploy to Production / Trigger production update (push) Failing after 10s
- DestroyTab: wrap all hardcoded English strings with t() - instances: add status_reinstalling, status_changing_password keys - common: add shutdown key (ru + en) - fw: translate groups, ipsets, aliases, security_group and related actions - nodeadm: translate upgrade button label - en.json: fix Russian placeholder_notes in English locale
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { AlertTriangle, Loader2 } from 'lucide-react';
|
import { AlertTriangle, Loader2 } from 'lucide-react';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@@ -19,6 +20,7 @@ interface Props {
|
|||||||
|
|
||||||
export default function DestroyTab({ serverId, vmid, type, node, name }: Props) {
|
export default function DestroyTab({ serverId, vmid, type, node, name }: Props) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { t } = useTranslation();
|
||||||
const deleteVM = useDeleteVM(serverId, vmid, type, node);
|
const deleteVM = useDeleteVM(serverId, vmid, type, node);
|
||||||
const [confirmation, setConfirmation] = useState('');
|
const [confirmation, setConfirmation] = useState('');
|
||||||
|
|
||||||
@@ -29,7 +31,7 @@ export default function DestroyTab({ serverId, vmid, type, node, name }: Props)
|
|||||||
if (!canDelete) return;
|
if (!canDelete) return;
|
||||||
deleteVM.mutate(undefined, {
|
deleteVM.mutate(undefined, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
toast.success(`${displayName} has been destroyed`);
|
toast.success(t('instances.destroyed', { name: displayName }));
|
||||||
navigate('/instances');
|
navigate('/instances');
|
||||||
},
|
},
|
||||||
onError: (err) => toast.error(err.message),
|
onError: (err) => toast.error(err.message),
|
||||||
@@ -42,21 +44,20 @@ export default function DestroyTab({ serverId, vmid, type, node, name }: Props)
|
|||||||
<CardHeader className="pb-3">
|
<CardHeader className="pb-3">
|
||||||
<CardTitle className="flex items-center gap-2 text-destructive">
|
<CardTitle className="flex items-center gap-2 text-destructive">
|
||||||
<AlertTriangle className="h-5 w-5" />
|
<AlertTriangle className="h-5 w-5" />
|
||||||
Destroy {vmTypeLabel(type)}
|
{t('instances.destroy_title', { type: vmTypeLabel(type) })}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
<div className="rounded-md bg-destructive/10 p-3 text-sm text-destructive">
|
<div className="rounded-md bg-destructive/10 p-3 text-sm text-destructive">
|
||||||
<p className="font-medium">This action is irreversible!</p>
|
<p className="font-medium">{t('instances.destroy_irreversible')}</p>
|
||||||
<p className="mt-1 text-destructive/80">
|
<p className="mt-1 text-destructive/80">
|
||||||
This will permanently delete <strong>{displayName}</strong> (#{vmid}) and all its data,
|
{t('instances.destroy_warning_before')} <strong>{displayName}</strong> (#{vmid}){t('instances.destroy_warning_after')}
|
||||||
including disks and snapshots. IP allocations will be released.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="confirm-name">
|
<Label htmlFor="confirm-name">
|
||||||
Type <strong className="text-foreground">{displayName}</strong> to confirm
|
{t('instances.destroy_confirm_label_before')} <strong className="text-foreground">{displayName}</strong> {t('instances.destroy_confirm_label_after')}
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id="confirm-name"
|
id="confirm-name"
|
||||||
@@ -74,7 +75,7 @@ export default function DestroyTab({ serverId, vmid, type, node, name }: Props)
|
|||||||
className="w-full"
|
className="w-full"
|
||||||
>
|
>
|
||||||
{deleteVM.isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
{deleteVM.isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||||
Permanently Destroy {vmTypeLabel(type)}
|
{t('instances.destroy_button', { type: vmTypeLabel(type) })}
|
||||||
</Button>
|
</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -303,6 +303,7 @@
|
|||||||
"console": "Console",
|
"console": "Console",
|
||||||
"start": "Start",
|
"start": "Start",
|
||||||
"stop": "Stop",
|
"stop": "Stop",
|
||||||
|
"shutdown": "Shutdown",
|
||||||
"restart": "Restart",
|
"restart": "Restart",
|
||||||
"snapshots": "Snapshots",
|
"snapshots": "Snapshots",
|
||||||
"suspend": "Suspend",
|
"suspend": "Suspend",
|
||||||
@@ -357,7 +358,7 @@
|
|||||||
"placeholder_snapshot_name": "e.g. before-update",
|
"placeholder_snapshot_name": "e.g. before-update",
|
||||||
"placeholder_root_pam": "root@pam",
|
"placeholder_root_pam": "root@pam",
|
||||||
"placeholder_disk": "scsi0",
|
"placeholder_disk": "scsi0",
|
||||||
"placeholder_notes": "Описание / заметки об инстансе...",
|
"placeholder_notes": "Description / notes about the instance...",
|
||||||
"ipam": "IPAM"
|
"ipam": "IPAM"
|
||||||
},
|
},
|
||||||
"snap_archive": {
|
"snap_archive": {
|
||||||
@@ -530,7 +531,17 @@
|
|||||||
"backup_now": "Create backup",
|
"backup_now": "Create backup",
|
||||||
"backup_started": "Backup started in background",
|
"backup_started": "Backup started in background",
|
||||||
"backup_create": "Create backup",
|
"backup_create": "Create backup",
|
||||||
"backup_no_storages": "No backup-capable storages on this node"
|
"backup_no_storages": "No backup-capable storages on this node",
|
||||||
|
"destroy_title": "Destroy {{type}}",
|
||||||
|
"destroy_irreversible": "This action is irreversible!",
|
||||||
|
"destroy_warning_before": "This will permanently delete",
|
||||||
|
"destroy_warning_after": " and all its data, including disks and snapshots. IP allocations will be released.",
|
||||||
|
"destroy_confirm_label_before": "Type",
|
||||||
|
"destroy_confirm_label_after": "to confirm",
|
||||||
|
"destroy_button": "Permanently Destroy {{type}}",
|
||||||
|
"destroyed": "{{name}} has been destroyed",
|
||||||
|
"status_reinstalling": "Reinstalling",
|
||||||
|
"status_changing_password": "Changing password"
|
||||||
},
|
},
|
||||||
"wizard": {
|
"wizard": {
|
||||||
"title": "Create Instance",
|
"title": "Create Instance",
|
||||||
|
|||||||
@@ -303,6 +303,7 @@
|
|||||||
"console": "Консоль",
|
"console": "Консоль",
|
||||||
"start": "Запустить",
|
"start": "Запустить",
|
||||||
"stop": "Остановить",
|
"stop": "Остановить",
|
||||||
|
"shutdown": "Выключить",
|
||||||
"restart": "Перезагрузить",
|
"restart": "Перезагрузить",
|
||||||
"snapshots": "Снимки",
|
"snapshots": "Снимки",
|
||||||
"suspend": "Приостановить",
|
"suspend": "Приостановить",
|
||||||
@@ -530,7 +531,17 @@
|
|||||||
"backup_now": "Создать резервную копию",
|
"backup_now": "Создать резервную копию",
|
||||||
"backup_started": "Бэкап запущен в фоне",
|
"backup_started": "Бэкап запущен в фоне",
|
||||||
"backup_create": "Создать бэкап",
|
"backup_create": "Создать бэкап",
|
||||||
"backup_no_storages": "Нет хранилищ с поддержкой бэкапов на этой ноде"
|
"backup_no_storages": "Нет хранилищ с поддержкой бэкапов на этой ноде",
|
||||||
|
"destroy_title": "Уничтожить {{type}}",
|
||||||
|
"destroy_irreversible": "Это действие необратимо!",
|
||||||
|
"destroy_warning_before": "Будут безвозвратно удалены",
|
||||||
|
"destroy_warning_after": " и все данные, включая диски и снимки. IP-адреса будут освобождены.",
|
||||||
|
"destroy_confirm_label_before": "Введите",
|
||||||
|
"destroy_confirm_label_after": "для подтверждения",
|
||||||
|
"destroy_button": "Безвозвратно уничтожить {{type}}",
|
||||||
|
"destroyed": "{{name}} уничтожен",
|
||||||
|
"status_reinstalling": "Переустановка",
|
||||||
|
"status_changing_password": "Смена пароля"
|
||||||
},
|
},
|
||||||
"wizard": {
|
"wizard": {
|
||||||
"title": "Создание инстанса",
|
"title": "Создание инстанса",
|
||||||
@@ -808,16 +819,16 @@
|
|||||||
"enable": "Включить",
|
"enable": "Включить",
|
||||||
"disable": "Выключить",
|
"disable": "Выключить",
|
||||||
"rules": "Правила",
|
"rules": "Правила",
|
||||||
"groups": "Security Groups",
|
"groups": "Группы безопасности",
|
||||||
"ipsets": "IP Sets",
|
"ipsets": "IP-множества",
|
||||||
"aliases": "Aliases",
|
"aliases": "Псевдонимы",
|
||||||
"options": "Опции",
|
"options": "Опции",
|
||||||
"add_rule": "Добавить правило",
|
"add_rule": "Добавить правило",
|
||||||
"rule_hint": "Правила применяются сверху вниз.",
|
"rule_hint": "Правила применяются сверху вниз.",
|
||||||
"direction": "Направление",
|
"direction": "Направление",
|
||||||
"action": "Действие",
|
"action": "Действие",
|
||||||
"match": "Источник → Назначение",
|
"match": "Источник → Назначение",
|
||||||
"security_group": "Security group",
|
"security_group": "Группа безопасности",
|
||||||
"select_group": "Выберите группу",
|
"select_group": "Выберите группу",
|
||||||
"proto": "Протокол",
|
"proto": "Протокол",
|
||||||
"macro": "Макрос",
|
"macro": "Макрос",
|
||||||
@@ -827,18 +838,18 @@
|
|||||||
"sport": "Порт источн.",
|
"sport": "Порт источн.",
|
||||||
"enabled": "Включено",
|
"enabled": "Включено",
|
||||||
"log": "Логировать",
|
"log": "Логировать",
|
||||||
"err_group_required": "Выберите security group",
|
"err_group_required": "Выберите группу безопасности",
|
||||||
"rule_added": "Правило добавлено",
|
"rule_added": "Правило добавлено",
|
||||||
"rule_deleted": "Правило удалено",
|
"rule_deleted": "Правило удалено",
|
||||||
"delete_rule_confirm": "Удалить правило?",
|
"delete_rule_confirm": "Удалить правило?",
|
||||||
"add_group": "Добавить security group",
|
"add_group": "Добавить группу безопасности",
|
||||||
"delete_group": "Удалить security group",
|
"delete_group": "Удалить группу безопасности",
|
||||||
"group_name": "Имя группы",
|
"group_name": "Имя группы",
|
||||||
"group_added": "Группа создана",
|
"group_added": "Группа создана",
|
||||||
"group_deleted": "Группа удалена",
|
"group_deleted": "Группа удалена",
|
||||||
"add_ipset": "Добавить IP set",
|
"add_ipset": "Добавить IP-множество",
|
||||||
"delete_ipset": "Удалить IP set",
|
"delete_ipset": "Удалить IP-множество",
|
||||||
"ipset_name": "Имя IP set",
|
"ipset_name": "Имя IP-множества",
|
||||||
"ipset_added": "IP set создан",
|
"ipset_added": "IP set создан",
|
||||||
"ipset_deleted": "IP set удалён",
|
"ipset_deleted": "IP set удалён",
|
||||||
"add_alias": "Добавить алиас",
|
"add_alias": "Добавить алиас",
|
||||||
@@ -966,7 +977,7 @@
|
|||||||
"updates_count": "Доступно обновлений: {{n}}",
|
"updates_count": "Доступно обновлений: {{n}}",
|
||||||
"upgrade_hint": "«Установить обновления» откроет консоль ноды с apt dist-upgrade (потребуется подтверждение). Не закрывайте вкладку до завершения.",
|
"upgrade_hint": "«Установить обновления» откроет консоль ноды с apt dist-upgrade (потребуется подтверждение). Не закрывайте вкладку до завершения.",
|
||||||
"do_upgrade": "Установить обновления",
|
"do_upgrade": "Установить обновления",
|
||||||
"upgrade": "Upgrade",
|
"upgrade": "Обновить",
|
||||||
"repo_updated": "Репозиторий обновлён",
|
"repo_updated": "Репозиторий обновлён",
|
||||||
"enable": "Включить",
|
"enable": "Включить",
|
||||||
"disable": "Выключить"
|
"disable": "Выключить"
|
||||||
|
|||||||
Reference in New Issue
Block a user