-
Preview Stamp
+
+ {t("addStamp.preview", "Preview Stamp")}
+
{
const title = newBookmarkTitle.trim();
if (!title) {
- setAddBookmarkError("Bookmark title is required");
+ setAddBookmarkError(
+ t(
+ "viewer.bookmarks.bookmarkTitleRequired",
+ "Bookmark title is required",
+ ),
+ );
return;
}
// Resolve the file the viewer is currently displaying. activeFileId
@@ -695,7 +700,10 @@ export const BookmarkSidebar = ({
"viewer.bookmarks.expandAll",
"Expand all bookmarks",
)}
- title="Expand all"
+ title={t(
+ "viewer.bookmarks.expandAll",
+ "Expand all bookmarks",
+ )}
>
@@ -746,7 +760,10 @@ export const BookmarkSidebar = ({
>
setSearchTerm(event.currentTarget.value)}
leftSection={
@@ -839,7 +856,10 @@ export const BookmarkSidebar = ({
@@ -360,7 +360,7 @@ export function LayerSidebar({
onClick={hideAll}
disabled={allHidden || isApplying}
aria-label={t("viewer.layers.hideAll", "Hide all layers")}
- title="Hide all"
+ title={t("viewer.layers.hideAll", "Hide all layers")}
>
@@ -372,7 +372,7 @@ export function LayerSidebar({
size="sm"
onClick={toggleLayerSidebar}
aria-label={t("viewer.layers.closeSidebar", "Close layers sidebar")}
- title="Close layers"
+ title={t("viewer.layers.closeSidebar", "Close layers sidebar")}
>
diff --git a/frontend/editor/src/core/components/viewer/ThumbnailSidebar.tsx b/frontend/editor/src/core/components/viewer/ThumbnailSidebar.tsx
index 3fb62df970..6b195c4485 100644
--- a/frontend/editor/src/core/components/viewer/ThumbnailSidebar.tsx
+++ b/frontend/editor/src/core/components/viewer/ThumbnailSidebar.tsx
@@ -193,7 +193,10 @@ export function ThumbnailSidebar({
"viewer.thumbnails.closeSidebar",
"Close thumbnails sidebar",
)}
- title="Close thumbnails"
+ title={t(
+ "viewer.thumbnails.closeSidebar",
+ "Close thumbnails sidebar",
+ )}
>
diff --git a/frontend/editor/src/core/tools/SwaggerUI.tsx b/frontend/editor/src/core/tools/SwaggerUI.tsx
index 08a878b4c5..4ee6faf11d 100644
--- a/frontend/editor/src/core/tools/SwaggerUI.tsx
+++ b/frontend/editor/src/core/tools/SwaggerUI.tsx
@@ -1,8 +1,10 @@
import React, { useEffect } from "react";
import { BaseToolProps } from "@app/types/tool";
import { withBasePath } from "@app/constants/app";
+import { useTranslation } from "react-i18next";
const SwaggerUI: React.FC = () => {
+ const { t } = useTranslation();
useEffect(() => {
// Redirect to Swagger UI
window.open(withBasePath("/swagger-ui/5.21.0/index.html"), "_blank");
@@ -10,15 +12,15 @@ const SwaggerUI: React.FC = () => {
return (
diff --git a/frontend/editor/src/core/tools/formFill/FormFill.tsx b/frontend/editor/src/core/tools/formFill/FormFill.tsx
index a99f990f33..bf1a8f5fe6 100644
--- a/frontend/editor/src/core/tools/formFill/FormFill.tsx
+++ b/frontend/editor/src/core/tools/formFill/FormFill.tsx
@@ -204,7 +204,7 @@ const FormFill = (_props: BaseToolProps) => {
setTimeout(() => URL.revokeObjectURL(url), 250);
} catch (err) {
console.error("[FormFill] CSV extraction failed:", err);
- setSaveError("Failed to extract CSV");
+ setSaveError(t("formFill.extractCsvError", "Failed to extract CSV"));
} finally {
setExtracting(false);
}
@@ -223,7 +223,7 @@ const FormFill = (_props: BaseToolProps) => {
setTimeout(() => URL.revokeObjectURL(url), 250);
} catch (err) {
console.error("[FormFill] XLSX extraction failed:", err);
- setSaveError("Failed to extract XLSX");
+ setSaveError(t("formFill.extractXlsxError", "Failed to extract XLSX"));
} finally {
setExtracting(false);
}
@@ -246,7 +246,9 @@ const FormFill = (_props: BaseToolProps) => {
if (!currentFile || !isStirlingFile(currentFile)) return;
if (!validateForm()) {
- setSaveError("Please fill in all required fields");
+ setSaveError(
+ t("formFill.requiredFieldsError", "Please fill in all required fields"),
+ );
return;
}
@@ -641,7 +643,9 @@ const FormFill = (_props: BaseToolProps) => {
{field.label || field.name}
{field.required && (
- req
+
+ {t("formFill.requiredAbbreviation", "req")}
+
)}
@@ -683,10 +687,10 @@ const FormFill = (_props: BaseToolProps) => {
)}
{formState.isDirty || flattenChanged
- ? "Unsaved changes"
- : "All saved"}
+ ? t("formFill.unsavedChanges", "Unsaved changes")
+ : t("formFill.allSaved", "All saved")}
-
Ctrl+S to save
+
{t("formFill.saveShortcut", "Ctrl+S to save")}
)}
>
diff --git a/frontend/editor/src/core/ui/CodeBlock.tsx b/frontend/editor/src/core/ui/CodeBlock.tsx
index 1a05b23e4f..cff078057d 100644
--- a/frontend/editor/src/core/ui/CodeBlock.tsx
+++ b/frontend/editor/src/core/ui/CodeBlock.tsx
@@ -1,5 +1,6 @@
import { useState, type ReactNode } from "react";
import { Button } from "@app/ui/Button";
+import { useTranslation } from "react-i18next";
import "@app/ui/CodeBlock.css";
export type CodeLang =
@@ -33,6 +34,7 @@ export function CodeBlock({
maxHeight = 400,
className,
}: CodeBlockProps) {
+ const { t } = useTranslation();
const [copied, setCopied] = useState(false);
async function copy() {
@@ -64,7 +66,7 @@ export function CodeBlock({
onClick={copy}
aria-label="Copy code"
>
- {copied ? "Copied" : "Copy"}
+ {copied ? t("common.copied", "Copied!") : t("common.copy", "Copy")}
)}
diff --git a/frontend/editor/src/proprietary/routes/AuthCallback.test.tsx b/frontend/editor/src/proprietary/routes/AuthCallback.test.tsx
index 61b676e786..53b838a0d3 100644
--- a/frontend/editor/src/proprietary/routes/AuthCallback.test.tsx
+++ b/frontend/editor/src/proprietary/routes/AuthCallback.test.tsx
@@ -262,6 +262,6 @@ describe("AuthCallback", () => {
,
);
- expect(getByText("Completing authentication")).toBeInTheDocument();
+ expect(getByText("auth.callback.completing")).toBeInTheDocument();
});
});
diff --git a/frontend/editor/src/proprietary/routes/AuthCallback.tsx b/frontend/editor/src/proprietary/routes/AuthCallback.tsx
index f0e90f5ed0..5d09776df4 100644
--- a/frontend/editor/src/proprietary/routes/AuthCallback.tsx
+++ b/frontend/editor/src/proprietary/routes/AuthCallback.tsx
@@ -1,5 +1,6 @@
import { useEffect, useRef } from "react";
import { useNavigate } from "react-router-dom";
+import { useTranslation } from "react-i18next";
import {
consumePostLoginRedirectPath,
springAuth,
@@ -7,6 +8,7 @@ import {
import { markLoginLandingPending } from "@app/utils/loginLanding";
import { handleAuthCallbackSuccess } from "@app/extensions/authCallback";
import styles from "@app/routes/AuthCallback.module.css";
+import i18n from "@app/i18n";
/**
* OAuth Callback Handler
@@ -16,6 +18,7 @@ import styles from "@app/routes/AuthCallback.module.css";
* We extract it, store in localStorage, and redirect to the home page.
*/
export default function AuthCallback() {
+ const { t } = useTranslation();
const navigate = useNavigate();
const processingRef = useRef(false);
@@ -31,7 +34,12 @@ export default function AuthCallback() {
) {
navigate("/login", {
replace: true,
- state: { error: "You have been signed out. Please sign in again." },
+ state: {
+ error: i18n.t(
+ "auth.callback.signedOut",
+ "You have been signed out. Please sign in again.",
+ ),
+ },
});
return;
}
@@ -50,7 +58,12 @@ export default function AuthCallback() {
);
navigate("/login", {
replace: true,
- state: { error: "OAuth login failed - no token received." },
+ state: {
+ error: i18n.t(
+ "auth.callback.missingToken",
+ "OAuth login failed - no token received.",
+ ),
+ },
});
return;
}
@@ -67,7 +80,12 @@ export default function AuthCallback() {
localStorage.removeItem("stirling_jwt");
navigate("/login", {
replace: true,
- state: { error: "OAuth login failed - invalid token." },
+ state: {
+ error: i18n.t(
+ "auth.callback.invalidToken",
+ "OAuth login failed - invalid token.",
+ ),
+ },
});
return;
}
@@ -93,7 +111,12 @@ export default function AuthCallback() {
);
navigate("/login", {
replace: true,
- state: { error: "OAuth login failed. Please try again." },
+ state: {
+ error: i18n.t(
+ "auth.callback.oauthFailed",
+ "OAuth login failed. Please try again.",
+ ),
+ },
});
}
};
@@ -105,12 +128,20 @@ export default function AuthCallback() {
...
-
Completing authentication
+
+ {t("auth.callback.completing", "Completing authentication")}
+
- Please wait while we finish signing you in.
+ {t(
+ "auth.callback.pleaseWait",
+ "Please wait while we finish signing you in.",
+ )}
- You can close this window once it completes.
+ {t(
+ "auth.callback.windowMayClose",
+ "You can close this window once it completes.",
+ )}
diff --git a/frontend/editor/src/proprietary/routes/Landing.tsx b/frontend/editor/src/proprietary/routes/Landing.tsx
index d22acbba56..c377df1794 100644
--- a/frontend/editor/src/proprietary/routes/Landing.tsx
+++ b/frontend/editor/src/proprietary/routes/Landing.tsx
@@ -109,7 +109,9 @@ export default function Landing() {
>