mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 06:05:24 +00:00
fix: file manager and sftp text showing raw i18n keys
This commit is contained in:
1 parent
9015d5dccb
commit
95a5e75495
38 files changed
+61
-45
No files matched your search
@@ -214,4 +214,23 @@ export default tseslint.config([
|
||||
"termix-plugins/stay-inside": "error",
|
||||
},
|
||||
},
|
||||
{
|
||||
// react-i18next's hook reads core's namespace, so plugin strings show as raw keys.
|
||||
files: ["plugins/*/src/**/*.{ts,tsx}"],
|
||||
rules: {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
name: "react-i18next",
|
||||
importNames: ["useTranslation", "Trans", "withTranslation"],
|
||||
message:
|
||||
"Use useTranslation from @termix/plugin-sdk/frontend so keys resolve in this plugin's namespace.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]);
|
||||
@@ -26,7 +26,7 @@ import { useDragToDesktop } from "./hooks/useDragToDesktop";
|
||||
import { useDragToSystemDesktop } from "./hooks/useDragToSystemDesktop";
|
||||
import { useConfirmation } from "@termix/plugin-sdk/ui";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { FileManagerDialogs } from "./FileManagerDialogs.tsx";
|
||||
import { PassphraseDialog } from "@termix/plugin-sdk/ui";
|
||||
import { FileManagerToolbar } from "./FileManagerToolbar.tsx";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { FileManager } from "./FileManager.tsx";
|
||||
import { FullScreenAppWrapper, ConnectionScreen } from "@termix/plugin-sdk/ui";
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
ArrowRightLeft,
|
||||
Link,
|
||||
} from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { Kbd, KbdKey, KbdSeparator } from "@termix/plugin-sdk/ui";
|
||||
|
||||
const VIEWPORT_PADDING = 16;
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
Move,
|
||||
GitCompare,
|
||||
} from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import type { FileItem } from "./host-types";
|
||||
import type { CreateIntent } from "./file-manager-types.ts";
|
||||
import { formatFileSize } from "./file-manager-utils.ts";
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
ChevronDown,
|
||||
Check,
|
||||
} from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import type { SSHHost } from "./host-types";
|
||||
import {
|
||||
getRecentFiles,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { RotateCcw, Trash2 } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
Button,
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
Trash2,
|
||||
Upload,
|
||||
} from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { Kbd, KbdKey, KbdSeparator } from "@termix/plugin-sdk/ui";
|
||||
import type { LocalFileEntry } from "@termix/plugin-sdk/frontend";
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import React, {
|
||||
useState,
|
||||
} from "react";
|
||||
import { useVirtualizer } from "@tanstack/react-virtual";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
ArrowDown,
|
||||
|
||||
@@ -9,8 +9,8 @@ import {
|
||||
type MouseEvent,
|
||||
} from "react";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { TFunction } from "i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import type { TranslateFn as TFunction } from "@termix/plugin-sdk/frontend";
|
||||
import {
|
||||
ArrowLeftRight,
|
||||
File as FileIcon,
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
PasswordInput,
|
||||
} from "@termix/plugin-sdk/ui";
|
||||
import { Shield } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
|
||||
interface SudoPasswordDialogProps {
|
||||
open: boolean;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { TranslateFn } from "@termix/plugin-sdk/frontend";
|
||||
import type { TFunction } from "i18next";
|
||||
import type { TranslateFn as TFunction } from "@termix/plugin-sdk/frontend";
|
||||
import { getTransferStatus, listActiveTransfers } from "./api/transfer-api";
|
||||
import { createFormatTransferMetrics } from "./transferMetricsFormat.ts";
|
||||
import {
|
||||
|
||||
@@ -3,7 +3,7 @@ import AudioPlayer from "react-h5-audio-player";
|
||||
import "react-h5-audio-player/lib/styles.css";
|
||||
import { Music } from "lucide-react";
|
||||
import { cn } from "@termix/plugin-sdk/ui";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
|
||||
interface FileItem {
|
||||
name: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||
import { Check } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { cn } from "@termix/plugin-sdk/ui";
|
||||
import type { ResizableColumns } from "../hooks/useResizableColumns.ts";
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
Label,
|
||||
} from "@termix/plugin-sdk/ui";
|
||||
import { Package } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
|
||||
interface CompressDialogProps {
|
||||
open: boolean;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { DiffEditor } from "@monaco-editor/react";
|
||||
import { Button } from "@termix/plugin-sdk/ui";
|
||||
import { toast } from "sonner";
|
||||
import { DownloadProgressToast } from "./DownloadProgressToast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import {
|
||||
Download,
|
||||
RefreshCw,
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { DraggableWindow } from "./DraggableWindow.tsx";
|
||||
import { DiffViewer } from "./DiffViewer.tsx";
|
||||
import { useWindowManager } from "./WindowManager.tsx";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import type { FileItem, SSHHost } from "../host-types";
|
||||
|
||||
interface DiffWindowProps {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { formatTransferMbPerSec } from "../api/transfer-api";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { ArrowDownToLine } from "lucide-react";
|
||||
import { TransferProgressBar } from "./TransferProgressBar";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useState, useRef, useCallback, useEffect } from "react";
|
||||
import { cn } from "@termix/plugin-sdk/ui";
|
||||
import { Minus, X, Maximize2, Minimize2 } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
|
||||
interface DraggableWindowProps {
|
||||
title: string;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import React, { Suspense, lazy, useState, useEffect, useRef } from "react";
|
||||
import { cn } from "@termix/plugin-sdk/ui";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import {
|
||||
FileText,
|
||||
Image as ImageIcon,
|
||||
|
||||
@@ -15,7 +15,7 @@ import { SudoPasswordDialog } from "../SudoPasswordDialog.tsx";
|
||||
import { toast } from "sonner";
|
||||
import { DownloadProgressToast } from "./DownloadProgressToast";
|
||||
import type { SSHHost } from "../host-types";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
|
||||
interface FileItem {
|
||||
name: string;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { PhotoProvider, PhotoView } from "react-photo-view";
|
||||
import "react-photo-view/dist/react-photo-view.css";
|
||||
import { AlertCircle, Download } from "lucide-react";
|
||||
import { Button } from "@termix/plugin-sdk/ui";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
|
||||
interface ImagePreviewProps {
|
||||
content: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Button } from "@termix/plugin-sdk/ui";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { formatFileSize } from "../file-manager-utils.ts";
|
||||
|
||||
export interface LocalTransferBatchStatus {
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useState } from "react";
|
||||
import { Document, Page, pdfjs } from "react-pdf";
|
||||
import { AlertCircle, Download } from "lucide-react";
|
||||
import { Button } from "@termix/plugin-sdk/ui";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import pdfjsWorkerUrl from "pdfjs-dist/build/pdf.worker.min.mjs?url";
|
||||
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorkerUrl;
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
Button,
|
||||
Input,
|
||||
} from "@termix/plugin-sdk/ui";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { Lock } from "lucide-react";
|
||||
|
||||
interface FileItem {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { DraggableWindow } from "./DraggableWindow.tsx";
|
||||
import type { TabHandle as TerminalHandle } from "@termix/plugin-sdk/frontend";
|
||||
import { PluginComponent } from "@termix/plugin-sdk/ui";
|
||||
import { useWindowManager } from "./WindowManager.tsx";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import type { SSHHost } from "../host-types";
|
||||
import { ExternalLink } from "lucide-react";
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
getTransferProgressPercent,
|
||||
type TransferProgressResponse,
|
||||
} from "../api/transfer-api";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import {
|
||||
Archive,
|
||||
ArchiveRestore,
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
Label,
|
||||
Select2,
|
||||
} from "@termix/plugin-sdk/ui";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
ArrowRightLeft,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FolderSearch } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import { useHost } from "@termix/plugin-sdk/frontend";
|
||||
import { WidgetTitle } from "@termix/plugin-sdk/ui";
|
||||
import type {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useEffect, useRef } from "react";
|
||||
import { createElement } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from "@termix/plugin-sdk/frontend";
|
||||
import type { FileItem } from "../host-types";
|
||||
import type { LocalWalkResult } from "@termix/plugin-sdk/frontend";
|
||||
import { useSettings } from "@termix/plugin-sdk/frontend";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { TFunction } from "i18next";
|
||||
import type { TranslateFn as TFunction } from "@termix/plugin-sdk/frontend";
|
||||
import {
|
||||
formatDurationMs,
|
||||
formatTransferMbPerSec,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getErrorMessage } from "./lib/error-message";
|
||||
import { toast } from "sonner";
|
||||
import type { TFunction } from "i18next";
|
||||
import type { TranslateFn as TFunction } from "@termix/plugin-sdk/frontend";
|
||||
import {
|
||||
pollTransferUntilComplete,
|
||||
cancelTransferToHost,
|
||||
|
||||
@@ -4,9 +4,9 @@ import "@testing-library/jest-dom/vitest";
|
||||
import { FileManagerGrid } from "../../src/frontend/FileManagerGrid";
|
||||
import type { FileItem } from "../../src/frontend/host-types";
|
||||
|
||||
vi.mock("react-i18next", () => ({
|
||||
vi.mock("@termix/plugin-sdk/frontend", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("@termix/plugin-sdk/frontend")>()),
|
||||
useTranslation: () => ({ t: (key: string) => key }),
|
||||
initReactI18next: { type: "3rdParty", init: () => {} },
|
||||
}));
|
||||
|
||||
vi.mock("@tanstack/react-virtual", () => ({
|
||||
|
||||
@@ -35,12 +35,12 @@ const sonnerToast = vi.hoisted(() => {
|
||||
});
|
||||
vi.mock("sonner", () => ({ toast: sonnerToast }));
|
||||
|
||||
vi.mock("react-i18next", () => ({
|
||||
vi.mock("@termix/plugin-sdk/frontend", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("@termix/plugin-sdk/frontend")>()),
|
||||
useTranslation: () => ({
|
||||
t: (key: string, opts?: Record<string, unknown>) =>
|
||||
opts?.count !== undefined ? `${key}:${opts.count}` : key,
|
||||
}),
|
||||
initReactI18next: { type: "3rdParty", init: () => {} },
|
||||
}));
|
||||
|
||||
const HOME = "/Users/max";
|
||||
|
||||
@@ -47,13 +47,9 @@ vi.mock("../../src/frontend/transferMetricsFormat", () => ({
|
||||
createFormatTransferMetrics: () => () => "",
|
||||
}));
|
||||
|
||||
vi.mock("react-i18next", () => ({
|
||||
useTranslation: () => ({ t: (key: string) => key }),
|
||||
initReactI18next: { type: "3rdParty", init: () => {} },
|
||||
}));
|
||||
|
||||
vi.mock("@termix/plugin-sdk/frontend", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("@termix/plugin-sdk/frontend")>()),
|
||||
useTranslation: () => ({ t: (key: string) => key, language: "en" }),
|
||||
useSettings: () => ({
|
||||
values: { confirmBeforeTrash: api.confirmBeforeTrash },
|
||||
}),
|
||||
|
||||
@@ -26,12 +26,12 @@ vi.mock("../../../src/frontend/api/ssh-file-operations-api", () => api);
|
||||
vi.mock("sonner", () => ({
|
||||
toast: { loading: vi.fn(), success: vi.fn(), error: vi.fn() },
|
||||
}));
|
||||
vi.mock("react-i18next", () => ({
|
||||
vi.mock("@termix/plugin-sdk/frontend", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("@termix/plugin-sdk/frontend")>()),
|
||||
useTranslation: () => ({
|
||||
t: (key: string, params?: { name?: string }) =>
|
||||
params?.name ? `${key}: ${params.name}` : key,
|
||||
}),
|
||||
initReactI18next: { type: "3rdParty", init: () => {} },
|
||||
}));
|
||||
vi.mock("../../../src/frontend/components/WindowManager", () => ({
|
||||
useWindowManager: () => ({
|
||||
|
||||
@@ -121,6 +121,7 @@
|
||||
"linkInvalid": "This guest link is invalid or the meeting has ended"
|
||||
},
|
||||
"reopenFromPanel": "This meeting tab expired. Reopen the room from the Meetings panel.",
|
||||
"retry": "Retry",
|
||||
"requestControl": "Request control",
|
||||
"cancelControlRequest": "Cancel request",
|
||||
"controlQueue": "Control requests",
|
||||
|
||||
@@ -533,7 +533,7 @@ export function CollabRoomTab({
|
||||
<AlertCircle className="size-8" />
|
||||
<p className="max-w-sm text-center text-sm">{loadError}</p>
|
||||
<Button variant="outline" onClick={() => void refresh()}>
|
||||
{t("common.retry")}
|
||||
{t("collab.retry")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -562,7 +562,7 @@ export function CollabRoomTab({
|
||||
<AlertCircle className="size-4 shrink-0 text-destructive" />
|
||||
<span className="flex-1 truncate">{loadError}</span>
|
||||
<Button size="sm" variant="outline" onClick={() => void refresh()}>
|
||||
{t("common.retry")}
|
||||
{t("collab.retry")}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in new issue
Block a user