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,6 +1,7 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import type { TextInput } from "react-native";
|
||||
import { router, usePathname, type Href } from "expo-router";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useKeyboardShortcutsStore } from "@/stores/keyboard-shortcuts-store";
|
||||
import { keyboardActionDispatcher } from "@/keyboard/keyboard-action-dispatcher";
|
||||
import { useAllAgentsList } from "@/hooks/use-all-agents-list";
|
||||
@@ -52,7 +53,10 @@ function sortAgents(left: AggregatedAgent, right: AggregatedAgent): number {
|
||||
|
||||
interface CommandCenterActionDefinition {
|
||||
id: string;
|
||||
title: string;
|
||||
titleKey:
|
||||
| "shell.commandCenter.openProject"
|
||||
| "shell.commandCenter.home"
|
||||
| "sidebar.actions.settings";
|
||||
icon?: "plus" | "settings" | "home";
|
||||
actionId?: string;
|
||||
keywords: string[];
|
||||
@@ -62,7 +66,7 @@ interface CommandCenterActionDefinition {
|
||||
const COMMAND_CENTER_ACTIONS: readonly CommandCenterActionDefinition[] = [
|
||||
{
|
||||
id: "new-agent",
|
||||
title: "Open project",
|
||||
titleKey: "shell.commandCenter.openProject",
|
||||
icon: "plus",
|
||||
actionId: "new-agent",
|
||||
keywords: ["open", "project", "folder", "workspace", "repo"],
|
||||
@@ -70,24 +74,28 @@ const COMMAND_CENTER_ACTIONS: readonly CommandCenterActionDefinition[] = [
|
||||
},
|
||||
{
|
||||
id: "home",
|
||||
title: "Home",
|
||||
titleKey: "shell.commandCenter.home",
|
||||
icon: "home",
|
||||
keywords: ["home", "start", "import", "session", "pair", "device", "providers"],
|
||||
routeKind: "home",
|
||||
},
|
||||
{
|
||||
id: "settings",
|
||||
title: "Settings",
|
||||
titleKey: "sidebar.actions.settings",
|
||||
icon: "settings",
|
||||
keywords: ["settings", "preferences", "config", "configuration"],
|
||||
routeKind: "settings",
|
||||
},
|
||||
];
|
||||
|
||||
function matchesActionQuery(query: string, action: CommandCenterActionDefinition): boolean {
|
||||
function matchesActionQuery(
|
||||
query: string,
|
||||
action: CommandCenterActionDefinition,
|
||||
title: string,
|
||||
): boolean {
|
||||
const normalized = query.trim().toLowerCase();
|
||||
if (!normalized) return true;
|
||||
if (action.title.toLowerCase().includes(normalized)) {
|
||||
if (title.toLowerCase().includes(normalized)) {
|
||||
return true;
|
||||
}
|
||||
return action.keywords.some((keyword) => keyword.includes(normalized));
|
||||
@@ -129,6 +137,7 @@ function resolveActionShortcutKeys(
|
||||
}
|
||||
|
||||
export function useCommandCenter() {
|
||||
const { t } = useTranslation();
|
||||
const pathname = usePathname();
|
||||
const routeActiveServerId = useActiveServerId();
|
||||
const { overrides } = useKeyboardShortcutOverrides();
|
||||
@@ -174,7 +183,7 @@ export function useCommandCenter() {
|
||||
}
|
||||
return COMMAND_CENTER_ACTIONS.filter((action) => {
|
||||
if (action.routeKind === "home" && !homeRoute) return false;
|
||||
return matchesActionQuery(query, action);
|
||||
return matchesActionQuery(query, action, t(action.titleKey));
|
||||
}).map<CommandCenterActionItem>((action) => {
|
||||
let route: Href | undefined;
|
||||
if (action.routeKind === "settings") route = settingsRoute;
|
||||
@@ -182,13 +191,13 @@ export function useCommandCenter() {
|
||||
return {
|
||||
kind: "action",
|
||||
id: action.id,
|
||||
title: action.title,
|
||||
title: t(action.titleKey),
|
||||
icon: action.icon,
|
||||
route,
|
||||
shortcutKeys: resolveActionShortcutKeys(action.actionId, overrides),
|
||||
};
|
||||
});
|
||||
}, [open, query, settingsRoute, homeRoute, overrides]);
|
||||
}, [open, query, settingsRoute, homeRoute, overrides, t]);
|
||||
|
||||
const items = useMemo(() => {
|
||||
if (!open) {
|
||||
|
||||
Reference in New Issue
Block a user