fix: resolve QA report issues across routing, editor, i18n, and pipeline

- Add /tools/:toolId legacy redirect and catch-all 404 page (P1-12, P1-13)
- Add Shift+O dodge/burn/sponge cycle and Ctrl+Y redo shortcut (P1-3, P1-4)
- Fix Fit on Screen menu action to properly compute fit zoom (P1-8)
- Add filename input to editor export dialog (P1-2)
- Fix password validation mismatch: frontend now requires 8 chars (P1-11)
- Add license info to Settings About section (P1-9)
- Replace hardcoded strings in dropzone, files, pipeline with i18n keys (P1-17 to P1-25)
- Add 20+ missing i18n keys to all 21 locale files
- Translate Japanese editor.shapes and settings.aiFeatures sections (P1-19, P1-20)
- Fix RTL: use logical CSS properties in sidebar, files, app-layout (P2-24 to P2-26)
- Add single-file download button to pipeline results (P1-28)
- Fix compress step settings restoration on pipeline load (P1-27)
- Increase mobile nav touch targets to 44px minimum (P2-29)
This commit is contained in:
SnapOtter
2026-06-05 22:31:28 +08:00
parent 91e90b390e
commit 07e12754ba
35 changed files with 706 additions and 44 deletions
+11 -1
View File
@@ -1,6 +1,6 @@
import { APP_VERSION, en, shouldShowConsent } from "@snapotter/shared";
import { Component, type ErrorInfo, lazy, type ReactNode, Suspense, useEffect } from "react";
import { BrowserRouter, Navigate, Route, Routes, useLocation } from "react-router-dom";
import { BrowserRouter, Navigate, Route, Routes, useLocation, useParams } from "react-router-dom";
import { Toaster, toast } from "sonner";
import { ConnectionMonitor } from "./components/common/connection-monitor";
import { KeyboardShortcutProvider } from "./components/common/keyboard-shortcut-provider";
@@ -32,6 +32,9 @@ const AnalyticsConsentPage = lazy(() =>
const EditorPage = lazy(() =>
import("./pages/editor-page").then((m) => ({ default: m.EditorPage })),
);
const NotFoundPage = lazy(() =>
import("./pages/not-found-page").then((m) => ({ default: m.NotFoundPage })),
);
const ToolPage = lazy(() => import("./pages/tool-page").then((m) => ({ default: m.ToolPage })));
class ErrorBoundary extends Component<
@@ -167,6 +170,11 @@ function AuthGuard({ children }: { children: React.ReactNode }) {
return <>{children}</>;
}
function ToolRedirect() {
const { toolId } = useParams<{ toolId: string }>();
return <Navigate to={`/${toolId}`} replace />;
}
// Single page-level loading fallback — shown while JS for a route downloads.
function PageLoader() {
return (
@@ -242,8 +250,10 @@ export function App() {
<Route path="/color-effects" element={<Navigate to="/adjust-colors" replace />} />
<Route path="/analytics-consent" element={<AnalyticsConsentPage />} />
<Route path="/editor" element={<EditorPage />} />
<Route path="/tools/:toolId" element={<ToolRedirect />} />
<Route path="/:toolId" element={<ToolPage />} />
<Route path="/" element={<HomePage />} />
<Route path="*" element={<NotFoundPage />} />
</Routes>
</Suspense>
</AuthGuard>
+2 -2
View File
@@ -264,7 +264,7 @@ export function Dropzone({
<>
<div className="flex items-center gap-2 w-full max-w-xs">
<div className="h-px flex-1 bg-border" />
<span className="text-xs text-muted-foreground">or</span>
<span className="text-xs text-muted-foreground">{t.dropzone.orSeparator}</span>
<div className="h-px flex-1 bg-border" />
</div>
<div className="flex gap-2 w-full max-w-sm">
@@ -295,7 +295,7 @@ export function Dropzone({
disabled={urlLoading || !urlInput.trim()}
className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50"
>
{urlLoading ? "..." : "Add"}
{urlLoading ? t.dropzone.urlLoadingIndicator : t.dropzone.addUrlButton}
</button>
</div>
{urlError && <p className="text-xs text-destructive">{urlError}</p>}
@@ -74,6 +74,7 @@ export function ExportDialog({ onClose }: { onClose: () => void }) {
lockAspect: true,
transparent: true,
});
const [filename, setFilename] = useState("export");
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
const [copyStatus, setCopyStatus] = useState<"idle" | "copied">("idle");
@@ -200,7 +201,7 @@ export function ExportDialog({ onClose }: { onClose: () => void }) {
if (json.downloadUrl) {
const a = document.createElement("a");
a.href = json.downloadUrl;
a.download = `export.${settings.format}`;
a.download = `${filename || "export"}.${settings.format}`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
@@ -265,7 +266,7 @@ export function ExportDialog({ onClose }: { onClose: () => void }) {
if (json.downloadUrl) {
const a = document.createElement("a");
a.href = json.downloadUrl;
a.download = `export.${settings.format}`;
a.download = `${filename || "export"}.${settings.format}`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
@@ -282,7 +283,7 @@ export function ExportDialog({ onClose }: { onClose: () => void }) {
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `export.${settings.format}`;
a.download = `${filename || "export"}.${settings.format}`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
@@ -457,6 +458,18 @@ export function ExportDialog({ onClose }: { onClose: () => void }) {
</div>
)}
{/* Filename */}
<div>
<span className="block text-xs font-medium text-muted-foreground mb-1.5">Filename</span>
<input
type="text"
value={filename}
onChange={(e) => setFilename(e.target.value)}
placeholder="export"
className="w-full px-2 py-1 text-xs bg-muted rounded border border-border text-foreground outline-none focus:border-primary"
/>
</div>
{/* Format */}
<div>
<span className="block text-xs font-medium text-muted-foreground mb-1.5">Format</span>
@@ -57,6 +57,7 @@ function useMenuDefinitions(callbacks: MenuBarCallbacks): MenuDef[] {
const setSelection = useEditorStore((s) => s.setSelection);
const invertSelection = useEditorStore((s) => s.invertSelection);
const canvasSize = useEditorStore((s) => s.canvasSize);
const setPanOffset = useEditorStore((s) => s.setPanOffset);
const rotateCanvas = useEditorStore((s) => s.rotateCanvas);
const flipCanvasHorizontal = useEditorStore((s) => s.flipCanvasHorizontal);
const flipCanvasVertical = useEditorStore((s) => s.flipCanvasVertical);
@@ -327,11 +328,34 @@ function useMenuDefinitions(callbacks: MenuBarCallbacks): MenuDef[] {
items: [
{ label: "Zoom In", shortcut: mod("Ctrl+="), action: () => setZoom(zoom * 1.25) },
{ label: "Zoom Out", shortcut: mod("Ctrl+-"), action: () => setZoom(zoom / 1.25) },
{ label: "Fit on Screen", shortcut: mod("Ctrl+0"), action: () => setZoom(1) },
{
label: "Fit on Screen",
shortcut: mod("Ctrl+0"),
action: () => {
const editorCanvas = document.querySelector("[data-testid='editor-canvas']");
if (!editorCanvas) return;
const { width: vw, height: vh } = editorCanvas.getBoundingClientRect();
const scaleX = vw / canvasSize.width;
const scaleY = vh / canvasSize.height;
const fitZoom = Math.min(scaleX, scaleY) * 0.9;
const offsetX = (vw - canvasSize.width * fitZoom) / 2;
const offsetY = (vh - canvasSize.height * fitZoom) / 2;
setZoom(fitZoom);
setPanOffset({ x: offsetX, y: offsetY });
},
},
{
label: "Actual Pixels",
shortcut: mod("Ctrl+1"),
action: () => setZoom(1),
action: () => {
const editorCanvas = document.querySelector("[data-testid='editor-canvas']");
if (!editorCanvas) return;
const { width: vw, height: vh } = editorCanvas.getBoundingClientRect();
const offsetX = (vw - canvasSize.width) / 2;
const offsetY = (vh - canvasSize.height) / 2;
setZoom(1);
setPanOffset({ x: offsetX, y: offsetY });
},
dividerAfter: true,
},
{ label: "Rulers", checked: rulersVisible, action: toggleRulers },
+18 -12
View File
@@ -2,6 +2,7 @@ import { TOOLS } from "@snapotter/shared";
import { FileImage, ImageIcon, Workflow } from "lucide-react";
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "@/contexts/i18n-context";
import {
apiGetFileDetails,
formatHeaders,
@@ -74,6 +75,7 @@ interface FileDetailsProps {
}
export function FileDetails({ mobile = false }: FileDetailsProps) {
const { t } = useTranslation();
const { selectedFileId } = useFilesPageStore();
const setFiles = useFileStore((s) => s.setFiles);
const navigate = useNavigate();
@@ -139,11 +141,11 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
"flex flex-col items-center justify-center text-muted-foreground",
mobile
? "flex flex-col gap-4"
: "w-60 border-l border-border p-4 shrink-0 hidden lg:flex flex-col",
: "w-60 border-s border-border p-4 shrink-0 hidden lg:flex flex-col",
)}
>
<FileImage className="h-12 w-12 mb-3 opacity-30" />
<p className="text-sm">Select a file to view details</p>
<p className="text-sm">{t.files.selectFilePrompt}</p>
</div>
);
}
@@ -155,7 +157,7 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
"flex items-center justify-center",
mobile
? "flex flex-col gap-4"
: "w-60 border-l border-border p-4 shrink-0 hidden lg:flex flex-col",
: "w-60 border-s border-border p-4 shrink-0 hidden lg:flex flex-col",
)}
>
<div className="h-6 w-6 border-2 border-primary border-t-transparent rounded-full animate-spin" />
@@ -171,7 +173,7 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
"overflow-y-auto",
mobile
? "flex flex-col gap-4"
: "w-60 border-l border-border p-4 shrink-0 hidden lg:flex flex-col",
: "w-60 border-s border-border p-4 shrink-0 hidden lg:flex flex-col",
)}
>
{/* Thumbnail */}
@@ -187,24 +189,28 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
<div className="flex-1">
<div className="rounded-lg border border-border overflow-hidden">
<div className="bg-blue-500/10 border-b border-border px-3 py-2">
<h4 className="text-sm font-semibold text-blue-600 dark:text-blue-400">File Details</h4>
<h4 className="text-sm font-semibold text-blue-600 dark:text-blue-400">
{t.files.fileDetailsHeading}
</h4>
</div>
<div className="divide-y divide-border">
<DetailRow label="Name" value={details.originalName} />
<DetailRow label={t.files.name} value={details.originalName} />
<DetailRow
label="Format"
label={t.files.format}
value={details.mimeType.replace("image/", "").toUpperCase()}
/>
<DetailRow label="Size" value={formatSize(details.size)} />
<DetailRow label={t.files.size} value={formatSize(details.size)} />
<DetailRow
label="Dimensions"
label={t.files.dimensions}
value={details.width && details.height ? `${details.width} × ${details.height}` : "—"}
/>
<DetailRow label="Version" value={`V${details.version}`} />
<DetailRow label={t.files.version} value={`V${details.version}`} />
<DetailRow
label="Tools Used"
label={t.files.toolsUsed}
value={
details.toolChain.length > 0 ? details.toolChain.map(toolName).join(", ") : "None"
details.toolChain.length > 0
? details.toolChain.map(toolName).join(", ")
: t.files.none
}
/>
</div>
+11 -6
View File
@@ -1,11 +1,14 @@
import { Download, Search, Trash2, Workflow } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "@/contexts/i18n-context";
import { getFileDownloadUrl } from "@/lib/api";
import { format } from "@/lib/format";
import { useFilesPageStore } from "@/stores/files-page-store";
import { FileListItem } from "./file-list-item";
export function FileList() {
const { t } = useTranslation();
const {
files,
checkedIds,
@@ -61,7 +64,7 @@ export function FileList() {
<Search className="absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<input
type="text"
placeholder="Search files..."
placeholder={t.files.searchPlaceholder}
value={inputValue}
onChange={handleSearchChange}
className="w-full ps-8 pe-3 py-1.5 text-sm bg-muted rounded-lg border border-border focus:outline-none focus:ring-2 focus:ring-primary/50 text-foreground placeholder:text-muted-foreground"
@@ -78,7 +81,9 @@ export function FileList() {
className="h-4 w-4 accent-primary"
/>
<span className="text-xs text-muted-foreground flex-1">
{someChecked ? `${checkedIds.size} selected` : `${files.length} files`}
{someChecked
? format(t.files.selectedCount, { count: checkedIds.size })
: format(t.files.fileCount, { count: files.length })}
</span>
{someChecked && (
<>
@@ -88,7 +93,7 @@ export function FileList() {
className="flex items-center gap-1 px-2 py-1 text-xs text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
>
<Trash2 className="h-3.5 w-3.5" />
Delete
{t.files.delete}
</button>
<button
type="button"
@@ -96,7 +101,7 @@ export function FileList() {
className="flex items-center gap-1 px-2 py-1 text-xs text-primary hover:bg-primary/10 rounded-lg transition-colors"
>
<Workflow className="h-3.5 w-3.5" />
Pipeline
{t.files.pipeline}
</button>
<button
type="button"
@@ -104,7 +109,7 @@ export function FileList() {
className="flex items-center gap-1 px-2 py-1 text-xs text-foreground hover:bg-muted rounded-lg transition-colors"
>
<Download className="h-3.5 w-3.5" />
Download
{t.files.download}
</button>
</>
)}
@@ -124,7 +129,7 @@ export function FileList() {
)}
{!loading && !error && files.length === 0 && (
<div className="flex items-center justify-center h-32">
<p className="text-sm text-muted-foreground">No files found</p>
<p className="text-sm text-muted-foreground">{t.files.noFilesFound}</p>
</div>
)}
{!loading && !error && files.map((file) => <FileListItem key={file.id} file={file} />)}
+6 -4
View File
@@ -1,17 +1,19 @@
import { Clock, Upload } from "lucide-react";
import { useTranslation } from "@/contexts/i18n-context";
import { cn } from "@/lib/utils";
import { useFilesPageStore } from "@/stores/files-page-store";
export function FilesNav() {
const { t } = useTranslation();
const { activeTab, setActiveTab } = useFilesPageStore();
const items = [
{ id: "recent" as const, label: "Recent", icon: Clock },
{ id: "upload" as const, label: "Upload Files", icon: Upload },
{ id: "recent" as const, label: t.files.recentTab, icon: Clock },
{ id: "upload" as const, label: t.files.uploadTab, icon: Upload },
];
return (
<div className="w-48 border-r border-border p-4 shrink-0 hidden md:block">
<h3 className="text-sm font-semibold text-foreground mb-3">My Files</h3>
<div className="w-48 border-e border-border p-4 shrink-0 hidden md:block">
<h3 className="text-sm font-semibold text-foreground mb-3">{t.files.myFiles}</h3>
<div className="space-y-1">
{items.map((item) => (
<button
@@ -67,7 +67,7 @@ export function AppLayout({
className="fixed inset-0 z-40 bg-black/50 backdrop-blur-sm cursor-default"
onClick={() => setMobileSidebarOpen(false)}
/>
<div className="fixed inset-y-0 left-0 z-50 w-64 bg-background border-r border-border shadow-xl animate-in slide-in-from-left">
<div className="fixed inset-y-0 start-0 z-50 w-64 bg-background border-e border-border shadow-xl animate-in slide-in-from-left">
<div className="flex items-center justify-between p-3 border-b border-border">
<div className="flex items-center gap-2">
<OtterLogo className="h-5 w-5 text-primary" />
+1 -1
View File
@@ -110,7 +110,7 @@ export function Sidebar({
}
return (
<aside className="flex flex-col items-center w-16 bg-sidebar border-r border-border py-3 gap-1 shrink-0">
<aside className="flex flex-col items-center w-16 bg-sidebar border-e border-border py-3 gap-1 shrink-0">
<div className="mb-2 flex items-center justify-center">
<OtterLogo className="h-7 w-7 text-primary" />
</div>
@@ -21,10 +21,12 @@ export function CompressControls({ settings: initialSettings, onChange }: Compre
const [targetSizeValue, setTargetSizeValue] = useState("");
const [sizeUnit, setSizeUnit] = useState<SizeUnit>("KB");
const initializedRef = useRef(false);
const prevSettingsKeyRef = useRef<string | null>(null);
useEffect(() => {
if (!initialSettings || initializedRef.current) return;
initializedRef.current = true;
if (!initialSettings) return;
const key = JSON.stringify(initialSettings);
if (prevSettingsKeyRef.current === key) return;
prevSettingsKeyRef.current = key;
if (initialSettings.mode != null) setMode(initialSettings.mode as CompressMode);
if (initialSettings.quality != null) setQuality(Number(initialSettings.quality));
if (initialSettings.targetSizeKb != null)
@@ -129,7 +129,7 @@ function SortableStep({
e.stopPropagation();
onRemove();
}}
title="Remove"
title={t.automate.removeStep}
className="p-1 rounded hover:bg-destructive/10 text-muted-foreground hover:text-destructive"
>
<X className="h-4 w-4" />
@@ -159,6 +159,7 @@ export function PipelineBuilder({
onUpdateSettings,
onToggleStep,
}: PipelineBuilderProps) {
const { t } = useTranslation();
const sensors = useSensors(
useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }),
@@ -177,10 +178,8 @@ export function PipelineBuilder({
<div className="p-4 rounded-full bg-muted/50 mb-4">
<FileImage className="h-8 w-8 text-muted-foreground" />
</div>
<h3 className="text-sm font-medium text-foreground mb-1">No steps yet</h3>
<p className="text-sm text-muted-foreground max-w-[240px]">
Click tools from the palette to build your pipeline
</p>
<h3 className="text-sm font-medium text-foreground mb-1">{t.automate.noStepsHeading}</h3>
<p className="text-sm text-muted-foreground max-w-[240px]">{t.automate.addToolsPrompt}</p>
</div>
);
}
@@ -66,12 +66,16 @@ export function ToolPalette({ onAddStep, className }: ToolPaletteProps) {
return (
<div className={cn("flex flex-col h-full", className)}>
<div className="px-3 pt-3 pb-2 shrink-0">
<SearchBar value={search} onChange={setSearch} placeholder="Search tools..." />
<SearchBar
value={search}
onChange={setSearch}
placeholder={t.automate.searchToolsPlaceholder}
/>
</div>
<div className="flex-1 overflow-y-auto px-3 pb-3">
{availableTools.length === 0 ? (
<p className="text-sm text-muted-foreground text-center py-8">No tools found</p>
<p className="text-sm text-muted-foreground text-center py-8">{t.common.noToolsFound}</p>
) : isSearching ? (
<div className="space-y-1">
{availableTools.map((tool) => (
+31 -2
View File
@@ -41,6 +41,8 @@ const SHAPE_CYCLE: ToolType[] = [
"shape-polygon",
"shape-star",
];
// Dodge/burn/sponge cycle
const DODGE_CYCLE: ToolType[] = ["dodge", "burn", "sponge"];
// Fill/gradient cycle
const FILL_CYCLE: ToolType[] = ["fill", "gradient"];
@@ -199,12 +201,29 @@ export function useEditorShortcuts(callbacks?: {
{ preventDefault: true },
);
// O - Dodge tool
// O - Dodge/Burn/Sponge (cycles)
useHotkeys(
"o",
() => {
if (isInputFocused()) return;
useEditorStore.getState().setTool("dodge");
const current = useEditorStore.getState().activeTool;
if (DODGE_CYCLE.includes(current)) {
useEditorStore.getState().setTool(cycleSubtool(current, DODGE_CYCLE));
} else {
useEditorStore.getState().setTool("dodge");
}
},
{ preventDefault: true },
);
// Shift+O - Cycle dodge/burn/sponge subtypes
useHotkeys(
"shift+o",
() => {
if (isInputFocused()) return;
useEditorStore
.getState()
.setTool(cycleSubtool(useEditorStore.getState().activeTool, DODGE_CYCLE));
},
{ preventDefault: true },
);
@@ -361,6 +380,16 @@ export function useEditorShortcuts(callbacks?: {
{ preventDefault: true },
);
// Ctrl+Y / Cmd+Y - Redo (alternative)
useHotkeys(
"mod+y",
(e) => {
e.preventDefault();
useEditorStore.temporal.getState().redo();
},
{ preventDefault: true },
);
// Ctrl+S / Cmd+S - Save project
useHotkeys(
"mod+s",
+22
View File
@@ -0,0 +1,22 @@
import { Link } from "react-router-dom";
import { useTranslation } from "@/contexts/i18n-context";
export function NotFoundPage() {
const { t } = useTranslation();
return (
<div className="flex h-screen items-center justify-center bg-background text-foreground">
<div className="text-center space-y-4 max-w-md px-6">
<h1 className="text-6xl font-bold text-primary">404</h1>
<h2 className="text-xl font-semibold">{t.common.pageNotFound}</h2>
<p className="text-sm text-muted-foreground">{t.common.pageNotFoundDescription}</p>
<Link
to="/"
className="inline-block px-4 py-2 rounded-lg bg-primary text-primary-foreground text-sm font-medium"
>
{t.common.goHome}
</Link>
</div>
</div>
);
}
+26
View File
@@ -36,6 +36,9 @@ export const ar: TranslationKeys = {
unexpectedError: "حدث خطأ غير متوقع.",
retry: "إعادة المحاولة",
privacyPolicy: "سياسة الخصوصية",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "الأساسيات",
@@ -1679,6 +1682,8 @@ export const ar: TranslationKeys = {
githubLink: "مستودع GitHub",
docsLink: "التوثيق",
apiRefLink: "مرجع API (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1819,6 +1824,8 @@ export const ar: TranslationKeys = {
pipelineName: "اسم Pipeline",
pipelineDescription: "الوصف (اختياري)",
noStepsPrompt: "أضف خطوات لبناء أتمتتك",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "خطوة",
},
nav: {
@@ -1836,6 +1843,25 @@ export const ar: TranslationKeys = {
uploadTab: "رفع",
fileDetailsAriaLabel: "تفاصيل الملف",
fileDetailsHeading: "تفاصيل الملف",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "نوع الملف هذا غير مدعوم بهذه الأداة",
+26
View File
@@ -36,6 +36,9 @@ export const de: TranslationKeys = {
unexpectedError: "Ein unerwarteter Fehler ist aufgetreten.",
retry: "Erneut versuchen",
privacyPolicy: "Datenschutzerklaerung",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Grundlagen",
@@ -1704,6 +1707,8 @@ export const de: TranslationKeys = {
githubLink: "GitHub-Repository",
docsLink: "Dokumentation",
apiRefLink: "API-Referenz (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1848,6 +1853,8 @@ export const de: TranslationKeys = {
pipelineName: "Pipeline-Name",
pipelineDescription: "Beschreibung (optional)",
noStepsPrompt: "Fuegen Sie Schritte hinzu, um Ihre Automatisierung zu erstellen",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Schritt",
},
nav: {
@@ -1865,6 +1872,25 @@ export const de: TranslationKeys = {
uploadTab: "Hochladen",
fileDetailsAriaLabel: "Dateidetails",
fileDetailsHeading: "Dateidetails",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Dieser Dateityp wird von diesem Werkzeug nicht unterstuetzt",
+26
View File
@@ -34,6 +34,9 @@ export const en = {
somethingWentWrong: "Something went wrong",
unexpectedError: "An unexpected error occurred.",
privacyPolicy: "Privacy Policy",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Essentials",
@@ -1638,6 +1641,8 @@ export const en = {
githubLink: "GitHub Repository",
docsLink: "Documentation",
apiRefLink: "API Reference (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1779,6 +1784,8 @@ export const en = {
pipelineName: "Pipeline Name",
pipelineDescription: "Description (optional)",
noStepsPrompt: "Add steps to build your automation",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Step",
},
nav: {
@@ -1796,6 +1803,25 @@ export const en = {
uploadTab: "Upload",
fileDetailsAriaLabel: "File Details",
fileDetailsHeading: "File Details",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "This file type is not supported by this tool",
+26
View File
@@ -36,6 +36,9 @@ export const es: TranslationKeys = {
unexpectedError: "Ocurrio un error inesperado.",
retry: "Reintentar",
privacyPolicy: "Politica de privacidad",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Esenciales",
@@ -1683,6 +1686,8 @@ export const es: TranslationKeys = {
githubLink: "Repositorio en GitHub",
docsLink: "Documentacion",
apiRefLink: "Referencia API (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1825,6 +1830,8 @@ export const es: TranslationKeys = {
pipelineName: "Nombre del Pipeline",
pipelineDescription: "Descripcion (opcional)",
noStepsPrompt: "Agrega pasos para construir tu automatizacion",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Paso",
},
nav: {
@@ -1842,6 +1849,25 @@ export const es: TranslationKeys = {
uploadTab: "Subir",
fileDetailsAriaLabel: "Detalles del archivo",
fileDetailsHeading: "Detalles del archivo",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Este tipo de archivo no es compatible con esta herramienta",
+26
View File
@@ -36,6 +36,9 @@ export const fr: TranslationKeys = {
unexpectedError: "Une erreur inattendue est survenue.",
retry: "Réessayer",
privacyPolicy: "Politique de confidentialite",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Essentiels",
@@ -1702,6 +1705,8 @@ export const fr: TranslationKeys = {
githubLink: "Depot GitHub",
docsLink: "Documentation",
apiRefLink: "Reference API (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1846,6 +1851,8 @@ export const fr: TranslationKeys = {
pipelineName: "Nom du Pipeline",
pipelineDescription: "Description (optionnel)",
noStepsPrompt: "Ajoutez des etapes pour construire votre automatisation",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Etape",
},
nav: {
@@ -1863,6 +1870,25 @@ export const fr: TranslationKeys = {
uploadTab: "Importer",
fileDetailsAriaLabel: "Details du fichier",
fileDetailsHeading: "Details du fichier",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Ce type de fichier n'est pas pris en charge par cet outil",
+26
View File
@@ -36,6 +36,9 @@ export const hi: TranslationKeys = {
unexpectedError: "एक अप्रत्याशित त्रुटि हुई।",
retry: "पुनः प्रयास करें",
privacyPolicy: "गोपनीयता नीति",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "आवश्यक टूल्स",
@@ -1675,6 +1678,8 @@ export const hi: TranslationKeys = {
githubLink: "GitHub रिपॉज़िटरी",
docsLink: "डॉक्यूमेंटेशन",
apiRefLink: "API रेफरेंस (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1816,6 +1821,8 @@ export const hi: TranslationKeys = {
pipelineName: "Pipeline का नाम",
pipelineDescription: "विवरण (वैकल्पिक)",
noStepsPrompt: "अपना ऑटोमेशन बनाने के लिए स्टेप्स जोड़ें",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "स्टेप",
},
nav: {
@@ -1833,6 +1840,25 @@ export const hi: TranslationKeys = {
uploadTab: "अपलोड",
fileDetailsAriaLabel: "फाइल विवरण",
fileDetailsHeading: "फाइल विवरण",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "इस फाइल प्रकार को यह टूल सपोर्ट नहीं करता",
+26
View File
@@ -36,6 +36,9 @@ export const id: TranslationKeys = {
unexpectedError: "Terjadi kesalahan yang tidak terduga.",
retry: "Coba lagi",
privacyPolicy: "Kebijakan Privasi",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Dasar",
@@ -1691,6 +1694,8 @@ export const id: TranslationKeys = {
githubLink: "Repositori GitHub",
docsLink: "Dokumentasi",
apiRefLink: "Referensi API (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1833,6 +1838,8 @@ export const id: TranslationKeys = {
pipelineName: "Nama Pipeline",
pipelineDescription: "Deskripsi (opsional)",
noStepsPrompt: "Tambahkan langkah untuk membangun otomasi Anda",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Langkah",
},
nav: {
@@ -1850,6 +1857,25 @@ export const id: TranslationKeys = {
uploadTab: "Unggah",
fileDetailsAriaLabel: "Detail File",
fileDetailsHeading: "Detail File",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Jenis file ini tidak didukung oleh alat ini",
+26
View File
@@ -36,6 +36,9 @@ export const it: TranslationKeys = {
unexpectedError: "Si e verificato un errore imprevisto.",
retry: "Riprova",
privacyPolicy: "Informativa sulla privacy",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Essenziali",
@@ -1697,6 +1700,8 @@ export const it: TranslationKeys = {
githubLink: "Repository GitHub",
docsLink: "Documentazione",
apiRefLink: "Riferimento API (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1840,6 +1845,8 @@ export const it: TranslationKeys = {
pipelineName: "Nome del Pipeline",
pipelineDescription: "Descrizione (opzionale)",
noStepsPrompt: "Aggiungi passaggi per costruire la tua automazione",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Passaggio",
},
nav: {
@@ -1857,6 +1864,25 @@ export const it: TranslationKeys = {
uploadTab: "Carica",
fileDetailsAriaLabel: "Dettagli file",
fileDetailsHeading: "Dettagli file",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Questo tipo di file non e supportato da questo strumento",
+26
View File
@@ -36,6 +36,9 @@ export const ja: TranslationKeys = {
unexpectedError: "予期しないエラーが発生しました。",
retry: "再試行",
privacyPolicy: "プライバシーポリシー",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "基本ツール",
@@ -1648,6 +1651,8 @@ export const ja: TranslationKeys = {
githubLink: "GitHubリポジトリ",
docsLink: "ドキュメント",
apiRefLink: "APIリファレンス(Swagger",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1789,6 +1794,8 @@ export const ja: TranslationKeys = {
pipelineName: "Pipeline名",
pipelineDescription: "説明(任意)",
noStepsPrompt: "ステップを追加して自動化を構築",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "ステップ",
},
nav: {
@@ -1806,6 +1813,25 @@ export const ja: TranslationKeys = {
uploadTab: "アップロード",
fileDetailsAriaLabel: "ファイル詳細",
fileDetailsHeading: "ファイル詳細",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "このツールではサポートされていないファイルタイプです",
+26
View File
@@ -36,6 +36,9 @@ export const ko: TranslationKeys = {
unexpectedError: "예기치 않은 오류가 발생했습니다.",
retry: "재시도",
privacyPolicy: "개인정보 처리방침",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "기본 도구",
@@ -1633,6 +1636,8 @@ export const ko: TranslationKeys = {
githubLink: "GitHub 저장소",
docsLink: "문서",
apiRefLink: "API 레퍼런스 (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1774,6 +1779,8 @@ export const ko: TranslationKeys = {
pipelineName: "Pipeline 이름",
pipelineDescription: "설명 (선택)",
noStepsPrompt: "단계를 추가하여 자동화를 구성하세요",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "단계",
},
nav: {
@@ -1791,6 +1798,25 @@ export const ko: TranslationKeys = {
uploadTab: "업로드",
fileDetailsAriaLabel: "파일 상세",
fileDetailsHeading: "파일 상세",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "이 도구에서 지원하지 않는 파일 형식입니다",
+26
View File
@@ -36,6 +36,9 @@ export const nl: TranslationKeys = {
unexpectedError: "Er is een onverwachte fout opgetreden.",
retry: "Opnieuw proberen",
privacyPolicy: "Privacybeleid",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Basistools",
@@ -1694,6 +1697,8 @@ export const nl: TranslationKeys = {
githubLink: "GitHub-repository",
docsLink: "Documentatie",
apiRefLink: "API-referentie (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1836,6 +1841,8 @@ export const nl: TranslationKeys = {
pipelineName: "Pipeline-naam",
pipelineDescription: "Beschrijving (optioneel)",
noStepsPrompt: "Voeg stappen toe om je automatisering te bouwen",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Stap",
},
nav: {
@@ -1853,6 +1860,25 @@ export const nl: TranslationKeys = {
uploadTab: "Uploaden",
fileDetailsAriaLabel: "Bestandsdetails",
fileDetailsHeading: "Bestandsdetails",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Dit bestandstype wordt niet ondersteund door deze tool",
+26
View File
@@ -36,6 +36,9 @@ export const pl: TranslationKeys = {
unexpectedError: "Wystąpił nieoczekiwany błąd.",
retry: "Ponów",
privacyPolicy: "Polityka prywatności",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Podstawowe",
@@ -1700,6 +1703,8 @@ export const pl: TranslationKeys = {
githubLink: "Repozytorium GitHub",
docsLink: "Dokumentacja",
apiRefLink: "Dokumentacja API (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1843,6 +1848,8 @@ export const pl: TranslationKeys = {
pipelineName: "Nazwa Pipeline",
pipelineDescription: "Opis (opcjonalnie)",
noStepsPrompt: "Dodaj kroki, aby zbudować automatyzację",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Krok",
},
nav: {
@@ -1860,6 +1867,25 @@ export const pl: TranslationKeys = {
uploadTab: "Przesyłanie",
fileDetailsAriaLabel: "Szczegóły pliku",
fileDetailsHeading: "Szczegóły pliku",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Ten typ pliku nie jest obsługiwany przez to narzędzie",
+26
View File
@@ -36,6 +36,9 @@ export const ptBR: TranslationKeys = {
unexpectedError: "Ocorreu um erro inesperado.",
retry: "Tentar novamente",
privacyPolicy: "Politica de privacidade",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Essenciais",
@@ -1693,6 +1696,8 @@ export const ptBR: TranslationKeys = {
githubLink: "Repositorio no GitHub",
docsLink: "Documentacao",
apiRefLink: "Referencia da API (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1836,6 +1841,8 @@ export const ptBR: TranslationKeys = {
pipelineName: "Nome do Pipeline",
pipelineDescription: "Descricao (opcional)",
noStepsPrompt: "Adicione passos para construir sua automacao",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Passo",
},
nav: {
@@ -1853,6 +1860,25 @@ export const ptBR: TranslationKeys = {
uploadTab: "Enviar",
fileDetailsAriaLabel: "Detalhes do arquivo",
fileDetailsHeading: "Detalhes do arquivo",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Este tipo de arquivo nao e suportado por esta ferramenta",
+26
View File
@@ -36,6 +36,9 @@ export const ru: TranslationKeys = {
unexpectedError: "Произошла непредвиденная ошибка.",
retry: "Повторить",
privacyPolicy: "Политика конфиденциальности",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Основные",
@@ -1693,6 +1696,8 @@ export const ru: TranslationKeys = {
githubLink: "Репозиторий GitHub",
docsLink: "Документация",
apiRefLink: "Справочник API (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1835,6 +1840,8 @@ export const ru: TranslationKeys = {
pipelineName: "Название Pipeline",
pipelineDescription: "Описание (необязательно)",
noStepsPrompt: "Добавьте шаги для построения автоматизации",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Шаг",
},
nav: {
@@ -1852,6 +1859,25 @@ export const ru: TranslationKeys = {
uploadTab: "Загрузка",
fileDetailsAriaLabel: "Сведения о файле",
fileDetailsHeading: "Сведения о файле",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Этот тип файла не поддерживается данным инструментом",
+26
View File
@@ -36,6 +36,9 @@ export const sv: TranslationKeys = {
unexpectedError: "Ett ovantat fel uppstod.",
retry: "Försök igen",
privacyPolicy: "Integritetspolicy",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Grundlaggande",
@@ -1689,6 +1692,8 @@ export const sv: TranslationKeys = {
githubLink: "GitHub-arkiv",
docsLink: "Dokumentation",
apiRefLink: "API-referens (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1830,6 +1835,8 @@ export const sv: TranslationKeys = {
pipelineName: "Pipeline-namn",
pipelineDescription: "Beskrivning (valfritt)",
noStepsPrompt: "Lagg till steg for att bygga din automatisering",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Steg",
},
nav: {
@@ -1847,6 +1854,25 @@ export const sv: TranslationKeys = {
uploadTab: "Ladda upp",
fileDetailsAriaLabel: "Fildetaljer",
fileDetailsHeading: "Fildetaljer",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Denna filtyp stods inte av detta verktyg",
+26
View File
@@ -36,6 +36,9 @@ export const th: TranslationKeys = {
unexpectedError: "เกิดข้อผิดพลาดที่ไม่คาดคิด",
retry: "ลองใหม่",
privacyPolicy: "นโยบายความเป็นส่วนตัว",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "พื้นฐาน",
@@ -1667,6 +1670,8 @@ export const th: TranslationKeys = {
githubLink: "คลังเก็บโค้ด GitHub",
docsLink: "เอกสารประกอบ",
apiRefLink: "อ้างอิง API (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1807,6 +1812,8 @@ export const th: TranslationKeys = {
pipelineName: "ชื่อ Pipeline",
pipelineDescription: "คำอธิบาย (ไม่บังคับ)",
noStepsPrompt: "เพิ่มขั้นตอนเพื่อสร้างการทำงานอัตโนมัติ",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "ขั้นตอน",
},
nav: {
@@ -1824,6 +1831,25 @@ export const th: TranslationKeys = {
uploadTab: "อัปโหลด",
fileDetailsAriaLabel: "รายละเอียดไฟล์",
fileDetailsHeading: "รายละเอียดไฟล์",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "ไฟล์ประเภทนี้ไม่รองรับโดยเครื่องมือนี้",
+26
View File
@@ -36,6 +36,9 @@ export const tr: TranslationKeys = {
unexpectedError: "Beklenmeyen bir hata oluştu.",
retry: "Yeniden dene",
privacyPolicy: "Gizlilik Politikası",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Temel Araçlar",
@@ -1697,6 +1700,8 @@ export const tr: TranslationKeys = {
githubLink: "GitHub Deposu",
docsLink: "Dokümantasyon",
apiRefLink: "API Referansı (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1840,6 +1845,8 @@ export const tr: TranslationKeys = {
pipelineName: "Pipeline Adı",
pipelineDescription: "Açıklama (isteğe bağlı)",
noStepsPrompt: "Otomasyonunuzu oluşturmak için adımlar ekleyin",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Adım",
},
nav: {
@@ -1857,6 +1864,25 @@ export const tr: TranslationKeys = {
uploadTab: "Yükle",
fileDetailsAriaLabel: "Dosya Ayrıntıları",
fileDetailsHeading: "Dosya Ayrıntıları",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Bu dosya türü bu araç tarafından desteklenmiyor",
+26
View File
@@ -36,6 +36,9 @@ export const uk: TranslationKeys = {
unexpectedError: "Сталася неочікувана помилка.",
retry: "Повторити",
privacyPolicy: "Політика конфіденційності",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Основні",
@@ -1693,6 +1696,8 @@ export const uk: TranslationKeys = {
githubLink: "Репозиторій GitHub",
docsLink: "Документація",
apiRefLink: "Довідник API (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1836,6 +1841,8 @@ export const uk: TranslationKeys = {
pipelineName: "Назва Pipeline",
pipelineDescription: "Опис (необов'язково)",
noStepsPrompt: "Додайте кроки для побудови автоматизації",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Крок",
},
nav: {
@@ -1853,6 +1860,25 @@ export const uk: TranslationKeys = {
uploadTab: "Завантаження",
fileDetailsAriaLabel: "Відомості про файл",
fileDetailsHeading: "Відомості про файл",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Цей тип файлу не підтримується цим інструментом",
+26
View File
@@ -36,6 +36,9 @@ export const vi: TranslationKeys = {
unexpectedError: "Đã xảy ra lỗi không mong muốn.",
retry: "Thử lại",
privacyPolicy: "Chính sách bảo mật",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "Cơ bản",
@@ -1689,6 +1692,8 @@ export const vi: TranslationKeys = {
githubLink: "Kho mã nguồn GitHub",
docsLink: "Tài liệu",
apiRefLink: "Tham chiếu API (Swagger)",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1830,6 +1835,8 @@ export const vi: TranslationKeys = {
pipelineName: "Tên Pipeline",
pipelineDescription: "Mô tả (tùy chọn)",
noStepsPrompt: "Thêm các bước để xây dựng tự động hóa",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "Bước",
},
nav: {
@@ -1847,6 +1854,25 @@ export const vi: TranslationKeys = {
uploadTab: "Tải lên",
fileDetailsAriaLabel: "Chi tiết tệp",
fileDetailsHeading: "Chi tiết tệp",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "Loại tệp này không được công cụ này hỗ trợ",
+26
View File
@@ -36,6 +36,9 @@ export const zhCN: TranslationKeys = {
unexpectedError: "发生了意外错误。",
retry: "重试",
privacyPolicy: "隐私政策",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "基础工具",
@@ -1619,6 +1622,8 @@ export const zhCN: TranslationKeys = {
githubLink: "GitHub 仓库",
docsLink: "文档",
apiRefLink: "API 参考(Swagger",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1758,6 +1763,8 @@ export const zhCN: TranslationKeys = {
pipelineName: "Pipeline 名称",
pipelineDescription: "描述(可选)",
noStepsPrompt: "添加步骤来构建自动化流程",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "步骤",
},
nav: {
@@ -1775,6 +1782,25 @@ export const zhCN: TranslationKeys = {
uploadTab: "上传",
fileDetailsAriaLabel: "文件详情",
fileDetailsHeading: "文件详情",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "此工具不支持该文件类型",
+26
View File
@@ -36,6 +36,9 @@ export const zhTW: TranslationKeys = {
unexpectedError: "發生了非預期的錯誤。",
retry: "重試",
privacyPolicy: "隱私權政策",
pageNotFound: "Page not found",
pageNotFoundDescription: "The page you are looking for does not exist or has been moved.",
noToolsFound: "No tools found",
},
categories: {
essentials: "基本工具",
@@ -1617,6 +1620,8 @@ export const zhTW: TranslationKeys = {
githubLink: "GitHub儲存庫",
docsLink: "說明文件",
apiRefLink: "API參考(Swagger",
licenseLabel: "License:",
licenseDescription: "Dual-licensed under AGPLv3 and a commercial license.",
},
},
auth: {
@@ -1756,6 +1761,8 @@ export const zhTW: TranslationKeys = {
pipelineName: "Pipeline名稱",
pipelineDescription: "描述(選填)",
noStepsPrompt: "加入步驟來建構自動化",
noStepsHeading: "No steps yet",
searchToolsPlaceholder: "Search tools...",
step: "步驟",
},
nav: {
@@ -1773,6 +1780,25 @@ export const zhTW: TranslationKeys = {
uploadTab: "上傳",
fileDetailsAriaLabel: "檔案詳情",
fileDetailsHeading: "檔案詳情",
myFiles: "My Files",
searchPlaceholder: "Search files...",
selectedCount: "{count} selected",
fileCount: "{count} files",
fileCountSingular: "{count} file",
noFilesFound: "No files found",
selectFilePrompt: "Select a file to view details",
openFile: "Open File",
openInPipeline: "Open in Pipeline",
name: "Name",
format: "Format",
size: "Size",
dimensions: "Dimensions",
version: "Version",
toolsUsed: "Tools Used",
none: "None",
delete: "Delete",
pipeline: "Pipeline",
download: "Download",
},
dropzone: {
unsupportedFileType: "此工具不支援該檔案類型",