diff --git a/.roomodes b/.roomodes index c74aba7c788..8dc2492f641 100644 --- a/.roomodes +++ b/.roomodes @@ -22,7 +22,7 @@ "slug": "translate", "name": "Translate", "roleDefinition": "You are Roo, a linguistic specialist focused on translating and managing localization files. Your responsibility is to help maintain and update translation files for the application, ensuring consistency and accuracy across all language resources.", - "customInstructions": "When internationalizing and translating content:\n\n# Translation Style and Tone\n- Maintain a direct and concise style that mirrors the tone of the original text\n- Carefully account for colloquialisms and idiomatic expressions in both source and target languages\n- Aim for culturally relevant and meaningful translations rather than literal translations\n- Adapt the formality level to match the original content (whether formal or informal)\n- Preserve the personality and voice of the original content\n- Use natural-sounding language that feels native to speakers of the target language\n\n# Technical Implementation\n- Use namespaces to organize translations logically\n- Handle pluralization using i18next's built-in capabilities\n- Implement proper interpolation for variables using {{variable}} syntax\n- Don't include defaultValue. The `en` translations are the fallback.\n\n# Quality Assurance\n- Maintain consistent terminology across all translations\n- Respect the JSON structure of translation files\n- Watch for placeholders and preserve them in translations\n- Be mindful of text length in UI elements when translating to languages that might require more characters\n- Use context-aware translations when the same string has different meanings\n\n# Supported Languages\n- Localize all strings into the following locale files: ar, ca, cs, de, en, es, fr, hi, hu, it, ja, ko, pl, pt, pt-BR, ru, tr, zh-CN, zh-TW", + "customInstructions": "When internationalizing and translating content:\n\n# Translation Style and Tone\n- Maintain a direct and concise style that mirrors the tone of the original text\n- Carefully account for colloquialisms and idiomatic expressions in both source and target languages\n- Aim for culturally relevant and meaningful translations rather than literal translations\n- Adapt the formality level to match the original content (whether formal or informal)\n- Preserve the personality and voice of the original content\n- Use natural-sounding language that feels native to speakers of the target language\n- Don't translate the word \"token\" as it means something specific in English that all languages will understand\n\n# Technical Implementation\n- Use namespaces to organize translations logically\n- Handle pluralization using i18next's built-in capabilities\n- Implement proper interpolation for variables using {{variable}} syntax\n- Don't include defaultValue. The `en` translations are the fallback.\n\n# Quality Assurance\n- Maintain consistent terminology across all translations\n- Respect the JSON structure of translation files\n- Watch for placeholders and preserve them in translations\n- Be mindful of text length in UI elements when translating to languages that might require more characters\n- Use context-aware translations when the same string has different meanings\n\n# Supported Languages\n- Localize all strings into the following locale files: ar, ca, cs, de, en, es, fr, hi, hu, it, ja, ko, pl, pt, pt-BR, ru, tr, zh-CN, zh-TW", "groups": [ "read", [ diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index d0c33a1189d..d0569e6f916 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -940,12 +940,10 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie [], ) - const placeholderText = useMemo(() => { - const baseText = task ? t("chat:typeMessage") : t("chat:typeTask") - const contextText = t("chat:addContext") - const imageText = shouldDisableImages ? `, ${t("chat:dragFiles")}` : `, ${t("chat:dragFilesImages")}` - return baseText + `\n(${contextText}${imageText})` - }, [task, shouldDisableImages, t]) + const baseText = task ? t("chat:typeMessage") : t("chat:typeTask") + const placeholderText = + baseText + + `\n(${t("chat:addContext")}${shouldDisableImages ? `, ${t("chat:dragFiles")}` : `, ${t("chat:dragFilesImages")}`})` const itemContent = useCallback( (index: number, messageOrGroup: ClineMessage | ClineMessage[]) => { diff --git a/webview-ui/src/components/history/CopyButton.tsx b/webview-ui/src/components/history/CopyButton.tsx index 0e693b44703..17964cc37e7 100644 --- a/webview-ui/src/components/history/CopyButton.tsx +++ b/webview-ui/src/components/history/CopyButton.tsx @@ -3,6 +3,7 @@ import { useCallback } from "react" import { useClipboard } from "@/components/ui/hooks" import { Button } from "@/components/ui" import { cn } from "@/lib/utils" +import { useAppTranslation } from "@/i18n/TranslationContext" type CopyButtonProps = { itemTask: string @@ -10,6 +11,7 @@ type CopyButtonProps = { export const CopyButton = ({ itemTask }: CopyButtonProps) => { const { isCopied, copy } = useClipboard() + const { t } = useAppTranslation() const onCopy = useCallback( (e: React.MouseEvent) => { @@ -23,7 +25,7 @@ export const CopyButton = ({ itemTask }: CopyButtonProps) => { + diff --git a/webview-ui/src/components/history/ExportButton.tsx b/webview-ui/src/components/history/ExportButton.tsx index 6617e475bdd..14b312470b3 100644 --- a/webview-ui/src/components/history/ExportButton.tsx +++ b/webview-ui/src/components/history/ExportButton.tsx @@ -1,16 +1,21 @@ import { vscode } from "@/utils/vscode" import { Button } from "@/components/ui" +import { useAppTranslation } from "@/i18n/TranslationContext" -export const ExportButton = ({ itemId }: { itemId: string }) => ( - -) +export const ExportButton = ({ itemId }: { itemId: string }) => { + const { t } = useAppTranslation() + + return ( + + ) +} diff --git a/webview-ui/src/components/history/HistoryPreview.tsx b/webview-ui/src/components/history/HistoryPreview.tsx index f81d8ddacff..64af37ed64d 100644 --- a/webview-ui/src/components/history/HistoryPreview.tsx +++ b/webview-ui/src/components/history/HistoryPreview.tsx @@ -5,24 +5,25 @@ import { formatLargeNumber, formatDate } from "@/utils/format" import { Button } from "@/components/ui" import { useExtensionState } from "../../context/ExtensionStateContext" +import { useAppTranslation } from "../../i18n/TranslationContext" import { CopyButton } from "./CopyButton" type HistoryPreviewProps = { showHistoryView: () => void } - const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => { const { taskHistory } = useExtensionState() + const { t } = useAppTranslation() return (
- Recent Tasks + {t("history:recentTasks")}
{taskHistory.slice(0, 3).map((item) => ( @@ -50,22 +51,26 @@ const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => {
- Tokens: ↑{formatLargeNumber(item.tokensIn || 0)} ↓ - {formatLargeNumber(item.tokensOut || 0)} + {t("history:tokens", { + in: formatLargeNumber(item.tokensIn || 0), + out: formatLargeNumber(item.tokensOut || 0), + })} {!!item.cacheWrites && ( <> {" • "} - Cache: +{formatLargeNumber(item.cacheWrites || 0)} →{" "} - {formatLargeNumber(item.cacheReads || 0)} + {t("history:cache", { + writes: formatLargeNumber(item.cacheWrites || 0), + reads: formatLargeNumber(item.cacheReads || 0), + })} )} {!!item.totalCost && ( <> {" • "} - API Cost: ${item.totalCost?.toFixed(4)} + {t("history:apiCost", { cost: item.totalCost?.toFixed(4) })} )}
diff --git a/webview-ui/src/components/history/HistoryView.tsx b/webview-ui/src/components/history/HistoryView.tsx index ec44f8eaca9..c82fd0b92a3 100644 --- a/webview-ui/src/components/history/HistoryView.tsx +++ b/webview-ui/src/components/history/HistoryView.tsx @@ -8,6 +8,7 @@ import { vscode } from "@/utils/vscode" import { formatLargeNumber, formatDate } from "@/utils/format" import { cn } from "@/lib/utils" import { Button } from "@/components/ui" +import { useAppTranslation } from "@/i18n/TranslationContext" import { Tab, TabContent, TabHeader } from "../common/Tab" import { useTaskSearch } from "./useTaskSearch" @@ -22,6 +23,7 @@ type SortOption = "newest" | "oldest" | "mostExpensive" | "mostTokens" | "mostRe const HistoryView = ({ onDone }: HistoryViewProps) => { const { tasks, searchQuery, setSearchQuery, sortOption, setSortOption, setLastNonRelevantSort } = useTaskSearch() + const { t } = useAppTranslation() const [deleteTaskId, setDeleteTaskId] = useState(null) @@ -29,13 +31,13 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
-

History

- Done +

{t("history:history")}

+ {t("history:done")}
{ const newValue = (e.target as HTMLInputElement)?.value @@ -70,15 +72,15 @@ const HistoryView = ({ onDone }: HistoryViewProps) => { value={sortOption} role="radiogroup" onChange={(e) => setSortOption((e.target as HTMLInputElement).value as SortOption)}> - Newest - Oldest - Most Expensive - Most Tokens + {t("history:newest")} + {t("history:oldest")} + {t("history:mostExpensive")} + {t("history:mostTokens")} - Most Relevant + {t("history:mostRelevant")}
@@ -132,7 +134,7 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {