refactor: consolidate English translations (#6640)
This commit is contained in:
1 parent
81aa704537
commit
9e14a07e64
449 files changed
+3515
-3922
No files matched your search
@@ -40,7 +40,7 @@ import type { RouterOutputs } from "@homarr/api";
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
import { backgroundImageAttachments, backgroundImageRepeats, backgroundImageSizes } from "@homarr/definitions";
|
||||
import { useZodForm } from "@homarr/form";
|
||||
import { useI18n, useScopedI18n } from "@homarr/translation/client";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import { boardSavePartialSettingsSchema } from "@homarr/validation/board";
|
||||
|
||||
import {
|
||||
@@ -97,7 +97,8 @@ export const AssistantConfigureBoardSettingsTool = ({
|
||||
status,
|
||||
toolCallId,
|
||||
}: ToolCallMessagePartProps<ConfigureBoardSettingsArgs, ConfigureBoardSettingsResult>) => {
|
||||
const t = useScopedI18n("common.assistant.configureBoardSettings");
|
||||
const t = useI18n("assistant.configureBoardSettings");
|
||||
const actionT = useI18n("common.action");
|
||||
const hasCompleteArguments = hasCompleteAssistantToolArguments(status);
|
||||
const boardId = args?.boardId ?? "";
|
||||
const settings = clientApi.board.getBoardSettings.useQuery(
|
||||
@@ -150,7 +151,7 @@ export const AssistantConfigureBoardSettingsTool = ({
|
||||
<Stack gap="sm">
|
||||
<Text size="sm">{t("loadErrorDescription")}</Text>
|
||||
<Button variant="light" color="red" size="compact-sm" w="fit-content" onClick={() => settings.refetch()}>
|
||||
{t("retry")}
|
||||
{actionT("tryAgain")}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Alert>
|
||||
@@ -199,7 +200,8 @@ const BoardSettingsForm = ({
|
||||
onSubmit: (changes: AssistantBoardSettingsChanges) => void;
|
||||
onCancel: () => void;
|
||||
}) => {
|
||||
const t = useScopedI18n("common.assistant.configureBoardSettings");
|
||||
const t = useI18n("assistant.configureBoardSettings");
|
||||
const actionT = useI18n("common.action");
|
||||
const boardT = useI18n();
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const currentValues = useMemo(() => toCurrentValues(current), [current]);
|
||||
@@ -297,7 +299,7 @@ const BoardSettingsForm = ({
|
||||
leftSection={copied ? <IconCheck size={14} /> : <IconCopy size={14} />}
|
||||
onClick={copy}
|
||||
>
|
||||
{copied ? t("copied") : t("copy")}
|
||||
{copied ? t("copied") : actionT("copy")}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { PropsWithChildren } from "react";
|
||||
import { useMemo } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import { AssistantWidgetRendererProvider } from "@homarr/widgets/assistant/context";
|
||||
|
||||
import { AssistantContext } from "./assistant-context";
|
||||
@@ -73,7 +73,7 @@ const unavailableMessageKeys = {
|
||||
} as const;
|
||||
|
||||
export const AssistantGate = ({ availability, children }: AssistantGateProps) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
|
||||
if (availability === "enabled") {
|
||||
return <EnabledAssistantRoot>{children}</EnabledAssistantRoot>;
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
import type { z } from "zod/v4";
|
||||
|
||||
import { AppForm } from "@homarr/forms-collection";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import type { appManageSchema } from "@homarr/validation/app";
|
||||
|
||||
import { getAssistantAskUserOptionKind } from "./assistant-ask-user";
|
||||
@@ -54,7 +54,7 @@ export const getAssistantAppFormValues = (
|
||||
) => (hasCompleteAssistantToolArguments(status) ? toAssistantAppValues(args) : null);
|
||||
|
||||
export const AssistantHumanToolError = () => {
|
||||
const t = useScopedI18n("common.assistant.toolPreparationError");
|
||||
const t = useI18n("assistant.toolPreparationError");
|
||||
return (
|
||||
<Alert color="red" variant="light" title={t("title")} icon={<IconAlertTriangle size={18} />}>
|
||||
{t("description")}
|
||||
@@ -68,7 +68,7 @@ export const AssistantAskUserTool = ({
|
||||
addResult,
|
||||
status,
|
||||
}: ToolCallMessagePartProps<AskUserArgs, AskUserResult>) => {
|
||||
const t = useScopedI18n("common.assistant.askUser");
|
||||
const t = useI18n("assistant.askUser");
|
||||
const [showOther, setShowOther] = useState(false);
|
||||
const [other, setOther] = useState("");
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
@@ -272,7 +272,7 @@ export const AssistantConfigureAppTool = ({
|
||||
status,
|
||||
toolCallId,
|
||||
}: ToolCallMessagePartProps<ConfigureAppArgs, AppValues>) => {
|
||||
const t = useScopedI18n("common.assistant.configureApp");
|
||||
const t = useI18n("assistant.configureApp");
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const initialValues = getAssistantAppFormValues(args, status);
|
||||
const autoConfirming = useAssistantAutomaticAction({
|
||||
|
||||
@@ -131,7 +131,7 @@ import { assistantProviderIds, assistantProviderPresets, assistantReasoningModes
|
||||
import type { AssistantProvider } from "@homarr/definitions";
|
||||
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
|
||||
import { useConfirmModal } from "@homarr/modals";
|
||||
import { useCurrentIntlLocale, useScopedI18n } from "@homarr/translation/client";
|
||||
import { useCurrentIntlLocale, useI18n } from "@homarr/translation/client";
|
||||
|
||||
import classes from "./assistant-panel.module.css";
|
||||
import { getAssistantActivityState } from "./assistant-activity-state";
|
||||
@@ -218,7 +218,7 @@ const ContextDirectiveChip = ({
|
||||
label,
|
||||
iconUrl,
|
||||
}: DirectiveChipProps & { iconUrl?: string }) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const Icon = contextIcons[directiveType as keyof typeof contextIcons] ?? IconAt;
|
||||
const safeIconUrl = getSafeAssistantMarkdownImageSource(iconUrl);
|
||||
const translationKey = getAssistantDirectiveTranslationKey(directiveType);
|
||||
@@ -291,7 +291,7 @@ const MarkdownTable = ({ children, ...props }: ComponentPropsWithoutRef<"table">
|
||||
);
|
||||
|
||||
const MarkdownImage = ({ src, alt = "", ...props }: ComponentPropsWithoutRef<"img">) => {
|
||||
const t = useScopedI18n("common.assistant.image");
|
||||
const t = useI18n("assistant.image");
|
||||
const safeSource = getSafeAssistantMarkdownImageSource(src);
|
||||
if (!safeSource) return null;
|
||||
|
||||
@@ -343,7 +343,7 @@ const AssistantSyntaxHighlighter = ({ code, components, language }: SyntaxHighli
|
||||
};
|
||||
|
||||
const MermaidDiagram = ({ code, components }: SyntaxHighlighterProps) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const colorScheme = useComputedColorScheme("light");
|
||||
const diagramId = `assistant-mermaid-${useId().replaceAll(/[^A-Za-z0-9_-]/gu, "")}`;
|
||||
const [rendered, setRendered] = useState<{ code: string; svg?: string; failed?: boolean }>({ code });
|
||||
@@ -541,7 +541,7 @@ const AttachmentPreview = () => {
|
||||
};
|
||||
|
||||
const Attachment = ({ removable = false }: { removable?: boolean }) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const attachment = useAuiState((state) => state.attachment);
|
||||
return (
|
||||
<AttachmentPrimitive.Root className={classes.attachment}>
|
||||
@@ -583,7 +583,7 @@ const ReasoningPart = (_props: ReasoningMessagePartProps) => (
|
||||
);
|
||||
|
||||
const AssistantMessagePending = ({ status }: EmptyMessagePartProps) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
if (status.type !== "running") return null;
|
||||
|
||||
return (
|
||||
@@ -622,7 +622,7 @@ const SourcePart = (source: SourceMessagePartProps) => {
|
||||
};
|
||||
|
||||
const FilePart = ({ data, filename, mimeType }: FileMessagePartProps) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const downloadable = data.startsWith("data:");
|
||||
const displayName = filename ?? mimeType;
|
||||
return (
|
||||
@@ -649,7 +649,7 @@ const FilePart = ({ data, filename, mimeType }: FileMessagePartProps) => {
|
||||
};
|
||||
|
||||
const ImagePart = ({ image, filename }: ImageMessagePartProps) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const source = getSafeAssistantAttachmentImageSource(
|
||||
image,
|
||||
typeof window === "undefined" ? undefined : window.location.origin,
|
||||
@@ -814,7 +814,7 @@ const getToolResultNavigation = (result: unknown) => {
|
||||
};
|
||||
|
||||
const ToolResultNavigation = ({ result }: { result: unknown }) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const router = useRouter();
|
||||
const links = getToolResultNavigation(result);
|
||||
|
||||
@@ -870,7 +870,7 @@ const ToolPart = ({
|
||||
respondToApproval,
|
||||
timing,
|
||||
}: ToolCallMessagePartProps) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const compact = useContext(AgentTraceToolContext);
|
||||
const [opened, setOpened] = useState(false);
|
||||
const [approvalResponse, setApprovalResponse] = useState<"approve" | "deny" | null>(null);
|
||||
@@ -1048,7 +1048,7 @@ const ChainOfThoughtLayout = ({ children }: { children?: ReactNode }) => (
|
||||
);
|
||||
|
||||
const AssistantChainOfThought = ({ children }: { children?: ReactNode }) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const contentId = useId();
|
||||
const { collapsed: preferredCollapsed, setCollapsed: setPreferredCollapsed } = useContext(ReasoningVisibilityContext);
|
||||
const { chainStatus, collapsed } = useAssistantReasoningState(preferredCollapsed);
|
||||
@@ -1083,7 +1083,7 @@ const AssistantChainOfThought = ({ children }: { children?: ReactNode }) => {
|
||||
};
|
||||
|
||||
const BranchPicker = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
return (
|
||||
<BranchPickerPrimitive.Root hideWhenSingleBranch className={classes.branchPicker}>
|
||||
<BranchPickerPrimitive.Previous asChild>
|
||||
@@ -1116,7 +1116,7 @@ const downloadAssistantMarkdown = (markdown: string, filename: string) => {
|
||||
};
|
||||
|
||||
const AssistantMessageActions = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const aui = useAui();
|
||||
const exportMessage = () => {
|
||||
const message = aui.message().getState();
|
||||
@@ -1129,7 +1129,6 @@ const AssistantMessageActions = () => {
|
||||
});
|
||||
downloadAssistantMarkdown(markdown, `assistant-message-${message.id.slice(0, 8)}.md`);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box className={classes.messageActions}>
|
||||
<ActionBarPrimitive.Root
|
||||
@@ -1211,7 +1210,7 @@ const AssistantMessageActions = () => {
|
||||
};
|
||||
|
||||
const UserMessageActions = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
return (
|
||||
<ActionBarPrimitive.Root hideWhenRunning autohide="not-last" className={classes.userActions}>
|
||||
<Group gap={2}>
|
||||
@@ -1235,14 +1234,15 @@ const UserMessageActions = () => {
|
||||
};
|
||||
|
||||
const EditComposer = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const actionT = useI18n("common.action");
|
||||
return (
|
||||
<ComposerPrimitive.Root className={classes.editComposer}>
|
||||
<ComposerPrimitive.Input className={classes.editComposerInput} rows={2} aria-label={t("editMessage")} />
|
||||
<Group gap="xs" justify="flex-end">
|
||||
<ComposerPrimitive.Cancel asChild>
|
||||
<Button size="compact-sm" variant="default">
|
||||
{t("cancelEdit")}
|
||||
{actionT("cancel")}
|
||||
</Button>
|
||||
</ComposerPrimitive.Cancel>
|
||||
<ComposerPrimitive.Send asChild>
|
||||
@@ -1361,7 +1361,7 @@ const ConversationTurn = ({
|
||||
threadId?: string;
|
||||
turn: AssistantConversationTurnUsage;
|
||||
}) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const detailsId = useId();
|
||||
const [opened, setOpened] = useState(false);
|
||||
const generationQuery = clientApi.assistant.getGenerationTelemetry.useQuery(
|
||||
@@ -1657,7 +1657,7 @@ const ConversationTurn = ({
|
||||
};
|
||||
|
||||
const ConversationContextBreakdown = ({ breakdown }: { breakdown: AssistantContextBreakdown }) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const hasContext = breakdown.percentage !== undefined;
|
||||
const categories = [
|
||||
{ label: t("usage.input"), value: breakdown.inputTokens },
|
||||
@@ -1715,7 +1715,7 @@ const ConversationContextBreakdown = ({ breakdown }: { breakdown: AssistantConte
|
||||
};
|
||||
|
||||
const ConversationContext = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const [opened, setOpened] = useState(false);
|
||||
const messages = useAuiState((state) => state.thread.messages);
|
||||
const threadId = useAuiState((state) => state.threadListItem.remoteId);
|
||||
@@ -1847,7 +1847,8 @@ const ConversationContext = () => {
|
||||
);
|
||||
};
|
||||
const RuntimeError = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const actionT = useI18n("common.action");
|
||||
return (
|
||||
<MessagePrimitive.Error>
|
||||
<ErrorPrimitive.Root className={classes.messageError}>
|
||||
@@ -1868,7 +1869,7 @@ const RuntimeError = () => {
|
||||
w="fit-content"
|
||||
leftSection={<IconRefresh size={14} />}
|
||||
>
|
||||
{t("responseError.retry")}
|
||||
{actionT("tryAgain")}
|
||||
</Button>
|
||||
</ActionBarPrimitive.Reload>
|
||||
</Stack>
|
||||
@@ -1879,7 +1880,7 @@ const RuntimeError = () => {
|
||||
};
|
||||
|
||||
const WebSearchActivity = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const metadata = useAuiState((state) => state.message.metadata);
|
||||
const telemetry = getAssistantTelemetry(metadata);
|
||||
if (!telemetry) return null;
|
||||
@@ -1997,7 +1998,8 @@ const assistantThreadMessageComponents = { UserMessage, AssistantMessage };
|
||||
const HistorySelectContext = createContext<() => void>(() => undefined);
|
||||
|
||||
const ThreadListItem = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const actionT = useI18n("common.action");
|
||||
const aui = useAui();
|
||||
const { openConfirmModal } = useConfirmModal();
|
||||
const onSelect = useContext(HistorySelectContext);
|
||||
@@ -2057,7 +2059,7 @@ const ThreadListItem = () => {
|
||||
title: t("deleteConversation.title"),
|
||||
children: t("deleteConversation.description", { title: title ?? t("newConversation") }),
|
||||
confirmProps: { color: "red" },
|
||||
labels: { confirm: t("delete"), cancel: t("cancel") },
|
||||
labels: { confirm: actionT("delete"), cancel: actionT("cancel") },
|
||||
onConfirm: async () => {
|
||||
try {
|
||||
await aui.threadListItem().delete();
|
||||
@@ -2103,7 +2105,7 @@ const ThreadListItem = () => {
|
||||
variant="subtle"
|
||||
color="gray"
|
||||
size="sm"
|
||||
aria-label={t("cancel")}
|
||||
aria-label={actionT("cancel")}
|
||||
disabled={renaming}
|
||||
onClick={() => setRenameOpened(false)}
|
||||
>
|
||||
@@ -2154,8 +2156,8 @@ const ThreadListItem = () => {
|
||||
variant="subtle"
|
||||
color="red"
|
||||
size="sm"
|
||||
title={t("delete")}
|
||||
aria-label={t("delete")}
|
||||
title={actionT("delete")}
|
||||
aria-label={actionT("delete")}
|
||||
onClick={deleteConversation}
|
||||
>
|
||||
<IconTrash size={14} />
|
||||
@@ -2179,7 +2181,7 @@ const ThreadListItem = () => {
|
||||
};
|
||||
|
||||
const ThreadHistory = ({ onSelect }: { onSelect: () => void }) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const [query, setQuery] = useState("");
|
||||
const normalizedQuery = query.trim().toLocaleLowerCase();
|
||||
const threadItems = useAuiState((state) => state.threads.threadItems);
|
||||
@@ -2233,7 +2235,7 @@ const ThreadHistory = ({ onSelect }: { onSelect: () => void }) => {
|
||||
};
|
||||
|
||||
const ConversationHistory = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const [opened, setOpened] = useState(false);
|
||||
return (
|
||||
<Popover
|
||||
@@ -2272,7 +2274,7 @@ const ConversationHistory = () => {
|
||||
};
|
||||
|
||||
const AutoApprovalControl = () => {
|
||||
const t = useScopedI18n("common.assistant.autoApproval");
|
||||
const t = useI18n("assistant.autoApproval");
|
||||
const [opened, setOpened] = useState(false);
|
||||
const { enabled, setEnabled } = useAssistantAutoApproval();
|
||||
|
||||
@@ -2331,7 +2333,7 @@ const ViewRefreshAction = ({
|
||||
isRefreshing,
|
||||
onRefresh,
|
||||
}: Pick<AssistantConversationControls, "isRefreshing" | "onRefresh">) => {
|
||||
const t = useScopedI18n("common.assistant.refresh");
|
||||
const t = useI18n("assistant.refresh");
|
||||
|
||||
const refresh = async () => {
|
||||
try {
|
||||
@@ -2360,7 +2362,7 @@ const ViewRefreshAction = ({
|
||||
};
|
||||
|
||||
const EmptyThread = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
return (
|
||||
<ThreadPrimitive.Empty>
|
||||
<Box className={classes.empty}>
|
||||
@@ -2461,7 +2463,7 @@ const TriggerItem = ({ item, index }: { item: Unstable_TriggerItem; index: numbe
|
||||
};
|
||||
|
||||
const ComposerTriggers = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const aui = useAui();
|
||||
const mentionViewportRef = useRef<HTMLDivElement>(null);
|
||||
const slashViewportRef = useRef<HTMLDivElement>(null);
|
||||
@@ -2604,7 +2606,7 @@ const RuntimeControls = ({
|
||||
onModelChange,
|
||||
onReasoningChange,
|
||||
}: ComposerProps) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const [modelSearch, setModelSearch] = useState("");
|
||||
const selectedModel = models.find((model) => model.id === modelId);
|
||||
const normalizedModelSearch = modelSearch.trim().toLocaleLowerCase();
|
||||
@@ -2759,7 +2761,7 @@ const providerQuotaColors = {
|
||||
} as const;
|
||||
|
||||
const HomarrProviderQuota = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const locale = useCurrentIntlLocale();
|
||||
const preferences = useAssistantPreferences();
|
||||
const quota = preferences.quota;
|
||||
@@ -2882,7 +2884,7 @@ const HomarrProviderQuota = () => {
|
||||
};
|
||||
|
||||
const Composer = (props: ComposerProps) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const preferences = useAssistantPreferences();
|
||||
const running = useAuiState((state) => state.thread.isRunning);
|
||||
const hasPendingAction = props.pendingAction !== undefined;
|
||||
@@ -2987,7 +2989,7 @@ const Composer = (props: ComposerProps) => {
|
||||
};
|
||||
|
||||
const usePendingActionCopy = (action: AssistantPendingAction | undefined) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
if (!action) return undefined;
|
||||
if (action.kind === "question") {
|
||||
return { title: t("pendingAction.answerTitle"), detail: action.detail ?? t("pendingAction.answerFallback") };
|
||||
@@ -3004,7 +3006,7 @@ const usePendingActionCopy = (action: AssistantPendingAction | undefined) => {
|
||||
};
|
||||
|
||||
const PendingActionBanner = ({ pendingAction }: { pendingAction: AssistantPendingAction | undefined }) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const copy = usePendingActionCopy(pendingAction);
|
||||
if (!copy || pendingAction?.kind === "question") return null;
|
||||
|
||||
@@ -3039,7 +3041,7 @@ const PendingQuestionDock = ({
|
||||
pendingAction: AssistantPendingAction | undefined;
|
||||
setTarget: (target: HTMLDivElement | null) => void;
|
||||
}) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
if (pendingAction?.kind !== "question") return null;
|
||||
|
||||
return (
|
||||
@@ -3073,7 +3075,7 @@ const AssistantActivityBar = ({
|
||||
| "onDismissActivity"
|
||||
| "activityDismissed"
|
||||
>) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const pendingCopy = usePendingActionCopy(pendingAction);
|
||||
const needsApproval = pendingAction !== undefined || latestStatus?.type === "requires-action";
|
||||
const failed = latestStatus?.type === "incomplete" && latestStatus.reason !== "cancelled";
|
||||
@@ -3161,7 +3163,7 @@ interface AssistantConversationSurfaceProps extends AssistantConversationControl
|
||||
}
|
||||
|
||||
const AssistantPanelIdentity = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const threadTitle = useAuiState((state) => state.threadListItem.title);
|
||||
|
||||
return (
|
||||
@@ -3197,7 +3199,7 @@ export const AssistantConversationSurface = ({
|
||||
onMinimize,
|
||||
onDismiss,
|
||||
}: AssistantConversationSurfaceProps) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const reducedMotion = useReducedMotion();
|
||||
const [questionPortalTarget, setQuestionPortalTarget] = useState<HTMLDivElement | null>(null);
|
||||
const [reasoningCollapsed, setReasoningCollapsed] = useState(false);
|
||||
@@ -3343,7 +3345,7 @@ export const AssistantPanel = ({
|
||||
onModelChange,
|
||||
onReasoningChange,
|
||||
}: AssistantPanelProps) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const aui = useAui();
|
||||
const previousFocusRef = useRef<HTMLElement | null>(null);
|
||||
const panelRef = useRef<HTMLDialogElement>(null);
|
||||
|
||||
@@ -30,7 +30,7 @@ import { createId } from "@homarr/common";
|
||||
import { assistantHomarrProviderTokenHeader, hotkeys } from "@homarr/definitions";
|
||||
import { showErrorNotification, showWarningNotification } from "@homarr/notifications";
|
||||
import { closeSpotlight } from "@homarr/spotlight/store";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import { openMediaRequestSearch, openSpotlight, useRegisterSpotlightContextResults } from "@homarr/spotlight";
|
||||
import { AssistantWidgetRendererProvider } from "@homarr/widgets";
|
||||
import { createWorkshopClient } from "~/components/workshop/workshop-client";
|
||||
@@ -135,7 +135,7 @@ const createAssistantAttachmentAdapter = (allowImages: boolean): AttachmentAdapt
|
||||
};
|
||||
|
||||
const AssistantPreferencesProvider = ({ children }: PropsWithChildren) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const { data, isLoading } = clientApi.assistant.getRuntimeOptions.useQuery(undefined, {
|
||||
staleTime: 10 * 60_000,
|
||||
});
|
||||
@@ -454,7 +454,7 @@ const createHistoryAdapter = (threadId: string | undefined): ThreadHistoryAdapte
|
||||
});
|
||||
|
||||
const AssistantThreadRuntime = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const aui = useAui();
|
||||
const localThreadId = useAuiState((state) => state.threadListItem.id);
|
||||
const threadId = useAuiState((state) => state.threadListItem.remoteId);
|
||||
@@ -652,7 +652,7 @@ const AssistantPreferenceSync = () => {
|
||||
};
|
||||
|
||||
const AssistantRuntimeEvents = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
useAuiEvent("composer.attachmentAddError", ({ message }) => {
|
||||
showErrorNotification({
|
||||
title: t("attachments.errorTitle"),
|
||||
@@ -679,7 +679,7 @@ const getNotificationKey = (message: ThreadMessage | undefined) => {
|
||||
};
|
||||
|
||||
const EnabledAssistantProvider = ({ children }: PropsWithChildren) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const [opened, setOpened] = useState(false);
|
||||
const [activityDismissed, setActivityDismissed] = useState(true);
|
||||
const [unreadCount, setUnreadCount] = useState(0);
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
} from "./assistant-runtime-provider";
|
||||
|
||||
vi.mock("@homarr/notifications", () => ({ showErrorNotification: vi.fn() }));
|
||||
vi.mock("@homarr/translation/client", () => ({ useScopedI18n: () => (key: string) => key }));
|
||||
vi.mock("@homarr/translation/client", () => ({ useI18n: () => (key: string) => key }));
|
||||
|
||||
(globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { AssistantRuntime, AttachmentAdapter, ThreadListRuntime, Toolkit }
|
||||
import { AssistantRuntimeProvider, INTERNAL, Tools, useAui, useAuiEvent } from "@assistant-ui/react";
|
||||
|
||||
import { showErrorNotification } from "@homarr/notifications";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
interface AssistantRuntimeProviderWithToolsProps extends PropsWithChildren {
|
||||
runtime: AssistantRuntime;
|
||||
@@ -437,7 +437,7 @@ const getClipboardAttachmentName = (file: File, index: number) => {
|
||||
};
|
||||
|
||||
const AssistantComposerSurfaceEvents = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
useAuiEvent("composer.attachmentAddError", ({ message }) => {
|
||||
showErrorNotification({ title: t("attachments.errorTitle"), message });
|
||||
});
|
||||
@@ -445,7 +445,7 @@ const AssistantComposerSurfaceEvents = () => {
|
||||
};
|
||||
|
||||
export const AssistantComposerSurfaceBoundary = ({ children, surfaceId }: PropsWithChildren<{ surfaceId: string }>) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const aui = useAui();
|
||||
const instanceId = useId();
|
||||
const resolvedSurfaceId = `${surfaceId}:${instanceId}`;
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
import { useMemo } from "react";
|
||||
|
||||
import { useRegisterSpotlightContextResults } from "@homarr/spotlight";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
/**
|
||||
* Keeps the assistant discoverable in the spotlight when it is unavailable, without loading the
|
||||
* assistant runtime. Lives apart from `assistant-provider` so the disabled path stays cheap.
|
||||
*/
|
||||
export const useRegisterAssistantSpotlightPlaceholder = (description: string) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
const spotlightItem = useMemo(
|
||||
() => ({
|
||||
id: "homarr-assistant",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { Group, Kbd, Stack, Text, ThemeIcon } from "@mantine/core";
|
||||
import { IconArrowUp, IconRobot } from "@tabler/icons-react";
|
||||
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
interface AssistantPromptInteractionOptions {
|
||||
sendPrompt: (prompt: string) => boolean;
|
||||
@@ -13,7 +13,7 @@ interface AssistantPromptInteractionOptions {
|
||||
}
|
||||
|
||||
const AssistantPromptDetail = () => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
return (
|
||||
<Group px="md" py="sm" wrap="nowrap">
|
||||
<ThemeIcon color="red" variant="light" radius="xl">
|
||||
@@ -30,7 +30,7 @@ const AssistantPromptDetail = () => {
|
||||
};
|
||||
|
||||
const AssistantPromptAction = ({ hasPrompt }: { hasPrompt: boolean }) => {
|
||||
const t = useScopedI18n("common.assistant");
|
||||
const t = useI18n("assistant");
|
||||
return (
|
||||
<Group w="100%" px="md" py="xs" justify="space-between" wrap="nowrap" opacity={hasPrompt ? 1 : 0.6}>
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
|
||||
@@ -7,11 +7,12 @@ import { IconAlertTriangle, IconCheck, IconSettings } from "@tabler/icons-react"
|
||||
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
import { useSession } from "@homarr/auth/client";
|
||||
import { getWidgetName } from "@homarr/definitions";
|
||||
import type { IntegrationKind } from "@homarr/definitions";
|
||||
import { useModalAction } from "@homarr/modals";
|
||||
import type { SettingsContextProps } from "@homarr/settings/creator";
|
||||
import { useSettings } from "@homarr/settings";
|
||||
import { useI18n, useScopedI18n } from "@homarr/translation/client";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import { reduceWidgetOptionsWithDefaultValues, widgetImports } from "@homarr/widgets";
|
||||
import type { IntegrationSelectOption } from "@homarr/widgets/widget-integration-select";
|
||||
import { WidgetEditModal } from "@homarr/widgets/modals";
|
||||
@@ -66,7 +67,8 @@ export const AssistantConfigureWidgetTool = ({
|
||||
status,
|
||||
toolCallId,
|
||||
}: ToolCallMessagePartProps<ConfigureWidgetArgs, ConfigureWidgetResult>) => {
|
||||
const t = useScopedI18n("common.assistant.configureWidget");
|
||||
const t = useI18n("assistant.configureWidget");
|
||||
const actionT = useI18n("common.action");
|
||||
const fullT = useI18n();
|
||||
const { data: session } = useSession();
|
||||
const settings = useSettings();
|
||||
@@ -116,7 +118,7 @@ export const AssistantConfigureWidgetTool = ({
|
||||
{cancelled ? t("cancelled") : t("ready")}
|
||||
</Text>
|
||||
<Text size="sm" fw={600} truncate>
|
||||
{args?.kind ? fullT(`widget.${args.kind}.name`) : t("title")}
|
||||
{args?.kind ? getWidgetName(args.kind, fullT) : t("title")}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -149,7 +151,7 @@ export const AssistantConfigureWidgetTool = ({
|
||||
<Stack gap="sm">
|
||||
<Text size="sm">{t("loadErrorDescription")}</Text>
|
||||
<Button variant="light" color="red" size="compact-sm" w="fit-content" onClick={() => integrations.refetch()}>
|
||||
{t("retry")}
|
||||
{actionT("tryAgain")}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Alert>
|
||||
@@ -174,7 +176,7 @@ export const AssistantConfigureWidgetTool = ({
|
||||
addResult({ boardId: args.boardId, kind: args.kind, options, integrationIds }),
|
||||
},
|
||||
{
|
||||
title: (titleT) => `${titleT("item.edit.title")} - ${titleT(`widget.${args.kind}.name`)}`,
|
||||
title: (titleT) => `${titleT("item.edit.title")} - ${getWidgetName(args.kind, titleT)}`,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -246,7 +248,7 @@ export const AssistantConfigureWidgetTool = ({
|
||||
<WidgetIcon size={20} />
|
||||
</ThemeIcon>
|
||||
<Box miw={0} flex={1}>
|
||||
<Text fw={700}>{fullT(`widget.${args.kind}.name`)}</Text>
|
||||
<Text fw={700}>{getWidgetName(args.kind, fullT)}</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
{args.summary}
|
||||
</Text>
|
||||
|
||||
Reference in new issue
Block a user