refactory(i18n): Improve internationalization configuration and add new translations
- Added multiple new translation items - Updated the two language files: en and zhcn - Added type definitions for new translation items in types/services.ts - Modified some components to use the new translation items
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import React from "react";
|
||||
import { Clock, TimerOff } from "lucide-react";
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { useLanguage } from "@/contexts/LanguageContext";
|
||||
|
||||
interface LastCheckedTimeProps {
|
||||
lastCheckedTime: string;
|
||||
@@ -10,6 +11,7 @@ interface LastCheckedTimeProps {
|
||||
}
|
||||
|
||||
export const LastCheckedTime = ({ lastCheckedTime, status, interval }: LastCheckedTimeProps) => {
|
||||
const { t } = useLanguage();
|
||||
// Format the time without seconds to display a static time
|
||||
const formatTimeWithoutSeconds = (timeString: string) => {
|
||||
try {
|
||||
@@ -55,7 +57,7 @@ export const LastCheckedTime = ({ lastCheckedTime, status, interval }: LastCheck
|
||||
<Clock className="h-4 w-4" />
|
||||
)}
|
||||
<span>
|
||||
{isPaused ? "Paused at " : ""}
|
||||
{isPaused ? t("pausedAt") : ""}
|
||||
{formattedTime}
|
||||
</span>
|
||||
</div>
|
||||
@@ -66,14 +68,14 @@ export const LastCheckedTime = ({ lastCheckedTime, status, interval }: LastCheck
|
||||
>
|
||||
<div className="flex flex-col gap-1 text-xs">
|
||||
<div className="font-medium">
|
||||
{isPaused ? "Monitoring Paused" : "Last Check Details"}
|
||||
{isPaused ? t("monitoringPaused") : t("lastCheckDetails")}
|
||||
</div>
|
||||
<div>
|
||||
{isPaused ? "No automatic checks" : `Checked at ${formattedTime}`}
|
||||
{isPaused ? t("noAutomaticChecks") : t("checkedAt") + `${formattedTime}`}
|
||||
</div>
|
||||
{interval && !isPaused && (
|
||||
<div>
|
||||
Check interval: {formatInterval(interval)}
|
||||
{t("checkInterval")}: {formatInterval(interval)}
|
||||
</div>
|
||||
)}
|
||||
<div className="text-gray-400 text-[10px]">
|
||||
|
||||
@@ -11,6 +11,7 @@ import { Service } from "@/types/service.types";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { useState, useEffect } from "react";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { useLanguage } from "@/contexts/LanguageContext";
|
||||
|
||||
interface ServiceEditDialogProps {
|
||||
open: boolean;
|
||||
@@ -19,6 +20,7 @@ interface ServiceEditDialogProps {
|
||||
}
|
||||
|
||||
export function ServiceEditDialog({ open, onOpenChange, service }: ServiceEditDialogProps) {
|
||||
const { t } = useLanguage();
|
||||
const queryClient = useQueryClient();
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
@@ -53,9 +55,9 @@ export function ServiceEditDialog({ open, onOpenChange, service }: ServiceEditDi
|
||||
}}>
|
||||
<DialogContent className="sm:max-w-[700px] max-h-[90vh] flex flex-col">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-xl">Edit Service</DialogTitle>
|
||||
<DialogTitle className="text-xl">{t("editService")}</DialogTitle>
|
||||
<DialogDescription>
|
||||
Update the details of your monitored service.
|
||||
{t("editServiceDesc")}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
{open && service && (
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import { MouseEvent } from "react";
|
||||
import {useLanguage} from "@/contexts/LanguageContext.tsx";
|
||||
|
||||
interface ServiceFormActionsProps {
|
||||
isSubmitting: boolean;
|
||||
@@ -14,6 +15,8 @@ export function ServiceFormActions({
|
||||
onCancel,
|
||||
submitLabel = "Create Service"
|
||||
}: ServiceFormActionsProps) {
|
||||
|
||||
const {t} = useLanguage();
|
||||
const handleCancel = (e: MouseEvent<HTMLButtonElement>) => {
|
||||
e.preventDefault();
|
||||
if (!isSubmitting) {
|
||||
@@ -29,7 +32,7 @@ export function ServiceFormActions({
|
||||
variant="outline"
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
Cancel
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
@@ -38,7 +41,7 @@ export function ServiceFormActions({
|
||||
{isSubmitting ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
Processing...
|
||||
{t("processing")}...
|
||||
</>
|
||||
) : (
|
||||
submitLabel
|
||||
|
||||
@@ -25,8 +25,8 @@ export function IncidentTable({ incidents }: IncidentTableProps) {
|
||||
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>{t("time")}</TableHead>
|
||||
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>{t("status")}</TableHead>
|
||||
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>{t("responseTime")}</TableHead>
|
||||
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>Error Message</TableHead>
|
||||
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>Details</TableHead>
|
||||
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>{t("errorMessage")}</TableHead>
|
||||
<TableHead className={theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}>{t("details")}</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
|
||||
@@ -9,10 +9,12 @@ import { IncidentTable } from "./IncidentTable";
|
||||
import { StatusFilter, PageSize } from "./types";
|
||||
import { getStatusChangeEvents } from "./utils";
|
||||
import { useTheme } from "@/contexts/ThemeContext";
|
||||
import { useLanguage } from "@/contexts/LanguageContext";
|
||||
|
||||
export function LatestChecksTable({ uptimeData }: { uptimeData: UptimeData[] }) {
|
||||
// Get current theme
|
||||
const { theme } = useTheme();
|
||||
const { t } = useLanguage();
|
||||
|
||||
// Filter state
|
||||
const [statusFilter, setStatusFilter] = useState<StatusFilter>("all");
|
||||
@@ -65,7 +67,7 @@ export function LatestChecksTable({ uptimeData }: { uptimeData: UptimeData[] })
|
||||
<CardHeader>
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
||||
<CardTitle className="text-card-foreground">
|
||||
<span>Incident History</span>
|
||||
<span>{t("incidentHistory")}</span>
|
||||
</CardTitle>
|
||||
<StatusFilterTabs statusFilter={statusFilter} onStatusFilterChange={setStatusFilter} />
|
||||
</div>
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
SelectValue
|
||||
} from "@/components/ui/select";
|
||||
import { PageSize } from "./types";
|
||||
import {useLanguage} from "@/contexts/LanguageContext.tsx";
|
||||
|
||||
interface TablePaginationProps {
|
||||
currentPage: number;
|
||||
@@ -35,6 +36,7 @@ export function TablePagination({
|
||||
onPageChange,
|
||||
onPageSizeChange,
|
||||
}: TablePaginationProps) {
|
||||
const {t} = useLanguage()
|
||||
// Generate page numbers
|
||||
const getPageNumbers = () => {
|
||||
const pages = [];
|
||||
@@ -58,7 +60,7 @@ export function TablePagination({
|
||||
return (
|
||||
<div className="mt-4 flex items-center justify-between">
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="text-sm text-muted-foreground">Rows per page:</span>
|
||||
<span className="text-sm text-muted-foreground">{t("rowsPerPage")}:</span>
|
||||
<Select
|
||||
value={pageSize}
|
||||
onValueChange={(value) => onPageSizeChange(value as PageSize)}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { Service } from "@/types/service.types";
|
||||
import { serviceService } from "@/services/serviceService";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
import { useLanguage } from "@/contexts/LanguageContext";
|
||||
|
||||
interface ServiceRowActionsProps {
|
||||
service: Service;
|
||||
@@ -31,6 +32,7 @@ export const ServiceRowActions = ({
|
||||
onMuteAlerts
|
||||
}: ServiceRowActionsProps) => {
|
||||
const { toast } = useToast();
|
||||
const { t } = useLanguage();
|
||||
|
||||
// Handle pause/resume directly from dropdown
|
||||
const handlePauseResume = async (e: React.MouseEvent) => {
|
||||
@@ -122,7 +124,7 @@ export const ServiceRowActions = ({
|
||||
}}
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
<span>View Detail</span>
|
||||
<span>{t("viewDetail")}</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
className="flex items-center gap-2 cursor-pointer text-base py-2.5"
|
||||
@@ -131,12 +133,12 @@ export const ServiceRowActions = ({
|
||||
{service.status === "paused" ? (
|
||||
<>
|
||||
<Play className="h-4 w-4" />
|
||||
<span>Resume Monitoring</span>
|
||||
<span>{t("resumeMonitoring")}</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Pause className="h-4 w-4" />
|
||||
<span>Pause Monitoring</span>
|
||||
<span>{t("pauseMonitoring")}</span>
|
||||
</>
|
||||
)}
|
||||
</DropdownMenuItem>
|
||||
@@ -148,7 +150,7 @@ export const ServiceRowActions = ({
|
||||
}}
|
||||
>
|
||||
<Edit className="h-4 w-4" />
|
||||
<span>Edit</span>
|
||||
<span>{t("edit")}</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
className="flex items-center gap-2 cursor-pointer text-base py-2.5"
|
||||
@@ -157,12 +159,12 @@ export const ServiceRowActions = ({
|
||||
{alertsMuted ? (
|
||||
<>
|
||||
<Bell className="h-4 w-4" />
|
||||
<span>Unmute Alerts</span>
|
||||
<span>{t("unmuteAlerts")}</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<BellOff className="h-4 w-4" />
|
||||
<span>Mute Alerts</span>
|
||||
<span>{t("muteAlerts")}</span>
|
||||
</>
|
||||
)}
|
||||
</DropdownMenuItem>
|
||||
@@ -175,7 +177,7 @@ export const ServiceRowActions = ({
|
||||
}}
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
<span>Delete</span>
|
||||
<span>{t("delete")}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
@@ -16,6 +16,7 @@ import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { TemplateType, templateTypeConfigs } from "@/services/templateService";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import {z} from "zod";
|
||||
|
||||
interface TemplateDialogProps {
|
||||
open: boolean;
|
||||
@@ -81,6 +82,7 @@ export const TemplateDialog: React.FC<TemplateDialogProps> = ({
|
||||
};
|
||||
|
||||
const renderPlaceholderGuide = () => {
|
||||
|
||||
const config = templateTypeConfigs[selectedTemplateType];
|
||||
if (!config) return null;
|
||||
|
||||
|
||||
+2
@@ -27,6 +27,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { Loader2, Copy } from "lucide-react";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { toast } from "@/hooks/use-toast";
|
||||
import { useLanguage } from "@/contexts/LanguageContext";
|
||||
|
||||
interface NotificationChannelDialogProps {
|
||||
open: boolean;
|
||||
@@ -34,6 +35,7 @@ interface NotificationChannelDialogProps {
|
||||
editingConfig: AlertConfiguration | null;
|
||||
}
|
||||
|
||||
|
||||
const baseSchema = z.object({
|
||||
notify_name: z.string().min(1, "Name is required"),
|
||||
notification_type: z.enum(["telegram", "discord", "slack", "signal", "google_chat", "email", "ntfy", "pushover", "notifiarr", "gotify", "webhook"]),
|
||||
|
||||
@@ -3,7 +3,6 @@ import { ServicesTranslations } from '../types/services';
|
||||
|
||||
export const servicesTranslations: ServicesTranslations = {
|
||||
serviceStatus: "Service Status",
|
||||
responseTime: "Response Time",
|
||||
uptime: "Uptime",
|
||||
lastChecked: "Last Checked",
|
||||
noServices: "No services match your filter criteria.",
|
||||
@@ -95,4 +94,35 @@ export const servicesTranslations: ServicesTranslations = {
|
||||
downServices: "DOWN SERVICES",
|
||||
pausedServices: "PAUSED SERVICES",
|
||||
warningServices: "WARNING SERVICES",
|
||||
|
||||
// ServiceRowActions.tsx
|
||||
viewDetail: "View Detail",
|
||||
resumeMonitoring: "Resume Monitoring",
|
||||
pauseMonitoring: "Pause Monitoring",
|
||||
|
||||
|
||||
//IncidentTable.tsx
|
||||
responseTime: "Response Time",
|
||||
errorMessage: "Error Message",
|
||||
details: "Details",
|
||||
unmuteAlerts: "Unmute Alerts",
|
||||
muteAlerts: "Mute Alerts",
|
||||
|
||||
//LastCheckedTime.tsx
|
||||
pausedAt: "Paused at ",
|
||||
lastCheckDetails: "Last Check Details",
|
||||
checkedAt: "Checked at ",
|
||||
monitoringPaused: "Monitoring Paused",
|
||||
noAutomaticChecks: "No automatic checks",
|
||||
|
||||
//ServiveEditDialog.tsx
|
||||
editService: "Edit Service",
|
||||
editServiceDesc: "Update the details of your monitored service.",
|
||||
|
||||
|
||||
incidentHistory: "Incident History",
|
||||
processing: "Processing",
|
||||
back: "Back",
|
||||
|
||||
|
||||
};
|
||||
@@ -59,4 +59,5 @@ export interface IncidentTranslations {
|
||||
affectedSystems: string;
|
||||
enterAffectedSystems: string;
|
||||
separateSystemsWithComma: string;
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
export interface ServicesTranslations {
|
||||
|
||||
serviceStatus: string;
|
||||
responseTime: string;
|
||||
uptime: string;
|
||||
lastChecked: string;
|
||||
noServices: string;
|
||||
@@ -93,5 +92,32 @@ export interface ServicesTranslations {
|
||||
upServices: string;
|
||||
downServices: string;
|
||||
pausedServices: string;
|
||||
warningServices: string;
|
||||
warningServices: string;
|
||||
|
||||
// ServiceRowActions.tsx
|
||||
viewDetail: string;
|
||||
resumeMonitoring: string;
|
||||
pauseMonitoring: string;
|
||||
unmuteAlerts: string;
|
||||
muteAlerts: string;
|
||||
|
||||
//IncidentTable.tsx
|
||||
responseTime: string;
|
||||
errorMessage: string;
|
||||
details: string;
|
||||
|
||||
//LastCheckedTime.tsx
|
||||
pausedAt: string;
|
||||
lastCheckDetails: string;
|
||||
checkedAt: string;
|
||||
monitoringPaused: string;
|
||||
noAutomaticChecks: string;
|
||||
|
||||
//ServiveEditDialog.tsx
|
||||
editService: string;
|
||||
editServiceDesc: string;
|
||||
|
||||
incidentHistory: string;
|
||||
processing: string;
|
||||
back: string;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { ServicesTranslations } from '../types/services';
|
||||
|
||||
export const servicesTranslations: ServicesTranslations = {
|
||||
serviceStatus: "服务状态",
|
||||
responseTime: "响应时间",
|
||||
uptime: "在线时间",
|
||||
lastChecked: "最后检查时间",
|
||||
noServices: "没有符合您筛选条件的服务。",
|
||||
@@ -95,4 +94,31 @@ export const servicesTranslations: ServicesTranslations = {
|
||||
downServices: "下线服务",
|
||||
pausedServices: "暂停服务",
|
||||
warningServices: "告警服务",
|
||||
|
||||
// ServiceRowActions.tsx
|
||||
viewDetail: "查看详情",
|
||||
resumeMonitoring: "恢复监控",
|
||||
pauseMonitoring: "暂停监控",
|
||||
unmuteAlerts: "取消静音警报",
|
||||
muteAlerts: "静音警报",
|
||||
|
||||
//IncidentTable.tsx
|
||||
responseTime: "响应时间",
|
||||
errorMessage: "错误信息",
|
||||
details: "详情",
|
||||
|
||||
//LastCheckedTime.tsx
|
||||
pausedAt: "暂停于 ",
|
||||
lastCheckDetails: "最近检查详情",
|
||||
checkedAt: "检查于 ",
|
||||
monitoringPaused: "监控已暂停",
|
||||
noAutomaticChecks: "无自动检查",
|
||||
|
||||
//ServiveEditDialog.tsx
|
||||
editService: "编辑服务",
|
||||
editServiceDesc: "更新您所监控服务的详细信息。",
|
||||
|
||||
incidentHistory: "事件历史",
|
||||
processing: "处理中",
|
||||
back: "返回",
|
||||
};
|
||||
Reference in New Issue
Block a user