Complete client UI i18n migration
Adds client-side i18n support, language settings, translated UI copy, and locale parity coverage.
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { keepPreviousData, useQuery } from "@tanstack/react-query";
|
||||
import type { TFunction } from "i18next";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { AutocompleteOption } from "@/components/ui/autocomplete";
|
||||
import {
|
||||
useAgentCommandsQuery,
|
||||
@@ -115,13 +117,14 @@ function mapDirectorySuggestionsToEntries(payload: {
|
||||
}));
|
||||
}
|
||||
|
||||
function mapCommandToOption(entry: AvailableCommand): AgentAutocompleteOption {
|
||||
function mapCommandToOption(entry: AvailableCommand, t: TFunction): AgentAutocompleteOption {
|
||||
const command = entry.command;
|
||||
const base = {
|
||||
id: command.name,
|
||||
label: `/${command.name}`,
|
||||
detail: command.argumentHint || undefined,
|
||||
description: command.description,
|
||||
description:
|
||||
entry.source === "client" ? t(entry.command.descriptionKey) : entry.command.description,
|
||||
kind: "command" as const,
|
||||
};
|
||||
if (entry.source === "client") {
|
||||
@@ -148,6 +151,7 @@ interface BuildAutocompleteOptionsInput {
|
||||
activeSlashCommand: SlashCommandRange | null;
|
||||
activeFileMention: FileMentionRange | null;
|
||||
fileSuggestions: DirectorySuggestionEntry[];
|
||||
t: TFunction;
|
||||
}
|
||||
|
||||
function buildCommandAutocompleteOptions(input: BuildAutocompleteOptionsInput) {
|
||||
@@ -177,7 +181,7 @@ function buildCommandAutocompleteOptions(input: BuildAutocompleteOptionsInput) {
|
||||
input.commandFilterQuery,
|
||||
);
|
||||
const orderedMatches = orderAutocompleteOptions(matches);
|
||||
return orderedMatches.map(mapCommandToOption);
|
||||
return orderedMatches.map((entry) => mapCommandToOption(entry, input.t));
|
||||
}
|
||||
|
||||
const activeFileMention = input.activeFileMention;
|
||||
@@ -258,9 +262,12 @@ function resolveAutocompleteErrorMessage(args: {
|
||||
isCommandError: boolean;
|
||||
commandError: Error | null;
|
||||
fileSuggestionsError: unknown;
|
||||
t: TFunction;
|
||||
}): string | undefined {
|
||||
if (args.mode === "command") {
|
||||
return args.isCommandError ? (args.commandError?.message ?? "Failed to load") : undefined;
|
||||
return args.isCommandError
|
||||
? (args.commandError?.message ?? args.t("agentAutocomplete.failedToLoad"))
|
||||
: undefined;
|
||||
}
|
||||
if (args.mode === "file") {
|
||||
return args.fileSuggestionsError instanceof Error
|
||||
@@ -271,6 +278,7 @@ function resolveAutocompleteErrorMessage(args: {
|
||||
}
|
||||
|
||||
export function useAgentAutocomplete(input: UseAgentAutocompleteInput): AgentAutocompleteResult {
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
userInput,
|
||||
cursorIndex,
|
||||
@@ -366,7 +374,7 @@ export function useAgentAutocomplete(input: UseAgentAutocompleteInput): AgentAut
|
||||
],
|
||||
queryFn: async (): Promise<DirectorySuggestionEntry[]> => {
|
||||
if (!client) {
|
||||
throw new Error("Daemon client unavailable");
|
||||
throw new Error(t("common.errors.daemonClientUnavailable"));
|
||||
}
|
||||
const response = await client.getDirectorySuggestions({
|
||||
cwd: autocompleteCwd,
|
||||
@@ -402,6 +410,7 @@ export function useAgentAutocomplete(input: UseAgentAutocompleteInput): AgentAut
|
||||
isDraftContext,
|
||||
isVisible,
|
||||
mode,
|
||||
t,
|
||||
}),
|
||||
[
|
||||
activeFileMention,
|
||||
@@ -412,6 +421,7 @@ export function useAgentAutocomplete(input: UseAgentAutocompleteInput): AgentAut
|
||||
isDraftContext,
|
||||
isVisible,
|
||||
mode,
|
||||
t,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -488,10 +498,15 @@ export function useAgentAutocomplete(input: UseAgentAutocompleteInput): AgentAut
|
||||
isCommandError: isError,
|
||||
commandError: error,
|
||||
fileSuggestionsError: fileSuggestionsQuery.error,
|
||||
t,
|
||||
});
|
||||
|
||||
const loadingText = mode === "file" ? "Searching workspace..." : "Loading commands...";
|
||||
const emptyText = mode === "file" ? "No files or directories found" : "No commands found";
|
||||
const loadingText =
|
||||
mode === "file"
|
||||
? t("agentAutocomplete.searchingWorkspace")
|
||||
: t("agentAutocomplete.loadingCommands");
|
||||
const emptyText =
|
||||
mode === "file" ? t("agentAutocomplete.noFiles") : t("agentAutocomplete.noCommands");
|
||||
|
||||
return {
|
||||
isVisible,
|
||||
|
||||
Reference in New Issue
Block a user