Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,10 @@
import { describe, it, expect } from "bun:test"
import { Project, SyntaxKind, Node } from "ts-morph"
import path from "node:path"
import { globSync } from "glob"

const ROOT = path.resolve(import.meta.dir, "../..")
const TSX_FILES = [
path.join(ROOT, "webview-ui/agent-manager/AgentManagerApp.tsx"),
path.join(ROOT, "webview-ui/agent-manager/sortable-tab.tsx"),
]
const TSX_FILES = globSync("webview-ui/**/*.tsx", { cwd: ROOT, absolute: true })

/**
* Props whose string values are user-visible and must be localized.
Expand Down Expand Up @@ -321,10 +319,10 @@ function findTranslationShadowViolations(): ShadowViolation[] {
return results
}

describe("Agent Manager i18n — no hardcoded strings", () => {
describe("Webview i18n — no hardcoded strings", () => {
const violations = findViolations()

it("should have no hardcoded user-facing strings in agent manager TSX files", () => {
it("should have no hardcoded user-facing strings in webview TSX files", () => {
if (violations.length > 0) {
const report = violations.map((v) => ` ${v.file}:${v.line} [${v.context}] "${v.text}"`).join("\n")
expect(violations, `Found ${violations.length} hardcoded string(s):\n${report}`).toEqual([])
Expand All @@ -333,7 +331,7 @@ describe("Agent Manager i18n — no hardcoded strings", () => {
})
})

describe("Agent Manager i18n — no t() shadowing", () => {
describe("Webview i18n — no t() shadowing", () => {
const shadows = findTranslationShadowViolations()

it("should not shadow the t() translation function in callbacks", () => {
Expand Down
5 changes: 3 additions & 2 deletions packages/kilo-vscode/webview-ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { ServerProvider, useServer } from "./context/server"
import { ProviderProvider, useProvider } from "./context/provider"
import { ConfigProvider } from "./context/config"
import { SessionProvider, useSession } from "./context/session"
import { LanguageProvider } from "./context/language"
import { LanguageProvider, useLanguage } from "./context/language"
import { ChatView } from "./components/chat"
import { KiloNotifications } from "./components/chat/KiloNotifications"
import SessionList from "./components/history/SessionList"
Expand Down Expand Up @@ -128,6 +128,7 @@ const AppContent: Component = () => {
const [currentView, setCurrentView] = createSignal<ViewType>("newTask")
const session = useSession()
const server = useServer()
const language = useLanguage()

const handleViewAction = (action: string) => {
switch (action) {
Expand Down Expand Up @@ -189,7 +190,7 @@ const AppContent: Component = () => {
<ChatView onSelectSession={handleSelectSession} />
</Match>
<Match when={currentView() === "marketplace"}>
<DummyView title="Marketplace" />
<DummyView title={language.t("nav.marketplace")} />
</Match>
<Match when={currentView() === "history"}>
<SessionList onSelectSession={handleSelectSession} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ const ProfileView: Component<ProfileViewProps> = (props) => {
margin: "0 0 8px 0",
}}
>
Account
{language.t("profile.account")}
</p>
<Select
options={orgOptions()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { IconButton } from "@kilocode/kilo-ui/icon-button"
import { Icon } from "@kilocode/kilo-ui/icon"
import { useNotifications } from "../../context/notifications"
import { useVSCode } from "../../context/vscode"
import { useLanguage } from "../../context/language"

export const KiloNotifications: Component = () => {
const { filteredNotifications, dismiss } = useNotifications()
const vscode = useVSCode()
const language = useLanguage()
const [index, setIndex] = createSignal(0)

const items = filteredNotifications
Expand Down Expand Up @@ -35,20 +37,24 @@ export const KiloNotifications: Component = () => {
<div class="kilo-notifications-card">
<div class="kilo-notifications-header">
<span class="kilo-notifications-title">{current()?.title}</span>
<IconButton size="small" variant="ghost" icon="close" onClick={handleDismiss} title="Dismiss" />
<IconButton
size="small"
variant="ghost"
icon="close"
onClick={handleDismiss}
title={language.t("notifications.dismiss")}
/>
</div>
<p class="kilo-notifications-message">{current()?.message}</p>
<div class="kilo-notifications-footer">
<Show when={total() > 1}>
<div class="kilo-notifications-nav">
<button class="kilo-notifications-nav-btn" onClick={prev} title="Previous">
<Icon name="arrow-left" size="small" />
<button class="kilo-notifications-nav-btn" onClick={prev} title={language.t("notifications.previous")}> <Icon name="arrow-left" size="small" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Formatting issue — the <Icon> component is on the same line as the button's closing >, with excessive whitespace. This appears to be a merge artifact where the line break was lost. The same issue occurs on line 57.

Suggested change
<button class="kilo-notifications-nav-btn" onClick={prev} title={language.t("notifications.previous")}> <Icon name="arrow-left" size="small" />
<button class="kilo-notifications-nav-btn" onClick={prev} title={language.t("notifications.previous")}>

</button>
<span class="kilo-notifications-nav-count">
{safeIndex() + 1} / {total()}
</span>
<button class="kilo-notifications-nav-btn" onClick={next} title="Next">
<Icon name="arrow-right" size="small" />
<button class="kilo-notifications-nav-btn" onClick={next} title={language.t("notifications.next")}> <Icon name="arrow-right" size="small" />
</button>
</div>
</Show>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ export const PromptInput: Component = () => {
<div class="file-mention-dropdown" ref={dropdownRef}>
<Show
when={mention.mentionResults().length > 0}
fallback={<div class="file-mention-empty">No files found</div>}
fallback={<div class="file-mention-empty">{language.t("prompt.fileMention.empty")}</div>}
>
<For each={mention.mentionResults()}>
{(path, index) => (
Expand Down Expand Up @@ -283,7 +283,7 @@ export const PromptInput: Component = () => {
type="button"
class="image-attachment-remove"
onClick={() => imageAttach.remove(img.id)}
aria-label="Remove image"
aria-label={language.t("prompt.image.remove")}
>
×
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ const AgentBehaviourTab: Component = () => {
>
<TextField
value={currentAgentConfig().model ?? ""}
placeholder="e.g. anthropic/claude-sonnet-4-20250514"
placeholder={language.t("settings.agentBehaviour.modelOverride.placeholder")}
onChange={(val) =>
updateAgentConfig(selectedAgent(), {
model: val.trim() || undefined,
Expand All @@ -221,7 +221,7 @@ const AgentBehaviourTab: Component = () => {
>
<TextField
value={currentAgentConfig().prompt ?? ""}
placeholder="Custom instructions…"
placeholder={language.t("settings.agentBehaviour.prompt.placeholder")}
multiline
onChange={(val) =>
updateAgentConfig(selectedAgent(), {
Expand Down Expand Up @@ -321,11 +321,11 @@ const AgentBehaviourTab: Component = () => {
>
<Show when={mcp.command}>
<div>
command: {mcp.command} {(mcp.args ?? []).join(" ")}
{language.t("settings.agentBehaviour.mcpCommandLabel")}: {mcp.command} {(mcp.args ?? []).join(" ")}
</div>
</Show>
<Show when={mcp.url}>
<div>url: {mcp.url}</div>
<div>{language.t("settings.agentBehaviour.mcpUrlLabel")}: {mcp.url}</div>
</Show>
</div>
</div>
Expand Down Expand Up @@ -354,7 +354,7 @@ const AgentBehaviourTab: Component = () => {
<div style={{ flex: 1 }}>
<TextField
value={newSkillPath()}
placeholder="e.g. ./skills"
placeholder={language.t("settings.agentBehaviour.skillPaths.placeholder")}
onChange={(val) => setNewSkillPath(val)}
onKeyDown={(e: KeyboardEvent) => {
if (e.key === "Enter") addSkillPath()
Expand Down Expand Up @@ -405,7 +405,7 @@ const AgentBehaviourTab: Component = () => {
<div style={{ flex: 1 }}>
<TextField
value={newSkillUrl()}
placeholder="e.g. https://example.com/skills"
placeholder={language.t("settings.agentBehaviour.skillUrls.placeholder")}
onChange={(val) => setNewSkillUrl(val)}
onKeyDown={(e: KeyboardEvent) => {
if (e.key === "Enter") addSkillUrl()
Expand Down Expand Up @@ -477,7 +477,7 @@ const AgentBehaviourTab: Component = () => {
<div style={{ flex: 1 }}>
<TextField
value={newInstruction()}
placeholder="e.g. ./INSTRUCTIONS.md"
placeholder={language.t("settings.agentBehaviour.instructionFiles.placeholder")}
onChange={(val) => setNewInstruction(val)}
onKeyDown={(e: KeyboardEvent) => {
if (e.key === "Enter") addInstruction()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ const ContextTab: Component = () => {
<div style={{ flex: 1 }}>
<TextField
value={newPattern()}
placeholder="e.g. **/node_modules/**"
placeholder={language.t("settings.context.watcherPatterns.placeholder")}
onChange={(val) => setNewPattern(val)}
onKeyDown={(e: KeyboardEvent) => {
if (e.key === "Enter") addPattern()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const DisplayTab: Component = () => {
<div style={{ width: "160px" }}>
<TextField
value={config().username ?? ""}
placeholder="User"
placeholder={language.t("settings.display.username.placeholder")}
onChange={(val) => updateConfig({ username: val.trim() || undefined })}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ const ProvidersTab: Component = () => {
variant="secondary"
size="small"
triggerVariant="settings"
placeholder="Select provider…"
placeholder={language.t("settings.providers.selectProvider")}
/>
</div>
<Button
Expand Down Expand Up @@ -202,7 +202,7 @@ const ProvidersTab: Component = () => {
variant="secondary"
size="small"
triggerVariant="settings"
placeholder="Select provider…"
placeholder={language.t("settings.providers.selectProvider")}
/>
</div>
<Button
Expand Down
18 changes: 18 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1017,4 +1017,22 @@ export const dict = {
"agentManager.import.noBranchesFound": "لم يتم العثور على فروع.",
"agentManager.import.noBranchesHint": "الصق رابط PR أعلاه أو أنشئ Worktree جديدًا.",
"agentManager.import.failed": "فشل الاستيراد",
"notifications.dismiss": "Dismiss",
"notifications.previous": "Previous",
"notifications.next": "Next",
"notifications.empty": "No notifications",
"prompt.fileMention.empty": "No files found",
"prompt.image.remove": "Remove image",
"settings.providers.selectProvider": "Select provider…",
"settings.display.username.placeholder": "User",
"settings.context.watcherPatterns.placeholder": "e.g. **/node_modules/**",
"profile.account": "Account",
"nav.marketplace": "Marketplace",
"settings.agentBehaviour.modelOverride.placeholder": "e.g. anthropic/claude-sonnet-4-20250514",
"settings.agentBehaviour.prompt.placeholder": "Custom instructions…",
"settings.agentBehaviour.mcpCommandLabel": "command",
"settings.agentBehaviour.mcpUrlLabel": "url",
"settings.agentBehaviour.skillPaths.placeholder": "e.g. ./skills",
"settings.agentBehaviour.skillUrls.placeholder": "e.g. https://example.com/skills",
"settings.agentBehaviour.instructionFiles.placeholder": "e.g. ./INSTRUCTIONS.md",
}
18 changes: 18 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/br.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1031,4 +1031,22 @@ export const dict = {
"agentManager.import.noBranchesFound": "Nenhum branch encontrado.",
"agentManager.import.noBranchesHint": "Cole uma URL de PR acima ou crie um novo Worktree.",
"agentManager.import.failed": "Falha na importação",
"notifications.dismiss": "Dismiss",
"notifications.previous": "Previous",
"notifications.next": "Next",
"notifications.empty": "No notifications",
"prompt.fileMention.empty": "No files found",
"prompt.image.remove": "Remove image",
"settings.providers.selectProvider": "Select provider…",
"settings.display.username.placeholder": "User",
"settings.context.watcherPatterns.placeholder": "e.g. **/node_modules/**",
"profile.account": "Account",
"nav.marketplace": "Marketplace",
"settings.agentBehaviour.modelOverride.placeholder": "e.g. anthropic/claude-sonnet-4-20250514",
"settings.agentBehaviour.prompt.placeholder": "Custom instructions…",
"settings.agentBehaviour.mcpCommandLabel": "command",
"settings.agentBehaviour.mcpUrlLabel": "url",
"settings.agentBehaviour.skillPaths.placeholder": "e.g. ./skills",
"settings.agentBehaviour.skillUrls.placeholder": "e.g. https://example.com/skills",
"settings.agentBehaviour.instructionFiles.placeholder": "e.g. ./INSTRUCTIONS.md",
}
18 changes: 18 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/bs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1053,4 +1053,22 @@ export const dict = {
"agentManager.import.noBranchesFound": "Nisu pronađeni branchevi.",
"agentManager.import.noBranchesHint": "Zalijepite PR URL iznad ili kreirajte novi Worktree.",
"agentManager.import.failed": "Uvoz neuspješan",
"notifications.dismiss": "Dismiss",
"notifications.previous": "Previous",
"notifications.next": "Next",
"notifications.empty": "No notifications",
"prompt.fileMention.empty": "No files found",
"prompt.image.remove": "Remove image",
"settings.providers.selectProvider": "Select provider…",
"settings.display.username.placeholder": "User",
"settings.context.watcherPatterns.placeholder": "e.g. **/node_modules/**",
"profile.account": "Account",
"nav.marketplace": "Marketplace",
"settings.agentBehaviour.modelOverride.placeholder": "e.g. anthropic/claude-sonnet-4-20250514",
"settings.agentBehaviour.prompt.placeholder": "Custom instructions…",
"settings.agentBehaviour.mcpCommandLabel": "command",
"settings.agentBehaviour.mcpUrlLabel": "url",
"settings.agentBehaviour.skillPaths.placeholder": "e.g. ./skills",
"settings.agentBehaviour.skillUrls.placeholder": "e.g. https://example.com/skills",
"settings.agentBehaviour.instructionFiles.placeholder": "e.g. ./INSTRUCTIONS.md",
}
18 changes: 18 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/da.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1026,4 +1026,22 @@ export const dict = {
"agentManager.import.noBranchesFound": "Ingen branches fundet.",
"agentManager.import.noBranchesHint": "Indsæt en PR URL ovenfor eller opret et nyt Worktree.",
"agentManager.import.failed": "Import mislykkedes",
"notifications.dismiss": "Dismiss",
"notifications.previous": "Previous",
"notifications.next": "Next",
"notifications.empty": "No notifications",
"prompt.fileMention.empty": "No files found",
"prompt.image.remove": "Remove image",
"settings.providers.selectProvider": "Select provider…",
"settings.display.username.placeholder": "User",
"settings.context.watcherPatterns.placeholder": "e.g. **/node_modules/**",
"profile.account": "Account",
"nav.marketplace": "Marketplace",
"settings.agentBehaviour.modelOverride.placeholder": "e.g. anthropic/claude-sonnet-4-20250514",
"settings.agentBehaviour.prompt.placeholder": "Custom instructions…",
"settings.agentBehaviour.mcpCommandLabel": "command",
"settings.agentBehaviour.mcpUrlLabel": "url",
"settings.agentBehaviour.skillPaths.placeholder": "e.g. ./skills",
"settings.agentBehaviour.skillUrls.placeholder": "e.g. https://example.com/skills",
"settings.agentBehaviour.instructionFiles.placeholder": "e.g. ./INSTRUCTIONS.md",
}
18 changes: 18 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1040,4 +1040,22 @@ export const dict = {
"agentManager.import.noBranchesFound": "Keine Branches gefunden.",
"agentManager.import.noBranchesHint": "Fügen Sie oben eine PR-URL ein oder erstellen Sie einen neuen Worktree.",
"agentManager.import.failed": "Import fehlgeschlagen",
"notifications.dismiss": "Dismiss",
"notifications.previous": "Previous",
"notifications.next": "Next",
"notifications.empty": "No notifications",
"prompt.fileMention.empty": "No files found",
"prompt.image.remove": "Remove image",
"settings.providers.selectProvider": "Select provider…",
"settings.display.username.placeholder": "User",
"settings.context.watcherPatterns.placeholder": "e.g. **/node_modules/**",
"profile.account": "Account",
"nav.marketplace": "Marketplace",
"settings.agentBehaviour.modelOverride.placeholder": "e.g. anthropic/claude-sonnet-4-20250514",
"settings.agentBehaviour.prompt.placeholder": "Custom instructions…",
"settings.agentBehaviour.mcpCommandLabel": "command",
"settings.agentBehaviour.mcpUrlLabel": "url",
"settings.agentBehaviour.skillPaths.placeholder": "e.g. ./skills",
"settings.agentBehaviour.skillUrls.placeholder": "e.g. https://example.com/skills",
"settings.agentBehaviour.instructionFiles.placeholder": "e.g. ./INSTRUCTIONS.md",
} satisfies Partial<Record<Keys, string>>
18 changes: 18 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1083,4 +1083,22 @@ export const dict = {
"agentManager.import.noBranchesFound": "No branches found.",
"agentManager.import.noBranchesHint": "Paste a PR URL above or create a new worktree.",
"agentManager.import.failed": "Import failed",
"notifications.dismiss": "Dismiss",
"notifications.previous": "Previous",
"notifications.next": "Next",
"notifications.empty": "No notifications",
"prompt.fileMention.empty": "No files found",
"prompt.image.remove": "Remove image",
"settings.providers.selectProvider": "Select provider…",
"settings.display.username.placeholder": "User",
"settings.context.watcherPatterns.placeholder": "e.g. **/node_modules/**",
"profile.account": "Account",
"nav.marketplace": "Marketplace",
"settings.agentBehaviour.modelOverride.placeholder": "e.g. anthropic/claude-sonnet-4-20250514",
"settings.agentBehaviour.prompt.placeholder": "Custom instructions…",
"settings.agentBehaviour.mcpCommandLabel": "command",
"settings.agentBehaviour.mcpUrlLabel": "url",
"settings.agentBehaviour.skillPaths.placeholder": "e.g. ./skills",
"settings.agentBehaviour.skillUrls.placeholder": "e.g. https://example.com/skills",
"settings.agentBehaviour.instructionFiles.placeholder": "e.g. ./INSTRUCTIONS.md",
}
18 changes: 18 additions & 0 deletions packages/kilo-vscode/webview-ui/src/i18n/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1034,4 +1034,22 @@ export const dict = {
"agentManager.import.noBranchesFound": "No se encontraron branches.",
"agentManager.import.noBranchesHint": "Pega una URL de PR arriba o crea un nuevo Worktree.",
"agentManager.import.failed": "Error en la importación",
"notifications.dismiss": "Dismiss",
"notifications.previous": "Previous",
"notifications.next": "Next",
"notifications.empty": "No notifications",
"prompt.fileMention.empty": "No files found",
"prompt.image.remove": "Remove image",
"settings.providers.selectProvider": "Select provider…",
"settings.display.username.placeholder": "User",
"settings.context.watcherPatterns.placeholder": "e.g. **/node_modules/**",
"profile.account": "Account",
"nav.marketplace": "Marketplace",
"settings.agentBehaviour.modelOverride.placeholder": "e.g. anthropic/claude-sonnet-4-20250514",
"settings.agentBehaviour.prompt.placeholder": "Custom instructions…",
"settings.agentBehaviour.mcpCommandLabel": "command",
"settings.agentBehaviour.mcpUrlLabel": "url",
"settings.agentBehaviour.skillPaths.placeholder": "e.g. ./skills",
"settings.agentBehaviour.skillUrls.placeholder": "e.g. https://example.com/skills",
"settings.agentBehaviour.instructionFiles.placeholder": "e.g. ./INSTRUCTIONS.md",
}
Loading