Complete client UI i18n migration
Adds client-side i18n support, language settings, translated UI copy, and locale parity coverage.
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
type ReactNode,
|
||||
type RefObject,
|
||||
} from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
@@ -56,7 +57,7 @@ import type { AgentProviderDefinition } from "@getpaseo/protocol/provider-manife
|
||||
import {
|
||||
getFeatureHighlightColor,
|
||||
getFeatureTooltip,
|
||||
getAgentControlHint,
|
||||
getAgentControlHintKey,
|
||||
formatThinkingOptionLabel,
|
||||
resolveAgentModelSelection,
|
||||
} from "@/composer/agent-controls/utils";
|
||||
@@ -415,6 +416,7 @@ function ControlledAgentControls({
|
||||
isCompactLayout,
|
||||
}: ControlledAgentControlsProps) {
|
||||
const { theme } = useUnistyles();
|
||||
const { t } = useTranslation();
|
||||
const isCompactFormFactor = useIsCompactFormFactor();
|
||||
const isCompact = isCompactLayout ?? isCompactFormFactor;
|
||||
const [activeSheet, setActiveSheet] = useState<ActiveSheet>(null);
|
||||
@@ -432,7 +434,11 @@ function ControlledAgentControls({
|
||||
onSelectThinkingOption && thinkingOptions && thinkingOptions.length > 0,
|
||||
);
|
||||
|
||||
const displayProvider = findOptionLabel(providerOptions, selectedProviderId, "Provider");
|
||||
const displayProvider = findOptionLabel(
|
||||
providerOptions,
|
||||
selectedProviderId,
|
||||
t("agentControls.provider.fallback"),
|
||||
);
|
||||
const formattedThinkingOptions = useMemo(
|
||||
() => toThinkingControlOptions(thinkingOptions),
|
||||
[thinkingOptions],
|
||||
@@ -440,7 +446,7 @@ function ControlledAgentControls({
|
||||
const displayThinking = findOptionLabel(
|
||||
formattedThinkingOptions,
|
||||
selectedThinkingOptionId,
|
||||
formattedThinkingOptions[0]?.label ?? "Unknown",
|
||||
formattedThinkingOptions[0]?.label ?? t("agentControls.thinking.unknown"),
|
||||
);
|
||||
|
||||
const ProviderIcon = resolveProviderIcon(provider);
|
||||
@@ -709,6 +715,7 @@ const DESKTOP_SEARCH_THRESHOLD = 6;
|
||||
|
||||
function DesktopAgentControlsContent(props: DesktopAgentControlsContentProps) {
|
||||
const { theme } = useUnistyles();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
provider,
|
||||
providerOptions,
|
||||
@@ -764,7 +771,7 @@ function DesktopAgentControlsContent(props: DesktopAgentControlsContentProps) {
|
||||
onPress={handleProviderPress}
|
||||
style={providerPressableStyle}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Select agent provider"
|
||||
accessibilityLabel={t("agentControls.provider.select")}
|
||||
testID="agent-provider-selector"
|
||||
>
|
||||
<Text style={styles.modeBadgeText}>{displayProvider}</Text>
|
||||
@@ -805,7 +812,7 @@ function DesktopAgentControlsContent(props: DesktopAgentControlsContentProps) {
|
||||
</View>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top" align="center" offset={8}>
|
||||
<Text style={styles.tooltipText}>{getAgentControlHint("model")}</Text>
|
||||
<Text style={styles.tooltipText}>{t(getAgentControlHintKey("model"))}</Text>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
@@ -821,7 +828,9 @@ function DesktopAgentControlsContent(props: DesktopAgentControlsContentProps) {
|
||||
onPress={handleThinkingPress}
|
||||
style={thinkingPressableStyle}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={`Select thinking option (${displayThinking})`}
|
||||
accessibilityLabel={t("agentControls.thinking.selectWithValue", {
|
||||
value: displayThinking,
|
||||
})}
|
||||
testID="agent-thinking-selector"
|
||||
>
|
||||
<Brain size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
|
||||
@@ -830,7 +839,7 @@ function DesktopAgentControlsContent(props: DesktopAgentControlsContentProps) {
|
||||
</Pressable>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top" align="center" offset={8}>
|
||||
<Text style={styles.tooltipText}>{getAgentControlHint("thinking")}</Text>
|
||||
<Text style={styles.tooltipText}>{t(getAgentControlHintKey("thinking"))}</Text>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Combobox
|
||||
@@ -901,6 +910,7 @@ interface SheetAgentControlsContentProps {
|
||||
|
||||
function SheetAgentControlsContent(props: SheetAgentControlsContentProps) {
|
||||
const { theme } = useUnistyles();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
provider,
|
||||
selectedModelId,
|
||||
@@ -936,6 +946,10 @@ function SheetAgentControlsContent(props: SheetAgentControlsContentProps) {
|
||||
|
||||
const hasThinking = comboboxThinkingOptions.length > 0;
|
||||
const hasFeatures = Boolean(features && features.length > 0);
|
||||
const featuresSheetHeader = useMemo<SheetHeader>(
|
||||
() => ({ title: t("agentControls.features.title") }),
|
||||
[t],
|
||||
);
|
||||
|
||||
const handleOpenThinking = useCallback(() => handleOpenSheet("thinking"), [handleOpenSheet]);
|
||||
const handleOpenFeatures = useCallback(() => handleOpenSheet("features"), [handleOpenSheet]);
|
||||
@@ -1012,7 +1026,7 @@ function SheetAgentControlsContent(props: SheetAgentControlsContentProps) {
|
||||
disabled={disabled || !canSelectThinking}
|
||||
style={thinkingButtonStyle}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Select thinking option"
|
||||
accessibilityLabel={t("agentControls.thinking.select")}
|
||||
testID="agent-controls-thinking"
|
||||
>
|
||||
<Brain size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
|
||||
@@ -1025,7 +1039,7 @@ function SheetAgentControlsContent(props: SheetAgentControlsContentProps) {
|
||||
disabled={disabled}
|
||||
style={featuresButtonStyle}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Open agent features"
|
||||
accessibilityLabel={t("agentControls.features.open")}
|
||||
testID="agent-controls-features"
|
||||
>
|
||||
<Settings2 size={theme.iconSize.md} color={theme.colors.foregroundMuted} />
|
||||
@@ -1038,7 +1052,7 @@ function SheetAgentControlsContent(props: SheetAgentControlsContentProps) {
|
||||
value={selectedThinkingOptionId ?? ""}
|
||||
onSelect={handleSelectThinkingAndClose}
|
||||
searchable={false}
|
||||
title="Thinking"
|
||||
title={t("agentControls.thinking.title")}
|
||||
open={activeSheet === "thinking"}
|
||||
onOpenChange={handleThinkingSheetOpenChange}
|
||||
anchorRef={thinkingAnchorRef}
|
||||
@@ -1047,7 +1061,7 @@ function SheetAgentControlsContent(props: SheetAgentControlsContentProps) {
|
||||
) : null}
|
||||
|
||||
<AdaptiveModalSheet
|
||||
header={FEATURES_SHEET_HEADER}
|
||||
header={featuresSheetHeader}
|
||||
visible={activeSheet === "features"}
|
||||
onClose={handleCloseSheet}
|
||||
testID="agent-features-sheet"
|
||||
@@ -1206,6 +1220,7 @@ function SheetFeatureItem({
|
||||
onSetFeature?: (featureId: string, value: unknown) => void;
|
||||
}) {
|
||||
const { theme } = useUnistyles();
|
||||
const { t } = useTranslation();
|
||||
const featureSelector: AgentControlSelector = `feature-${feature.id}`;
|
||||
|
||||
const handleFeatureOpenChange = useMemo(
|
||||
@@ -1257,7 +1272,9 @@ function SheetFeatureItem({
|
||||
)}
|
||||
/>
|
||||
<Text style={styles.sheetSelectText}>{feature.label}</Text>
|
||||
<Text style={styles.modeBadgeText}>{feature.value ? "On" : "Off"}</Text>
|
||||
<Text style={styles.modeBadgeText}>
|
||||
{feature.value ? t("agentControls.features.on") : t("agentControls.features.off")}
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
@@ -1344,8 +1361,6 @@ function ThinkingComboboxOption({
|
||||
);
|
||||
}
|
||||
|
||||
const FEATURES_SHEET_HEADER: SheetHeader = { title: "Features" };
|
||||
|
||||
export const AgentControls = memo(function AgentControls({
|
||||
agentId,
|
||||
serverId,
|
||||
|
||||
Reference in New Issue
Block a user