fix: translate leftover hardcoded ui text

This commit is contained in:
LukeGus committed 2026-09-30 14:39:28 -05:00
1 parent 1b342322dc
commit 20f19ff13b
26 files changed
+80 -41

No files matched your search

+5 -1
View File
@@ -379,7 +379,11 @@
"dragFilesToDesktop": "Dragging {{count}} files to the desktop",
"folderDragUnsupported": "Dragging folders to the desktop is not supported yet",
"saveToDesktopFailed": "Save failed: {{error}}",
"dragFailedDetail": "Drag failed: {{error}}"
"dragFailedDetail": "Drag failed: {{error}}",
"videoUnsupported": "Your browser cannot play this video format.",
"downloadToPlay": "Download to play it elsewhere",
"cannotPreviewType": "Cannot preview this file type",
"cannotPreviewTypeHint": "This file type has no preview. Download it to open it in another app."
},
"sftpTransfer": {
"title": "SFTP",
@@ -790,10 +790,7 @@ export function FileViewer({
<source src={videoUrl} type={mimeType} />
<div className="text-center text-muted-foreground p-4">
<AlertCircle className="w-8 h-8 mx-auto mb-2" />
<p>
Your browser does not support video playback for this
format.
</p>
<p>{t("fileManager.videoUnsupported")}</p>
{onDownload && (
<Button
variant="outline"
@@ -801,7 +798,7 @@ export function FileViewer({
className="mt-2 flex items-center gap-2 mx-auto"
>
<Download className="w-4 h-4" />
Download to play externally
{t("fileManager.downloadToPlay")}
</Button>
)}
</div>
@@ -918,11 +915,10 @@ export function FileViewer({
<div className="text-center text-muted-foreground">
<AlertCircle className="w-16 h-16 mx-auto mb-4 text-muted-foreground/50" />
<h3 className="text-lg font-medium mb-2">
Cannot preview this file type
{t("fileManager.cannotPreviewType")}
</h3>
<p className="text-sm mb-4">
This file type is not supported for preview. You can download
it to view in an external application.
{t("fileManager.cannotPreviewTypeHint")}
</p>
{onDownload && (
<Button
+9 -1
View File
@@ -161,7 +161,15 @@
"compactMode": "Compact Mode",
"selectHosts": "Select Hosts",
"listLayout": "List",
"gridLayout": "Grid"
"gridLayout": "Grid",
"configureUrl": "Set a URL in the widget settings",
"embeddedContent": "Embedded content",
"noBookmarks": "No bookmarks",
"noSections": "No sections set up",
"noServices": "No services set up",
"configureLocation": "Set a location in the widget settings",
"bannerTextPlaceholder": "Banner text",
"serviceNamePlaceholder": "My service"
},
"permissions": {
"use": {
@@ -39,7 +39,7 @@ export function ServiceLinkEditForm({
<Input
value={config.description ?? ""}
onChange={(e) => onChange({ ...config, description: e.target.value })}
placeholder="My service"
placeholder={t("homepage.serviceNamePlaceholder")}
className="h-8 text-sm"
/>
</div>
@@ -1,3 +1,4 @@
import { useTranslation } from "@termix/plugin-sdk/frontend";
import { Bookmark, ExternalLink } from "lucide-react";
import { registerWidget } from "./WidgetRegistry";
import type { BookmarkListConfig, WidgetComponentProps } from "../types.js";
@@ -8,6 +9,7 @@ function BookmarkListWidget({
widget,
isReadOnly,
}: WidgetComponentProps<BookmarkListConfig>) {
const { t } = useTranslation();
const { links } = config;
return (
@@ -23,7 +25,7 @@ function BookmarkListWidget({
<div className="flex-1 overflow-auto p-3 gap-1 flex flex-col">
{links.length === 0 && (
<span className="text-xs text-muted-foreground italic">
No bookmarks
{t("homepage.noBookmarks")}
</span>
)}
{links.map((link, i) =>
@@ -1,3 +1,4 @@
import { useTranslation } from "@termix/plugin-sdk/frontend";
import { Globe } from "lucide-react";
import { registerWidget } from "./WidgetRegistry";
import type { IframeConfig, WidgetComponentProps } from "../types.js";
@@ -9,13 +10,14 @@ function IframeWidget({
config,
isReadOnly,
}: WidgetComponentProps<IframeConfig>) {
const { t } = useTranslation();
const { url, scrolling } = config;
if (!url) {
return (
<div className="flex flex-col items-center justify-center w-full h-full gap-2 text-muted-foreground/50">
<Globe size={24} />
<span className="text-xs">Configure a URL in widget settings</span>
<span className="text-xs">{t("homepage.configureUrl")}</span>
</div>
);
}
@@ -29,7 +31,7 @@ function IframeWidget({
sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
scrolling={scrolling ? "yes" : "no"}
className="w-full h-full border-0"
title="Embedded content"
title={t("homepage.embeddedContent")}
/>
{/* Block interaction in read-only mode so the canvas can still pan */}
{isReadOnly && <div className="absolute inset-0 pointer-events-none" />}
@@ -1,3 +1,4 @@
import { useTranslation } from "@termix/plugin-sdk/frontend";
import { useRef } from "react";
import { List, ExternalLink } from "lucide-react";
import { registerWidget } from "./WidgetRegistry";
@@ -72,12 +73,13 @@ function LinkTreeWidget({
config,
isReadOnly,
}: WidgetComponentProps<LinkTreeConfig>) {
const { t } = useTranslation();
const { sections, compact } = config;
if (sections.length === 0) {
return (
<div className="flex items-center justify-center w-full h-full text-xs text-muted-foreground">
No sections configured
{t("homepage.noSections")}
</div>
);
}
@@ -1,3 +1,4 @@
import { useTranslation } from "@termix/plugin-sdk/frontend";
import { useRef, useState, useEffect } from "react";
import { Grid3x3, ExternalLink } from "lucide-react";
import { registerWidget } from "./WidgetRegistry";
@@ -107,12 +108,13 @@ function ServiceGridWidget({
config,
isReadOnly,
}: WidgetComponentProps<ServiceGridConfig>) {
const { t } = useTranslation();
const { services, columns, showLabels, iconSize } = config;
if (services.length === 0) {
return (
<div className="flex items-center justify-center w-full h-full text-xs text-muted-foreground">
No services configured
{t("homepage.noServices")}
</div>
);
}
@@ -1,3 +1,4 @@
import { useTranslation } from "@termix/plugin-sdk/frontend";
import { Type } from "lucide-react";
import { registerWidget } from "./WidgetRegistry";
import type { TextBannerConfig, WidgetComponentProps } from "../types.js";
@@ -23,6 +24,7 @@ const TEXT_ALIGN_MAP = {
};
function TextBannerWidget({ config }: WidgetComponentProps<TextBannerConfig>) {
const { t } = useTranslation();
const { text, fontSize, textAlign, fontWeight, backgroundColor } = config;
return (
@@ -31,7 +33,7 @@ function TextBannerWidget({ config }: WidgetComponentProps<TextBannerConfig>) {
style={backgroundColor ? { background: backgroundColor } : undefined}
>
<span className="whitespace-pre-wrap break-words w-full text-foreground leading-tight">
{text || "Banner text"}
{text || t("homepage.bannerTextPlaceholder")}
</span>
</div>
);
@@ -1,3 +1,4 @@
import { useTranslation } from "@termix/plugin-sdk/frontend";
import { useEffect, useState } from "react";
import {
Cloud,
@@ -54,6 +55,7 @@ function WeatherWidget({
widget,
config,
}: WidgetComponentProps<WeatherConfig>) {
const { t } = useTranslation();
const { location, unit, showForecast } = config;
const [data, setData] = useState<WttrResponse | null>(null);
const [error, setError] = useState(false);
@@ -90,7 +92,7 @@ function WeatherWidget({
if (!location) {
return (
<div className="flex items-center justify-center w-full h-full text-xs text-muted-foreground/60 p-3 text-center">
Configure a location in widget settings
{t("homepage.configureLocation")}
</div>
);
}
+2 -1
View File
@@ -177,7 +177,8 @@
"wgAllowedIPs": "Allowed IPs",
"wgLastHandshake": "Last handshake",
"wgHandshakeNever": "Never",
"wgTransfer": "Transfer"
"wgTransfer": "Transfer",
"wgNoPeers": "No peers"
}
},
"metricsHistory": {
@@ -162,7 +162,7 @@ export function WireGuardManagerCard({ hostId }: { hostId: number | null }) {
<div className="mb-1 ml-5 flex flex-col border-l border-border/50">
{iface.peers.length === 0 ? (
<span className="px-3 py-1 text-[10px] text-muted-foreground/50">
No peers
{t("hostMetrics.managers.wgNoPeers")}
</span>
) : (
iface.peers.map((peer) => (
+2 -1
View File
@@ -208,7 +208,8 @@
"colorScheme": "Color Scheme",
"backspaceKey": "Backspace Key",
"colorDepth": "Color Depth",
"resizeMethod": "Resize Method"
"resizeMethod": "Resize Method",
"driveNamePlaceholder": "Termix Drive"
},
"remoteDesktop": "Remote Desktop",
"tabRdp": "RDP",
@@ -523,7 +523,7 @@ export function HostEditorRdpTab({
{t("hosts.guac.driveName")}
</label>
<Input
placeholder="Termix Drive"
placeholder={t("hosts.guac.driveNamePlaceholder")}
value={form.guacamoleConfig["drive-name"] ?? ""}
onChange={(e) => setGuacField("drive-name", e.target.value)}
/>
@@ -45,5 +45,9 @@
"loadError": "Failed to load session logs",
"deleteError": "Failed to delete session log",
"filterByHost": "Filter by host..."
},
"player": {
"timeline": "Recording timeline",
"speed": "Playback speed"
}
}
@@ -1,3 +1,4 @@
import { useTranslation } from "@termix/plugin-sdk/frontend";
import { useCallback, useEffect, useRef, useState } from "react";
import { Pause, Play } from "lucide-react";
import { Terminal } from "@xterm/xterm";
@@ -36,6 +37,7 @@ function PlaybackControls({
onSeek: (position: number) => void;
onSpeed: (speed: number) => void;
}) {
const { t } = useTranslation();
return (
<div className="flex items-center gap-2 border-t border-border/60 bg-muted/20 px-3 py-2">
<button
@@ -61,7 +63,7 @@ function PlaybackControls({
value={Math.min(position, duration)}
onChange={(event) => onSeek(Number(event.target.value))}
className="min-w-0 flex-1 accent-primary"
aria-label="Recording timeline"
aria-label={t("player.timeline")}
/>
<span className="w-10 text-right text-[10px] tabular-nums text-muted-foreground">
{formatPosition(duration)}
@@ -70,7 +72,7 @@ function PlaybackControls({
value={speed}
onChange={(event) => onSpeed(Number(event.target.value))}
className="h-7 border border-border bg-background px-1 text-[10px]"
aria-label="Playback speed"
aria-label={t("player.speed")}
>
{SPEEDS.map((value) => (
<option key={value} value={value}>
+2 -1
View File
@@ -85,7 +85,8 @@
"imageChooseFile": "Choose an image file",
"imageUploaded": "Image uploaded: {{path}}",
"imageClipboardUnavailable": "This browser cannot read images from the clipboard",
"imageClipboardEmpty": "No image found in the clipboard"
"imageClipboardEmpty": "No image found in the clipboard",
"localShell": "Local terminal shell"
},
"terminalToolbar": {
"detachTmux": "Detach tmux",
@@ -185,7 +185,7 @@ export function LocalTerminal({
{isWindows && (
<div className="flex justify-end border-b border-border px-2 py-1">
<select
aria-label="Local terminal shell"
aria-label={t("terminal.localShell")}
className="rounded border border-border bg-background px-2 py-1 text-xs text-foreground"
value={shell}
onChange={(event) =>