diff --git a/apps/desktop/electron.vite.config.ts b/apps/desktop/electron.vite.config.ts index a8c1e5c6a0..7736443551 100644 --- a/apps/desktop/electron.vite.config.ts +++ b/apps/desktop/electron.vite.config.ts @@ -68,6 +68,10 @@ export default defineConfig({ '@ai-sdk/openai-compatible', '@ai-sdk/provider', '@ai-sdk/provider-utils', + '@ai-sdk/mcp', + '@openrouter/ai-sdk-provider', + '@modelcontextprotocol/sdk', + '@tavily/core', ] })], build: { diff --git a/apps/desktop/src/main/agent/agent-manager.ts b/apps/desktop/src/main/agent/agent-manager.ts index 21a538490c..bb9772079e 100644 --- a/apps/desktop/src/main/agent/agent-manager.ts +++ b/apps/desktop/src/main/agent/agent-manager.ts @@ -28,6 +28,7 @@ import { createOrGetWorktree } from '../ai/worktree'; import { findTaskWorktree } from '../worktree-paths'; import { readSettingsFile } from '../settings-utils'; import type { ProviderAccount } from '../../shared/types/provider-account'; +import { getAppLanguage } from '../app-language'; import { tryLoadPrompt } from '../ai/prompts/prompt-loader'; /** @@ -395,6 +396,7 @@ export class AgentManager extends EventEmitter { baseURL: resolved.auth?.baseURL, configDir: resolved.configDir, oauthTokenFilePath: resolved.auth?.oauthTokenFilePath, + language: getAppLanguage(), mcpOptions: { context7Enabled: true, memoryEnabled: !!process.env.GRAPHITI_MCP_URL, @@ -519,6 +521,7 @@ export class AgentManager extends EventEmitter { baseURL: resolved.auth?.baseURL, configDir: resolved.configDir, oauthTokenFilePath: resolved.auth?.oauthTokenFilePath, + language: getAppLanguage(), mcpOptions: { context7Enabled: true, memoryEnabled: !!process.env.GRAPHITI_MCP_URL, @@ -627,6 +630,7 @@ export class AgentManager extends EventEmitter { memoryEnabled: !!process.env.GRAPHITI_MCP_URL, linearEnabled: !!process.env.LINEAR_API_KEY, }, + language: getAppLanguage(), toolContext: { cwd: effectiveCwd, projectDir: effectiveProjectDir, diff --git a/apps/desktop/src/main/agent/agent-queue.ts b/apps/desktop/src/main/agent/agent-queue.ts index aada34a53f..8cb60a71db 100644 --- a/apps/desktop/src/main/agent/agent-queue.ts +++ b/apps/desktop/src/main/agent/agent-queue.ts @@ -414,6 +414,7 @@ export class AgentQueueManager { refresh, enableCompetitorAnalysis, abortSignal: abortController.signal, + language: config?.language, }, (event: RoadmapStreamEvent) => { switch (event.type) { diff --git a/apps/desktop/src/main/agent/types.ts b/apps/desktop/src/main/agent/types.ts index 998ada1a77..ea1f29d97b 100644 --- a/apps/desktop/src/main/agent/types.ts +++ b/apps/desktop/src/main/agent/types.ts @@ -45,6 +45,7 @@ export interface AgentManagerEvents { export interface RoadmapConfig { model?: string; // Model shorthand (opus, sonnet, haiku) thinkingLevel?: string; // Thinking level (low, medium, high) + language?: string; // Language code for generated content (e.g., 'en', 'pt-BR') } export interface TaskExecutionOptions { diff --git a/apps/desktop/src/main/ai/agent/types.ts b/apps/desktop/src/main/ai/agent/types.ts index 0f7f453055..0123680c9e 100644 --- a/apps/desktop/src/main/ai/agent/types.ts +++ b/apps/desktop/src/main/ai/agent/types.ts @@ -61,6 +61,8 @@ export interface SerializableSessionConfig { configDir?: string; /** Pre-resolved path to OAuth token file for file-based OAuth providers (e.g., Codex). Worker-safe. */ oauthTokenFilePath?: string; + /** Language code for generated content (e.g., 'en', 'pt-BR') */ + language?: string; /** MCP options resolved from project settings (serialized for worker) */ mcpOptions?: { context7Enabled?: boolean; diff --git a/apps/desktop/src/main/ai/agent/worker.ts b/apps/desktop/src/main/ai/agent/worker.ts index f03bb19d20..4644297bda 100644 --- a/apps/desktop/src/main/ai/agent/worker.ts +++ b/apps/desktop/src/main/ai/agent/worker.ts @@ -230,6 +230,7 @@ async function assemblePrompt( specDir: session.specDir, projectDir: session.projectDir, projectInstructions: cachedProjectInstructions, + language: session.language, }); } diff --git a/apps/desktop/src/main/ai/prompts/prompt-loader.ts b/apps/desktop/src/main/ai/prompts/prompt-loader.ts index 6ad1ff34fe..4df5dd40e3 100644 --- a/apps/desktop/src/main/ai/prompts/prompt-loader.ts +++ b/apps/desktop/src/main/ai/prompts/prompt-loader.ts @@ -243,7 +243,14 @@ export function injectContext(promptTemplate: string, context: PromptContext): s ); } - // 5. Base prompt + // 5. Language instruction + if (context.language && context.language !== 'en') { + sections.push( + `## OUTPUT LANGUAGE\n\nYou MUST write ALL human-readable text content in **${context.language}**. This includes: titles, descriptions, rationale, acceptance criteria, user stories, phase names, status messages, and any text shown to the user. Keep JSON keys, code, file paths, technical identifiers, and enum values in English.\n\n---\n\n` + ); + } + + // 6. Base prompt sections.push(promptTemplate); return sections.join(''); diff --git a/apps/desktop/src/main/ai/prompts/types.ts b/apps/desktop/src/main/ai/prompts/types.ts index 335bca3f9b..5f92f665e5 100644 --- a/apps/desktop/src/main/ai/prompts/types.ts +++ b/apps/desktop/src/main/ai/prompts/types.ts @@ -32,6 +32,8 @@ export interface PromptContext { recoveryHints?: string[]; /** Phase-specific planning retry context */ planningRetryContext?: string; + /** Language code for generated content (e.g., 'en', 'pt-BR') */ + language?: string; } // ============================================================================= diff --git a/apps/desktop/src/main/ai/runners/roadmap.ts b/apps/desktop/src/main/ai/runners/roadmap.ts index b589af4c70..0f14de0bbe 100644 --- a/apps/desktop/src/main/ai/runners/roadmap.ts +++ b/apps/desktop/src/main/ai/runners/roadmap.ts @@ -10,9 +10,11 @@ */ import { streamText, stepCountIs } from 'ai'; +import { randomUUID } from 'node:crypto'; import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync } from 'node:fs'; import { join } from 'node:path'; +import { withFileLock } from '../../utils/file-lock'; import { createSimpleClient } from '../client/factory'; import type { SimpleClientResult } from '../client/types'; import { buildToolRegistry } from '../tools/build-registry'; @@ -51,6 +53,8 @@ export interface RoadmapConfig { enableCompetitorAnalysis?: boolean; /** Abort signal for cancellation */ abortSignal?: AbortSignal; + /** Language code for generated content (e.g., 'en', 'pt-BR') */ + language?: string; } /** Result of a roadmap phase */ @@ -103,6 +107,7 @@ async function runDiscoveryPhase( client: SimpleClientResult, abortSignal?: AbortSignal, onStream?: RoadmapStreamCallback, + language?: string, ): Promise { const discoveryFile = join(outputDir, 'roadmap_discovery.json'); const projectIndexFile = join(outputDir, 'project_index.json'); @@ -121,7 +126,10 @@ async function runDiscoveryPhase( const loadedDiscoveryPrompt = tryLoadPrompt('roadmap_discovery'); for (let attempt = 0; attempt < MAX_RETRIES; attempt++) { - const contextBlock = `\n\n---\n\n## CONTEXT (injected by runner)\n\n**Project Directory**: ${projectDir}\n**Project Index**: ${projectIndexFile}\n**Output Directory**: ${outputDir}\n**Output File**: ${discoveryFile}\n\nUse the paths above when reading input files and writing output.`; + const languageInstruction = language && language !== 'en' + ? `\n\n**LANGUAGE**: You MUST write ALL human-readable text content in ${language}. This includes: project descriptions, pain points, goals, vision statements, value propositions, success metrics, feature names, known gaps, differentiators, market position, and constraints. Keep JSON keys, technical terms (framework names, language names), and file paths in English.` + : ''; + const contextBlock = `\n\n---\n\n## CONTEXT (injected by runner)\n\n**Project Directory**: ${projectDir}\n**Project Index**: ${projectIndexFile}\n**Output Directory**: ${outputDir}\n**Output File**: ${discoveryFile}\n\nUse the paths above when reading input files and writing output.${languageInstruction}`; const prompt = loadedDiscoveryPrompt ? loadedDiscoveryPrompt + contextBlock @@ -140,7 +148,7 @@ Your task: The JSON must contain at minimum: project_name, target_audience, product_vision, key_features, technical_stack, and constraints. -Do NOT ask questions. Make educated inferences and create the file.`; +Do NOT ask questions. Make educated inferences and create the file.${languageInstruction}`; const discoveryUserPrompt = 'Analyze the project and create the discovery document. Use the available tools to explore the codebase, then write your findings as JSON to the output file specified in the context above.'; @@ -217,6 +225,7 @@ async function runFeaturesPhase( client: SimpleClientResult, abortSignal?: AbortSignal, onStream?: RoadmapStreamCallback, + language?: string, ): Promise { const roadmapFile = join(outputDir, 'roadmap.json'); const discoveryFile = join(outputDir, 'roadmap_discovery.json'); @@ -253,7 +262,10 @@ The following ${preservedFeatures.length} features already exist and will be pre Generate NEW features that complement these, do not duplicate them: ${preservedInfo}\n`; } - const featuresContextBlock = `\n\n---\n\n## CONTEXT (injected by runner)\n\n**Discovery File**: ${discoveryFile}\n**Project Index**: ${projectIndexFile}\n**Output File**: ${roadmapFile}\n${preservedSection}\nUse the paths above when reading input files and writing output. Write the complete roadmap JSON to the Output File path.`; + const featuresLanguageInstruction = language && language !== 'en' + ? `\n\n**LANGUAGE**: You MUST write ALL human-readable text content in ${language}. This includes: feature titles, descriptions, rationales, acceptance criteria, user stories, phase names, phase descriptions, milestone titles, milestone descriptions, vision statement, and audience descriptions. Keep JSON keys, technical terms, file paths, and enum values (must/should/could/wont, low/medium/high, idea/planned) in English.` + : ''; + const featuresContextBlock = `\n\n---\n\n## CONTEXT (injected by runner)\n\n**Discovery File**: ${discoveryFile}\n**Project Index**: ${projectIndexFile}\n**Output File**: ${roadmapFile}\n${preservedSection}\nUse the paths above when reading input files and writing output. Write the complete roadmap JSON to the Output File path.${featuresLanguageInstruction}`; const prompt = loadedFeaturesPrompt ? loadedFeaturesPrompt + featuresContextBlock @@ -272,7 +284,7 @@ Based on the discovery data: 6. Map dependencies Output the complete roadmap as valid JSON to ${roadmapFile}. -The JSON must contain: vision, target_audience (object with "primary" key), phases (array), and features (array with at least 3 items each with id, title, description, priority, complexity, impact, phase_id, status, acceptance_criteria, and user_stories).`; +The JSON must contain: vision, target_audience (object with "primary" key), phases (array), and features (array with at least 3 items each with id, title, description, priority, complexity, impact, phase_id, status, acceptance_criteria, and user_stories).${featuresLanguageInstruction}`; const featuresUserPrompt = 'Read the discovery data and generate a complete roadmap with prioritized features. Write the roadmap JSON to the output file specified in the context above.'; @@ -330,13 +342,15 @@ The JSON must contain: vision, target_audience (object with "primary" key), phas } if (missing.length === 0 && featureCount >= 3) { - // Merge preserved features — atomic write via temp file + rename + // Merge preserved features — atomic write with file lock to prevent races if (preservedFeatures.length > 0) { data.features = mergeFeatures(data.features as Record[], preservedFeatures); const merged = JSON.stringify(data, null, 2); - const tmpFile = `${roadmapFile}.tmp.${process.pid}`; - writeFileSync(tmpFile, merged, 'utf-8'); - renameSync(tmpFile, roadmapFile); + await withFileLock(roadmapFile, async () => { + const tmpFile = `${roadmapFile}.tmp.${process.pid}.${randomUUID()}`; + writeFileSync(tmpFile, merged, 'utf-8'); + renameSync(tmpFile, roadmapFile); + }); } return { phase: 'features', success: true, outputs: [roadmapFile], errors: [] }; } @@ -441,6 +455,7 @@ export async function runRoadmapGeneration( thinkingLevel = 'medium', refresh = false, abortSignal, + language = 'en', } = config; const outputDir = config.outputDir ?? join(projectDir, '.auto-claude', 'roadmap'); @@ -475,7 +490,7 @@ export async function runRoadmapGeneration( // Phase 1: Discovery onStream?.({ type: 'phase-start', phase: 'discovery' }); const discoveryResult = await runDiscoveryPhase( - projectDir, outputDir, refresh, client, abortSignal, onStream, + projectDir, outputDir, refresh, client, abortSignal, onStream, language, ); phases.push(discoveryResult); onStream?.({ type: 'phase-complete', phase: 'discovery', success: discoveryResult.success }); @@ -491,7 +506,7 @@ export async function runRoadmapGeneration( // Phase 2: Feature Generation onStream?.({ type: 'phase-start', phase: 'features' }); const featuresResult = await runFeaturesPhase( - projectDir, outputDir, refresh, client, abortSignal, onStream, + projectDir, outputDir, refresh, client, abortSignal, onStream, language, ); phases.push(featuresResult); onStream?.({ type: 'phase-complete', phase: 'features', success: featuresResult.success }); diff --git a/apps/desktop/src/main/ipc-handlers/roadmap-handlers.ts b/apps/desktop/src/main/ipc-handlers/roadmap-handlers.ts index 3c17026a3c..3bf198572b 100644 --- a/apps/desktop/src/main/ipc-handlers/roadmap-handlers.ts +++ b/apps/desktop/src/main/ipc-handlers/roadmap-handlers.ts @@ -25,6 +25,7 @@ import { safeSendToRenderer } from "./utils"; import { writeFileWithRetry, readFileWithRetry } from "../utils/atomic-file"; import { withFileLock } from "../utils/file-lock"; import { getActiveProviderFeatureSettings } from "./feature-settings-helper"; +import { getAppLanguage } from "../app-language"; /** * Read roadmap feature settings using per-provider resolution @@ -217,6 +218,7 @@ export function registerRoadmapHandlers( const config: RoadmapConfig = { model: featureSettings.model, thinkingLevel: featureSettings.thinkingLevel, + language: getAppLanguage(), }; debugLog("[Roadmap Handler] Generate request:", { @@ -279,6 +281,7 @@ export function registerRoadmapHandlers( const config: RoadmapConfig = { model: featureSettings.model, thinkingLevel: featureSettings.thinkingLevel, + language: getAppLanguage(), }; debugLog("[Roadmap Handler] Refresh request:", { diff --git a/apps/desktop/src/renderer/components/AddFeatureDialog.tsx b/apps/desktop/src/renderer/components/AddFeatureDialog.tsx index 9b451386ab..7dd8046018 100644 --- a/apps/desktop/src/renderer/components/AddFeatureDialog.tsx +++ b/apps/desktop/src/renderer/components/AddFeatureDialog.tsx @@ -89,7 +89,7 @@ export function AddFeatureDialog({ onFeatureAdded, defaultPhaseId }: AddFeatureDialogProps) { - const { t } = useTranslation('dialogs'); + const { t } = useTranslation(['dialogs', 'common']); // Form state const [title, setTitle] = useState(''); @@ -283,7 +283,7 @@ export function AddFeatureDialog({ {Object.entries(ROADMAP_PRIORITY_LABELS).map(([value, label]) => ( - {label} + {t(`common:${label}`)} ))} diff --git a/apps/desktop/src/renderer/components/RoadmapKanbanView.tsx b/apps/desktop/src/renderer/components/RoadmapKanbanView.tsx index 399d2ca362..3e3db11e4e 100644 --- a/apps/desktop/src/renderer/components/RoadmapKanbanView.tsx +++ b/apps/desktop/src/renderer/components/RoadmapKanbanView.tsx @@ -17,6 +17,7 @@ import { sortableKeyboardCoordinates, verticalListSortingStrategy, } from '@dnd-kit/sortable'; +import { useTranslation } from 'react-i18next'; import { Plus, Inbox, Eye, Calendar, Play, Check } from 'lucide-react'; import { ScrollArea } from './ui/scroll-area'; import { Badge } from './ui/badge'; @@ -76,6 +77,7 @@ function DroppableStatusColumn({ onArchive, isOver }: DroppableStatusColumnProps) { + const { t } = useTranslation('common'); const { setNodeRef } = useDroppable({ id: column.id }); @@ -110,7 +112,7 @@ function DroppableStatusColumn({ {getStatusIcon(column.icon)}

- {column.label} + {t(column.label)}

{features.length} @@ -138,16 +140,16 @@ function DroppableStatusColumn({
- Drop here + {t('roadmap.kanban.dropHere')} ) : ( <> - No features + {t('roadmap.kanban.noFeatures')} - Drag features here + {t('roadmap.kanban.dragFeaturesHere')} )} @@ -181,6 +183,7 @@ export function RoadmapKanbanView({ onSave, onArchive }: RoadmapKanbanViewProps) { + const { t } = useTranslation('common'); const [activeFeature, setActiveFeature] = useState(null); const [overColumnId, setOverColumnId] = useState(null); @@ -282,7 +285,7 @@ export function RoadmapKanbanView({ // Get status label for a feature (for display in drag overlay) const getStatusLabelForFeature = (feature: RoadmapFeature) => { const statusColumn = ROADMAP_STATUS_COLUMNS.find((c) => c.id === feature.status); - return statusColumn?.label || 'Unknown Status'; + return statusColumn ? t(statusColumn.label) : t('roadmap.unknownStatus'); }; return ( diff --git a/apps/desktop/src/renderer/components/SortableFeatureCard.tsx b/apps/desktop/src/renderer/components/SortableFeatureCard.tsx index befd2c0e88..e96cd56372 100644 --- a/apps/desktop/src/renderer/components/SortableFeatureCard.tsx +++ b/apps/desktop/src/renderer/components/SortableFeatureCard.tsx @@ -88,7 +88,7 @@ export function SortableFeatureCard({ variant="outline" className={cn('text-[10px] px-1.5 py-0', ROADMAP_PRIORITY_COLORS[feature.priority])} > - {ROADMAP_PRIORITY_LABELS[feature.priority]} + {t(ROADMAP_PRIORITY_LABELS[feature.priority])} {phaseName && ( @@ -102,7 +102,7 @@ export function SortableFeatureCard({ - Phase: {phaseName} + {t('roadmap.phaseLabel', { phase: phaseName })} )} @@ -117,7 +117,7 @@ export function SortableFeatureCard({ - This feature addresses competitor pain points + {t('roadmap.competitorInsight.tooltip')} )} @@ -191,13 +191,13 @@ export function SortableFeatureCard({ variant="outline" className={cn('text-[10px] px-1.5 py-0', ROADMAP_COMPLEXITY_COLORS[feature.complexity])} > - {feature.complexity} + {t(`roadmap.complexity.${feature.complexity}`)} - {feature.impact} + {t(`roadmap.impact.${feature.impact}`)} {/* Show vote count if from external source */} {feature.votes !== undefined && feature.votes > 0 && ( @@ -212,7 +212,7 @@ export function SortableFeatureCard({ - {feature.votes} votes from user feedback + {t('roadmap.votesFromFeedback', { count: feature.votes })} )} @@ -224,11 +224,11 @@ export function SortableFeatureCard({ variant="outline" className="text-[10px] px-1.5 py-0 text-orange-500 border-orange-500/30" > - {feature.source?.provider === 'canny' ? 'Canny' : 'External'} + {feature.source?.provider === 'canny' ? 'Canny' : t('roadmap.externalSource')} - Imported from {feature.source?.provider} + {t('roadmap.importedFrom', { provider: feature.source?.provider })} )} diff --git a/apps/desktop/src/renderer/components/TerminalGrid.tsx b/apps/desktop/src/renderer/components/TerminalGrid.tsx index b2daf53bca..dd8e252802 100644 --- a/apps/desktop/src/renderer/components/TerminalGrid.tsx +++ b/apps/desktop/src/renderer/components/TerminalGrid.tsx @@ -42,7 +42,7 @@ interface TerminalGridProps { } export function TerminalGrid({ projectPath, onNewTaskClick, isActive = false }: TerminalGridProps) { - const { t } = useTranslation('common'); + const { t } = useTranslation(['terminal', 'common']); const allTerminals = useTerminalStore((state) => state.terminals); // Track terminals that are in the grace period before being filtered out @@ -446,16 +446,15 @@ export function TerminalGrid({ projectPath, onNewTaskClick, isActive = false }:
-

Agent Terminals

+

{t('terminal:grid.title')}

- Spawn multiple terminals to run Claude agents in parallel. - Use Ctrl+T to create a new terminal. + {t('terminal:grid.description')}

); @@ -473,7 +472,7 @@ export function TerminalGrid({ projectPath, onNewTaskClick, isActive = false }:
- {terminals.length} / 12 terminals + {t('terminal:grid.terminalCount', { count: terminals.length, max: 12 })}
@@ -494,13 +493,13 @@ export function TerminalGrid({ projectPath, onNewTaskClick, isActive = false }: ) : ( )} - History + {t('terminal:grid.history')}
- Restore sessions from... + {t('terminal:grid.restoreSessionsFrom')}
{sessionDates.map((dateInfo) => ( @@ -511,7 +510,7 @@ export function TerminalGrid({ projectPath, onNewTaskClick, isActive = false }: > {dateInfo.label} - {dateInfo.sessionCount} session{dateInfo.sessionCount !== 1 ? 's' : ''} + {t('terminal:grid.sessionCount', { count: dateInfo.sessionCount })} ))} @@ -527,7 +526,7 @@ export function TerminalGrid({ projectPath, onNewTaskClick, isActive = false }: }} > - {t('actions.settings')} + {t('common:actions.settings')} {terminals.some((t) => t.status === 'running' && !t.isCLIMode) && ( )} )}
diff --git a/apps/desktop/src/renderer/components/Worktrees.tsx b/apps/desktop/src/renderer/components/Worktrees.tsx index ffd365b299..0d0990ef08 100644 --- a/apps/desktop/src/renderer/components/Worktrees.tsx +++ b/apps/desktop/src/renderer/components/Worktrees.tsx @@ -59,7 +59,7 @@ interface WorktreesProps { } export function Worktrees({ projectId }: WorktreesProps) { - const { t } = useTranslation(['common', 'dialogs']); + const { t } = useTranslation(['common', 'dialogs', 'terminal']); const { toast } = useToast(); const projects = useProjectStore((state) => state.projects); const selectedProject = projects.find((p) => p.id === projectId); @@ -465,7 +465,7 @@ export function Worktrees({ projectId }: WorktreesProps) { if (!selectedProject) { return (
-

Select a project to view worktrees

+

{t('dialogs:worktrees.selectProject')}

); } @@ -477,10 +477,10 @@ export function Worktrees({ projectId }: WorktreesProps) {

- Worktrees + {t('dialogs:worktrees.title')}

- Manage isolated workspaces for your Aperant tasks + {t('dialogs:worktrees.description')}

@@ -547,7 +547,7 @@ export function Worktrees({ projectId }: WorktreesProps) {
-

Error

+

{t('common:labels.error')}

{error}

@@ -567,10 +567,9 @@ export function Worktrees({ projectId }: WorktreesProps) {
-

No Worktrees

+

{t('dialogs:worktrees.empty')}

- Worktrees are created automatically when Aperant builds features. - You can also create terminal worktrees from the Agent Terminals tab. + {t('dialogs:worktrees.emptyDescription')}

)} @@ -584,7 +583,7 @@ export function Worktrees({ projectId }: WorktreesProps) {

- Task Worktrees + {t('terminal:worktree.taskWorktrees')}

{worktrees.map((worktree) => { const task = findTaskForWorktree(worktree.specName); @@ -623,11 +622,11 @@ export function Worktrees({ projectId }: WorktreesProps) {
- {worktree.filesChanged ?? 0} files changed + {t('dialogs:worktrees.filesChanged', { count: worktree.filesChanged ?? 0 })}
- {worktree.commitCount ?? 0} commits ahead + {t('dialogs:worktrees.commitsAhead', { count: worktree.commitCount ?? 0 })}
@@ -655,7 +654,7 @@ export function Worktrees({ projectId }: WorktreesProps) { disabled={!task} > - Merge to {worktree.baseBranch} + {t('dialogs:worktrees.mergeTo', { branch: worktree.baseBranch })} {task && (
@@ -711,7 +710,7 @@ export function Worktrees({ projectId }: WorktreesProps) {

- Terminal Worktrees + {t('terminal:worktree.existing')}

{terminalWorktrees.map((wt) => { const terminalId = `${TERMINAL_PREFIX}${wt.name}`; @@ -759,7 +758,7 @@ export function Worktrees({ projectId }: WorktreesProps) { {/* Created at */} {wt.createdAt && (
- Created {new Date(wt.createdAt).toLocaleDateString()} + {t('dialogs:worktrees.createdAt', { date: new Date(wt.createdAt).toLocaleDateString() })}
)} @@ -774,7 +773,7 @@ export function Worktrees({ projectId }: WorktreesProps) { }} > - Copy Path + {t('dialogs:worktrees.copyPath')}
@@ -802,10 +801,10 @@ export function Worktrees({ projectId }: WorktreesProps) { - Merge Worktree + {t('dialogs:worktrees.merge')} - Merge changes from this worktree into the base branch. + {t('dialogs:worktrees.mergeDescription')} @@ -813,21 +812,21 @@ export function Worktrees({ projectId }: WorktreesProps) {
- Source Branch + {t('dialogs:worktrees.sourceBranch')} {selectedWorktree.isOrphaned ? t('common:labels.orphaned') : selectedWorktree.branch}
- Target Branch + {t('dialogs:worktrees.targetBranch')} {selectedWorktree.baseBranch}
- Changes + {t('dialogs:worktrees.changes')} - {selectedWorktree.commitCount ?? 0} commits, {selectedWorktree.filesChanged ?? 0} files + {t('dialogs:worktrees.changesSummary', { commits: selectedWorktree.commitCount ?? 0, files: selectedWorktree.filesChanged ?? 0 })}
@@ -850,12 +849,12 @@ export function Worktrees({ projectId }: WorktreesProps) { )}

- {mergeResult.success ? 'Merge Successful' : 'Merge Failed'} + {mergeResult.success ? t('dialogs:worktrees.mergeSuccessful') : t('dialogs:worktrees.mergeFailed')}

{mergeResult.message}

{mergeResult.conflictFiles && mergeResult.conflictFiles.length > 0 && (
-

Conflicting files:

+

{t('dialogs:worktrees.conflictingFiles')}

    {mergeResult.conflictFiles.map(file => (
  • {file}
  • @@ -877,7 +876,7 @@ export function Worktrees({ projectId }: WorktreesProps) { setMergeResult(null); }} > - {mergeResult ? 'Close' : 'Cancel'} + {mergeResult ? t('common:buttons.close') : t('common:buttons.cancel')} {!mergeResult && ( @@ -905,19 +904,18 @@ export function Worktrees({ projectId }: WorktreesProps) { !open && !isDeleting && setShowDeleteConfirm(false)}> - Delete Worktree? + {t('dialogs:worktrees.delete')} - This will permanently delete the worktree and all uncommitted changes. + {t('dialogs:worktrees.deleteDescription')} {worktreeToDelete && ( {worktreeToDelete.isOrphaned ? t('common:labels.orphaned') : worktreeToDelete.branch} )} - This action cannot be undone. - Cancel + {t('common:buttons.cancel')} { e.preventDefault(); @@ -929,12 +927,12 @@ export function Worktrees({ projectId }: WorktreesProps) { {isDeleting ? ( <> - Deleting... + {t('dialogs:worktrees.deleting')} ) : ( <> - Delete + {t('common:buttons.delete')} )} @@ -946,9 +944,9 @@ export function Worktrees({ projectId }: WorktreesProps) { !open && !isDeletingTerminal && setTerminalWorktreeToDelete(null)}> - Delete Terminal Worktree? + {t('dialogs:worktrees.delete')} - This will permanently delete the worktree and its branch. Any uncommitted changes will be lost. + {t('dialogs:worktrees.deleteDescription')} {terminalWorktreeToDelete && ( {terminalWorktreeToDelete.name} @@ -960,7 +958,7 @@ export function Worktrees({ projectId }: WorktreesProps) { - Cancel + {t('common:buttons.cancel')} { e.preventDefault(); @@ -972,12 +970,12 @@ export function Worktrees({ projectId }: WorktreesProps) { {isDeletingTerminal ? ( <> - Deleting... + {t('dialogs:worktrees.deleting')} ) : ( <> - Delete + {t('common:buttons.delete')} )} diff --git a/apps/desktop/src/renderer/components/changelog/ChangelogList.tsx b/apps/desktop/src/renderer/components/changelog/ChangelogList.tsx index 67731fdde5..ad31bf39b0 100644 --- a/apps/desktop/src/renderer/components/changelog/ChangelogList.tsx +++ b/apps/desktop/src/renderer/components/changelog/ChangelogList.tsx @@ -1,3 +1,4 @@ +import { useTranslation } from 'react-i18next'; import { FileText, GitCommit, Loader2, ArrowRight } from 'lucide-react'; import { Button } from '../ui/button'; import { Badge } from '../ui/badge'; @@ -33,6 +34,8 @@ export function ChangelogList({ onContinue, canContinue }: ChangelogListProps) { + const { t } = useTranslation('common'); + // Get summary text for footer badge const getSummaryCount = () => { switch (sourceMode) { @@ -46,15 +49,15 @@ export function ChangelogList({ } }; - const getSummaryLabel = () => { + const getSummaryLabelKey = () => { switch (sourceMode) { case 'tasks': - return 'task'; + return 'changelog.task'; case 'git-history': case 'branch-diff': - return 'commit'; + return 'changelog.commit'; default: - return 'item'; + return 'changelog.item'; } }; @@ -67,7 +70,7 @@ export function ChangelogList({
    - {selectedTaskIds.length} of {doneTasks.length} tasks selected + {t('changelog.tasksSelected', { selected: selectedTaskIds.length, total: doneTasks.length })}
    @@ -96,9 +99,9 @@ export function ChangelogList({
    -

    No Completed Tasks

    +

    {t('changelog.noCompletedTasks')}

    - Complete tasks in the Kanban board and mark them as "Done" to include them in your changelog. + {t('changelog.noCompletedTasksHint')}

    @@ -125,7 +128,7 @@ export function ChangelogList({
    - {previewCommits.length} commit{previewCommits.length !== 1 ? 's' : ''} found + {t('changelog.commitsFound', { count: previewCommits.length })} {isLoadingCommits && ( @@ -139,18 +142,18 @@ export function ChangelogList({
    -

    Loading commits...

    +

    {t('changelog.loadingCommits')}

    ) : previewCommits.length === 0 ? (
    -

    No Commits Found

    +

    {t('changelog.noCommitsFound')}

    {sourceMode === 'git-history' - ? 'Configure the history options and click "Load Commits" to preview.' - : 'Select both branches and click "Load Commits" to see the changes.'} + ? t('changelog.configureHistoryHint') + : t('changelog.selectBranchesHint')}

    @@ -168,11 +171,11 @@ export function ChangelogList({ {/* Footer with Continue button */}
    diff --git a/apps/desktop/src/renderer/components/roadmap/FeatureCard.tsx b/apps/desktop/src/renderer/components/roadmap/FeatureCard.tsx index 87d139e72c..2e953f9a45 100644 --- a/apps/desktop/src/renderer/components/roadmap/FeatureCard.tsx +++ b/apps/desktop/src/renderer/components/roadmap/FeatureCard.tsx @@ -29,29 +29,29 @@ export function FeatureCard({
    - {ROADMAP_PRIORITY_LABELS[feature.priority]} + {t(ROADMAP_PRIORITY_LABELS[feature.priority])} - {feature.complexity} + {t(`roadmap.complexity.${feature.complexity}`)} - {feature.impact} impact + {t('roadmap.impact.label', { impact: t(`roadmap.impact.${feature.impact}`) })} {hasCompetitorInsight && ( - Competitor Insight + {t('roadmap.competitorInsight.badge')} - This feature addresses competitor pain points + {t('roadmap.competitorInsight.tooltip')} )}
    diff --git a/apps/desktop/src/renderer/components/roadmap/FeatureDetailPanel.tsx b/apps/desktop/src/renderer/components/roadmap/FeatureDetailPanel.tsx index ab08fed4a9..9cfb150bb3 100644 --- a/apps/desktop/src/renderer/components/roadmap/FeatureDetailPanel.tsx +++ b/apps/desktop/src/renderer/components/roadmap/FeatureDetailPanel.tsx @@ -50,20 +50,20 @@ export function FeatureDetailPanel({ }; return ( -
    +
    {/* Header */}
    - {ROADMAP_PRIORITY_LABELS[feature.priority]} + {t(ROADMAP_PRIORITY_LABELS[feature.priority])} - {feature.complexity} + {t(`roadmap.complexity.${feature.complexity}`)}

    {feature.title}

    @@ -94,7 +94,7 @@ export function FeatureDetailPanel({
    {/* Description */}
    -

    Description

    +

    {t('roadmap.featureDetail.description')}

    {feature.description}

    @@ -102,7 +102,7 @@ export function FeatureDetailPanel({

    - Rationale + {t('roadmap.featureDetail.rationale')}

    {feature.rationale}

    @@ -113,19 +113,19 @@ export function FeatureDetailPanel({
    - {feature.complexity} + {t(`roadmap.complexity.${feature.complexity}`)}
    -
    Complexity
    +
    {t('roadmap.featureDetail.complexity')}
    - {feature.impact} + {t(`roadmap.impact.${feature.impact}`)}
    -
    Impact
    +
    {t('roadmap.featureDetail.impact')}
    {feature.dependencies.length}
    -
    Dependencies
    +
    {t('roadmap.featureDetail.dependencies')}
    @@ -134,7 +134,7 @@ export function FeatureDetailPanel({

    - User Stories + {t('roadmap.featureDetail.userStories')}

    {feature.userStories.map((story, i) => ( @@ -151,7 +151,7 @@ export function FeatureDetailPanel({

    - Acceptance Criteria + {t('roadmap.featureDetail.acceptanceCriteria')}

      {feature.acceptanceCriteria.map((criterion, i) => ( @@ -169,7 +169,7 @@ export function FeatureDetailPanel({

      - Dependencies + {t('roadmap.featureDetail.dependencies')}

      {feature.dependencies.map((dep) => ( @@ -186,7 +186,7 @@ export function FeatureDetailPanel({

      - Addresses Competitor Pain Points + {t('roadmap.featureDetail.competitorInsights')}

      {competitorInsights.map((insight) => ( @@ -209,7 +209,7 @@ export function FeatureDetailPanel({ : 'text-green-500 border-green-500/50' }`} > - {insight.severity} severity + {t('roadmap.featureDetail.severityLabel', { severity: insight.severity })}
      @@ -277,17 +277,17 @@ export function FeatureDetailPanel({
      -

      Delete Feature?

      +

      {t('roadmap.featureDetail.deleteTitle')}

      - This will permanently remove "{feature.title}" from your roadmap. + {t('roadmap.featureDetail.deleteConfirmMessage', { title: feature.title })}

      diff --git a/apps/desktop/src/renderer/components/roadmap/RoadmapEmptyState.tsx b/apps/desktop/src/renderer/components/roadmap/RoadmapEmptyState.tsx index 55f56c53a7..cc80e72da1 100644 --- a/apps/desktop/src/renderer/components/roadmap/RoadmapEmptyState.tsx +++ b/apps/desktop/src/renderer/components/roadmap/RoadmapEmptyState.tsx @@ -1,21 +1,22 @@ import { Map, Sparkles } from 'lucide-react'; +import { useTranslation } from 'react-i18next'; import { Button } from '../ui/button'; import { Card } from '../ui/card'; import type { RoadmapEmptyStateProps } from './types'; export function RoadmapEmptyState({ onGenerate }: RoadmapEmptyStateProps) { + const { t } = useTranslation('common'); return (
      -

      No Roadmap Yet

      +

      {t('roadmap.emptyTitle')}

      - Generate an AI-powered roadmap that understands your project's target audience and - creates a strategic feature plan. + {t('roadmap.emptyDescription')}

      diff --git a/apps/desktop/src/renderer/components/roadmap/RoadmapTabs.tsx b/apps/desktop/src/renderer/components/roadmap/RoadmapTabs.tsx index 1ba5f7edfc..870e1a3969 100644 --- a/apps/desktop/src/renderer/components/roadmap/RoadmapTabs.tsx +++ b/apps/desktop/src/renderer/components/roadmap/RoadmapTabs.tsx @@ -32,10 +32,10 @@ export function RoadmapTabs({ return ( - Kanban - Phases - All Features - By Priority + {t('roadmap.tabs.kanban')} + {t('roadmap.tabs.phases')} + {t('roadmap.tabs.allFeatures')} + {t('roadmap.tabs.byPriority')} {/* Kanban View */} @@ -95,9 +95,9 @@ export function RoadmapTabs({
      - {ROADMAP_PRIORITY_LABELS[priority]} + {t(ROADMAP_PRIORITY_LABELS[priority])} - {features.length} features + {t('roadmap.featuresCount', { count: features.length })}
      {features.map((feature: RoadmapFeature) => { @@ -118,18 +118,18 @@ export function RoadmapTabs({ variant="outline" className={`text-xs ${ROADMAP_COMPLEXITY_COLORS[feature.complexity]}`} > - {feature.complexity} + {t(`roadmap.complexity.${feature.complexity}`)} - {feature.impact} impact + {t('roadmap.impact.label', { impact: t(`roadmap.impact.${feature.impact}`) })} {hasCompetitorInsight(feature) && ( - Insight + {t('roadmap.insight')} )}
      @@ -138,7 +138,7 @@ export function RoadmapTabs({
      - Completed + {t('roadmap.taskCompleted')}
      )} diff --git a/apps/desktop/src/renderer/components/settings/AppSettings.tsx b/apps/desktop/src/renderer/components/settings/AppSettings.tsx index 5d1a4b92dc..17fd56d28b 100644 --- a/apps/desktop/src/renderer/components/settings/AppSettings.tsx +++ b/apps/desktop/src/renderer/components/settings/AppSettings.tsx @@ -247,7 +247,7 @@ export function AppSettingsDialog({ open, onOpenChange, initialSection, initialP
      {/* Navigation sidebar */} -
      @@ -482,19 +488,19 @@ function TaskDetailModalContent({ open, task, onOpenChange, onSwitchToTerminals, value="overview" className="rounded-none border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:bg-transparent data-[state=active]:shadow-none px-4 py-2.5 text-sm" > - Overview + {t('tasks:tabs.overview')} - Subtasks ({task.subtasks.length}) + {t('tasks:tabs.subtasks', { count: task.subtasks.length })} - Logs + {t('tasks:tabs.logs')} {showFilesTab && ( - Delete Task + {t('tasks:actions.delete')}
      {renderPrimaryAction()}
      diff --git a/apps/desktop/src/renderer/components/task-detail/TaskHeader.tsx b/apps/desktop/src/renderer/components/task-detail/TaskHeader.tsx index b2d2416deb..97427673d3 100644 --- a/apps/desktop/src/renderer/components/task-detail/TaskHeader.tsx +++ b/apps/desktop/src/renderer/components/task-detail/TaskHeader.tsx @@ -60,16 +60,16 @@ export function TaskHeader({ {isStuck ? ( - Stuck + {t('tasks:labels.stuck')} ) : isIncomplete ? ( <> - Incomplete + {t('tasks:labels.incomplete')} - {taskProgress.completed}/{taskProgress.total} subtasks + {t('tasks:labels.subtaskProgress', { completed: taskProgress.completed, total: taskProgress.total })} ) : ( @@ -85,10 +85,10 @@ export function TaskHeader({ variant={task.reviewReason === 'completed' ? 'success' : task.reviewReason === 'errors' ? 'destructive' : 'warning'} className="text-xs" > - {task.reviewReason === 'completed' ? 'Completed' : - task.reviewReason === 'errors' ? 'Has Errors' : - task.reviewReason === 'plan_review' ? 'Approve Plan' : - task.reviewReason === 'stopped' ? 'Stopped' : 'QA Issues'} + {task.reviewReason === 'completed' ? t('tasks:reviewReason.completed') : + task.reviewReason === 'errors' ? t('tasks:reviewReason.hasErrors') : + task.reviewReason === 'plan_review' ? t('tasks:reviewReason.approvePlan') : + task.reviewReason === 'stopped' ? t('tasks:reviewReason.stopped') : t('tasks:reviewReason.qaIssues')} )} diff --git a/apps/desktop/src/renderer/components/task-detail/TaskMetadata.tsx b/apps/desktop/src/renderer/components/task-detail/TaskMetadata.tsx index 9fae888430..2f60e49259 100644 --- a/apps/desktop/src/renderer/components/task-detail/TaskMetadata.tsx +++ b/apps/desktop/src/renderer/components/task-detail/TaskMetadata.tsx @@ -169,10 +169,10 @@ export function TaskMetadata({ task }: TaskMetadataProps) {
      - Created {formatRelativeTime(task.createdAt)} + {t('tasks:metadata.created', { time: formatRelativeTime(task.createdAt) })} - Updated {formatRelativeTime(task.updatedAt)} + {t('tasks:metadata.updated', { time: formatRelativeTime(task.updatedAt) })}
    @@ -237,7 +237,7 @@ export function TaskMetadata({ task }: TaskMetadataProps) {

    - Rationale + {t('tasks:metadata.rationale')}

    {task.metadata.rationale}

    @@ -248,7 +248,7 @@ export function TaskMetadata({ task }: TaskMetadataProps) {

    - Problem Solved + {t('tasks:metadata.problemSolved')}

    {task.metadata.problemSolved}

    @@ -259,7 +259,7 @@ export function TaskMetadata({ task }: TaskMetadataProps) {

    - Target Audience + {t('tasks:metadata.targetAudience')}

    {task.metadata.targetAudience}

    @@ -270,7 +270,7 @@ export function TaskMetadata({ task }: TaskMetadataProps) {

    - Dependencies + {t('tasks:metadata.dependencies')}

      {task.metadata.dependencies.map((dep, idx) => ( @@ -307,7 +307,7 @@ export function TaskMetadata({ task }: TaskMetadataProps) {

      - Acceptance Criteria + {t('tasks:metadata.acceptanceCriteria')}

        {task.metadata.acceptanceCriteria.map((criteria, idx) => ( @@ -322,7 +322,7 @@ export function TaskMetadata({ task }: TaskMetadataProps) {

        - Affected Files + {t('tasks:metadata.affectedFiles')}

        {task.metadata.affectedFiles.map((file, idx) => ( diff --git a/apps/desktop/src/shared/constants/i18n.ts b/apps/desktop/src/shared/constants/i18n.ts index 5f4ebbde38..5e95a43cdf 100644 --- a/apps/desktop/src/shared/constants/i18n.ts +++ b/apps/desktop/src/shared/constants/i18n.ts @@ -3,11 +3,12 @@ * Available languages and display labels */ -export type SupportedLanguage = 'en' | 'fr'; +export type SupportedLanguage = 'en' | 'fr' | 'pt-BR'; export const AVAILABLE_LANGUAGES = [ { value: 'en' as const, label: 'English', nativeLabel: 'English' }, - { value: 'fr' as const, label: 'French', nativeLabel: 'Français' } + { value: 'fr' as const, label: 'French', nativeLabel: 'Français' }, + { value: 'pt-BR' as const, label: 'Brazilian Portuguese', nativeLabel: 'Português' } ] as const; export const DEFAULT_LANGUAGE: SupportedLanguage = 'en'; diff --git a/apps/desktop/src/shared/constants/roadmap.ts b/apps/desktop/src/shared/constants/roadmap.ts index a1ee0bc555..fb2e91699a 100644 --- a/apps/desktop/src/shared/constants/roadmap.ts +++ b/apps/desktop/src/shared/constants/roadmap.ts @@ -8,10 +8,10 @@ // ============================================ export const ROADMAP_PRIORITY_LABELS: Record = { - must: 'Must Have', - should: 'Should Have', - could: 'Could Have', - wont: "Won't Have" + must: 'roadmap.priority.mustHave', + should: 'roadmap.priority.shouldHave', + could: 'roadmap.priority.couldHave', + wont: 'roadmap.priority.wontHave' }; export const ROADMAP_PRIORITY_COLORS: Record = { @@ -53,17 +53,17 @@ export interface RoadmapStatusColumn { } export const ROADMAP_STATUS_COLUMNS: RoadmapStatusColumn[] = [ - { id: 'under_review', label: 'Under Review', color: 'border-t-muted-foreground/50', icon: 'Eye' }, - { id: 'planned', label: 'Planned', color: 'border-t-info', icon: 'Calendar' }, - { id: 'in_progress', label: 'In Progress', color: 'border-t-primary', icon: 'Play' }, - { id: 'done', label: 'Done', color: 'border-t-success', icon: 'Check' } + { id: 'under_review', label: 'roadmap.status.underReview', color: 'border-t-muted-foreground/50', icon: 'Eye' }, + { id: 'planned', label: 'roadmap.status.planned', color: 'border-t-info', icon: 'Calendar' }, + { id: 'in_progress', label: 'roadmap.status.inProgress', color: 'border-t-primary', icon: 'Play' }, + { id: 'done', label: 'roadmap.status.done', color: 'border-t-success', icon: 'Check' } ]; export const ROADMAP_STATUS_LABELS: Record = { - under_review: 'Under Review', - planned: 'Planned', - in_progress: 'In Progress', - done: 'Done' + under_review: 'roadmap.status.underReview', + planned: 'roadmap.status.planned', + in_progress: 'roadmap.status.inProgress', + done: 'roadmap.status.done' }; export const ROADMAP_STATUS_COLORS: Record = { diff --git a/apps/desktop/src/shared/constants/spellcheck.ts b/apps/desktop/src/shared/constants/spellcheck.ts index 8e32a3c0f3..b481ce21b5 100644 --- a/apps/desktop/src/shared/constants/spellcheck.ts +++ b/apps/desktop/src/shared/constants/spellcheck.ts @@ -13,6 +13,7 @@ export const SPELL_CHECK_LANGUAGE_MAP: Record = { en: ['en-US', 'en-GB'], fr: ['fr-FR', 'fr'], + 'pt-BR': ['pt-BR', 'pt'], }; /** @@ -27,4 +28,5 @@ export const DEFAULT_SPELL_CHECK_LANGUAGE = 'en-US'; export const ADD_TO_DICTIONARY_LABELS: Record = { en: 'Add to Dictionary', fr: 'Ajouter au dictionnaire', + 'pt-BR': 'Adicionar ao dicionário', }; diff --git a/apps/desktop/src/shared/i18n/index.ts b/apps/desktop/src/shared/i18n/index.ts index 095b0b1188..2d7a96e65b 100644 --- a/apps/desktop/src/shared/i18n/index.ts +++ b/apps/desktop/src/shared/i18n/index.ts @@ -27,6 +27,19 @@ import frTaskReview from './locales/fr/taskReview.json'; import frTerminal from './locales/fr/terminal.json'; import frErrors from './locales/fr/errors.json'; +// Import Brazilian Portuguese translation resources +import ptBRCommon from './locales/pt-BR/common.json'; +import ptBRNavigation from './locales/pt-BR/navigation.json'; +import ptBRSettings from './locales/pt-BR/settings.json'; +import ptBRTasks from './locales/pt-BR/tasks.json'; +import ptBRWelcome from './locales/pt-BR/welcome.json'; +import ptBROnboarding from './locales/pt-BR/onboarding.json'; +import ptBRDialogs from './locales/pt-BR/dialogs.json'; +import ptBRGitlab from './locales/pt-BR/gitlab.json'; +import ptBRTaskReview from './locales/pt-BR/taskReview.json'; +import ptBRTerminal from './locales/pt-BR/terminal.json'; +import ptBRErrors from './locales/pt-BR/errors.json'; + export const defaultNS = 'common'; export const resources = { @@ -55,6 +68,19 @@ export const resources = { taskReview: frTaskReview, terminal: frTerminal, errors: frErrors + }, + 'pt-BR': { + common: ptBRCommon, + navigation: ptBRNavigation, + settings: ptBRSettings, + tasks: ptBRTasks, + welcome: ptBRWelcome, + onboarding: ptBROnboarding, + dialogs: ptBRDialogs, + gitlab: ptBRGitlab, + taskReview: ptBRTaskReview, + terminal: ptBRTerminal, + errors: ptBRErrors } } as const; diff --git a/apps/desktop/src/shared/i18n/locales/en/common.json b/apps/desktop/src/shared/i18n/locales/en/common.json index 7c44cedbc0..9eb3d5fa3b 100644 --- a/apps/desktop/src/shared/i18n/locales/en/common.json +++ b/apps/desktop/src/shared/i18n/locales/en/common.json @@ -106,7 +106,9 @@ "save": "Save", "apply": "Apply", "delete": "Delete", - "settings": "Settings" + "settings": "Settings", + "files": "Files", + "success": "Success" }, "os": { "windows": "Windows", @@ -688,6 +690,9 @@ "footer": "The account will be available once you complete authentication." }, "roadmap": { + "emptyTitle": "No Roadmap Yet", + "emptyDescription": "Generate an AI-powered roadmap that understands your project's target audience and creates a strategic feature plan.", + "generateButton": "Generate Roadmap", "taskCompleted": "Completed", "taskDeleted": "Deleted", "taskArchived": "Archived", @@ -701,7 +706,68 @@ "convertToTask": "Convert to Auto-Build Task", "build": "Build", "task": "Task", - "viewTask": "View Task" + "viewTask": "View Task", + "status": { + "underReview": "Under Review", + "planned": "Planned", + "inProgress": "In Progress", + "done": "Done" + }, + "priority": { + "mustHave": "Must Have", + "shouldHave": "Should Have", + "couldHave": "Could Have", + "wontHave": "Won't Have" + }, + "complexity": { + "low": "Low", + "medium": "Medium", + "high": "High" + }, + "featureDetail": { + "description": "Description", + "rationale": "Rationale", + "complexity": "Complexity", + "impact": "Impact", + "dependencies": "Dependencies", + "userStories": "User Stories", + "acceptanceCriteria": "Acceptance Criteria", + "competitorInsights": "Addresses Competitor Pain Points", + "deleteTitle": "Delete Feature?", + "deleteConfirmMessage": "This will permanently remove \"{{title}}\" from your roadmap.", + "delete": "Delete", + "cancel": "Cancel", + "severityLabel": "{{severity}} severity" + }, + "impact": { + "low": "Low", + "medium": "Medium", + "high": "High", + "label": "{{impact}} impact" + }, + "tabs": { + "kanban": "Kanban", + "phases": "Phases", + "allFeatures": "All Features", + "byPriority": "By Priority" + }, + "kanban": { + "dropHere": "Drop here", + "noFeatures": "No features", + "dragFeaturesHere": "Drag features here" + }, + "insight": "Insight", + "featuresCount": "{{count}} feature", + "featuresCount_plural": "{{count}} features", + "phaseLabel": "Phase: {{phase}}", + "competitorInsight": { + "badge": "Competitor Insight", + "tooltip": "This feature addresses competitor pain points" + }, + "votesFromFeedback": "{{count}} votes from user feedback", + "externalSource": "External", + "importedFrom": "Imported from {{provider}}", + "unknownStatus": "Unknown Status" }, "roadmapGeneration": { "progress": "Progress", @@ -929,6 +995,26 @@ "memories": "Memories" } }, + "changelog": { + "tasksSelected": "{{selected}} of {{total}} tasks selected", + "selectAll": "Select All", + "clear": "Clear", + "noCompletedTasks": "No Completed Tasks", + "noCompletedTasksHint": "Complete tasks in the Kanban board and mark them as \"Done\" to include them in your changelog.", + "loadingCommits": "Loading commits...", + "noCommitsFound": "No Commits Found", + "configureHistoryHint": "Configure the history options and click \"Load Commits\" to preview.", + "selectBranchesHint": "Select both branches and click \"Load Commits\" to see the changes.", + "continue": "Continue", + "commitsFound": "{{count}} commit found", + "commitsFound_plural": "{{count}} commits found", + "task": "{{count}} task", + "task_plural": "{{count}} tasks", + "commit": "{{count}} commit", + "commit_plural": "{{count}} commits", + "item": "{{count}} item", + "item_plural": "{{count}} items" + }, "prStatus": { "ci": { "success": "CI Passed", diff --git a/apps/desktop/src/shared/i18n/locales/en/dialogs.json b/apps/desktop/src/shared/i18n/locales/en/dialogs.json index 35feafb800..5de2c60308 100644 --- a/apps/desktop/src/shared/i18n/locales/en/dialogs.json +++ b/apps/desktop/src/shared/i18n/locales/en/dialogs.json @@ -63,7 +63,20 @@ "bulkDeleteTitle": "Delete {{count}} Worktrees?", "bulkDeleteDescription": "This will permanently delete the selected worktrees and all their uncommitted changes. This action cannot be undone.", "deleting": "Deleting...", - "deleteSelected": "Delete Selected" + "deleteSelected": "Delete Selected", + "selectProject": "Select a project to view worktrees", + "filesChanged": "{{count}} files changed", + "commitsAhead": "{{count}} commits ahead", + "mergeTo": "Merge to {{branch}}", + "copyPath": "Copy Path", + "createdAt": "Created {{date}}", + "sourceBranch": "Source Branch", + "targetBranch": "Target Branch", + "changes": "Changes", + "changesSummary": "{{commits}} commits, {{files}} files", + "mergeSuccessful": "Merge Successful", + "mergeFailed": "Merge Failed", + "conflictingFiles": "Conflicting files:" }, "worktreeCleanup": { "title": "Complete Task", diff --git a/apps/desktop/src/shared/i18n/locales/en/tasks.json b/apps/desktop/src/shared/i18n/locales/en/tasks.json index a407a01886..525fb96553 100644 --- a/apps/desktop/src/shared/i18n/locales/en/tasks.json +++ b/apps/desktop/src/shared/i18n/locales/en/tasks.json @@ -32,7 +32,9 @@ "incomplete": "Incomplete", "recovering": "Recovering...", "needsRecovery": "Needs Recovery", - "needsResume": "Needs Resume" + "needsResume": "Needs Resume", + "subtasksProgress": "{{completed}}/{{total}} subtasks", + "subtaskProgress": "{{completed}}/{{total}} subtasks" }, "reviewReason": { "completed": "Completed", @@ -179,7 +181,15 @@ "severity": "severity", "pullRequest": "Pull Request", "showMore": "Show more", - "showLess": "Show less" + "showLess": "Show less", + "rationale": "Rationale", + "problemSolved": "Problem Solved", + "targetAudience": "Target Audience", + "dependencies": "Dependencies", + "acceptanceCriteria": "Acceptance Criteria", + "affectedFiles": "Affected Files", + "created": "Created {{time}}", + "updated": "Updated {{time}}" }, "images": { "removeImageAriaLabel": "Remove image {{filename}}", @@ -192,9 +202,22 @@ "doubleClickHint": "Double-click to enlarge", "lowResolution": "Low resolution preview" }, + "tabs": { + "overview": "Overview", + "subtasks": "Subtasks ({{count}})", + "logs": "Logs" + }, "notifications": { "backgroundTaskTitle": "Task continues in background", - "backgroundTaskDescription": "The task is still running. You can reopen this dialog to monitor progress." + "backgroundTaskDescription": "The task is still running. You can reopen this dialog to monitor progress.", + "cannotResumeTitle": "Cannot Resume Task", + "cannotResumeDescription": "Failed to load implementation plan. Please try again or check the task files." + }, + "errors": { + "deleteFailed": "Failed to delete task", + "mergeFailed": "Failed to merge changes", + "mergeUnknown": "Unknown error during merge", + "discardFailed": "Failed to discard changes" }, "wizard": { "createTitle": "Create New Task", diff --git a/apps/desktop/src/shared/i18n/locales/en/terminal.json b/apps/desktop/src/shared/i18n/locales/en/terminal.json index d6e4c38eae..ba8ca75cad 100644 --- a/apps/desktop/src/shared/i18n/locales/en/terminal.json +++ b/apps/desktop/src/shared/i18n/locales/en/terminal.json @@ -20,6 +20,18 @@ "noSession": "Profile switched. No active session to resume.", "migrationFailed": "Profile switched, but session migration failed. Starting fresh terminal." }, + "grid": { + "title": "Agent Terminals", + "description": "Spawn multiple terminals to run Claude agents in parallel.\nUse Ctrl+T to create a new terminal.", + "newTerminal": "New Terminal", + "terminalCount": "{{count}} / {{max}} terminals", + "history": "History", + "restoreSessionsFrom": "Restore sessions from...", + "sessionCount": "{{count}} session", + "sessionCount_plural": "{{count}} sessions", + "invokeClaudeAll": "Invoke Claude All", + "clearTask": "Clear task" + }, "worktree": { "create": "Worktree", "createNew": "New Worktree", diff --git a/apps/desktop/src/shared/i18n/locales/fr/common.json b/apps/desktop/src/shared/i18n/locales/fr/common.json index e404930657..e713fb799c 100644 --- a/apps/desktop/src/shared/i18n/locales/fr/common.json +++ b/apps/desktop/src/shared/i18n/locales/fr/common.json @@ -106,7 +106,9 @@ "save": "Enregistrer", "apply": "Appliquer", "delete": "Supprimer", - "settings": "Paramètres" + "settings": "Paramètres", + "files": "Fichiers", + "success": "Succès" }, "os": { "windows": "Windows", @@ -688,6 +690,9 @@ "footer": "Le compte sera disponible une fois l'authentification terminée." }, "roadmap": { + "emptyTitle": "Pas encore de feuille de route", + "emptyDescription": "Générez une feuille de route propulsée par l'IA qui comprend le public cible de votre projet et crée un plan stratégique de fonctionnalités.", + "generateButton": "Générer la feuille de route", "taskCompleted": "Terminé", "taskDeleted": "Supprimé", "taskArchived": "Archivé", @@ -701,7 +706,68 @@ "convertToTask": "Convertir en tâche Auto-Build", "build": "Construire", "task": "Tâche", - "viewTask": "Voir la tâche" + "viewTask": "Voir la tâche", + "featureDetail": { + "description": "Description", + "rationale": "Justification", + "complexity": "Complexité", + "impact": "Impact", + "dependencies": "Dépendances", + "userStories": "Témoignages utilisateurs", + "acceptanceCriteria": "Critères d'acceptation", + "competitorInsights": "Points faibles concurrentiels", + "deleteTitle": "Supprimer la fonctionnalité ?", + "deleteConfirmMessage": "Cela supprimera définitivement \"{{title}}\" de votre feuille de route.", + "delete": "Supprimer", + "cancel": "Annuler", + "severityLabel": "Sévérité {{severity}}" + }, + "impact": { + "low": "Faible", + "medium": "Moyen", + "high": "Élevé", + "label": "Impact {{impact}}" + }, + "status": { + "underReview": "En révision", + "planned": "Planifié", + "inProgress": "En cours", + "done": "Terminé" + }, + "priority": { + "mustHave": "Indispensable", + "shouldHave": "Important", + "couldHave": "Souhaitable", + "wontHave": "Non inclus" + }, + "complexity": { + "low": "Faible", + "medium": "Moyenne", + "high": "Élevée" + }, + "tabs": { + "kanban": "Kanban", + "phases": "Phases", + "allFeatures": "Toutes les fonctionnalités", + "byPriority": "Par priorité" + }, + "kanban": { + "dropHere": "Déposer ici", + "noFeatures": "Aucune fonctionnalité", + "dragFeaturesHere": "Faites glisser les fonctionnalités ici" + }, + "insight": "Aperçu", + "featuresCount": "{{count}} fonctionnalité", + "featuresCount_plural": "{{count}} fonctionnalités", + "unknownStatus": "Statut inconnu", + "phaseLabel": "Phase : {{phase}}", + "competitorInsight": { + "badge": "Aperçu concurrentiel", + "tooltip": "Cette fonctionnalité répond aux points faibles des concurrents" + }, + "votesFromFeedback": "{{count}} votes des retours utilisateurs", + "externalSource": "Externe", + "importedFrom": "Importé depuis {{provider}}" }, "roadmapGeneration": { "progress": "Progression", @@ -929,6 +995,26 @@ "memories": "Mémoires" } }, + "changelog": { + "tasksSelected": "{{selected}} sur {{total}} tâches sélectionnées", + "selectAll": "Tout sélectionner", + "clear": "Effacer", + "noCompletedTasks": "Aucune tâche terminée", + "noCompletedTasksHint": "Terminez des tâches dans le tableau Kanban et marquez-les comme « Terminé » pour les inclure dans votre changelog.", + "loadingCommits": "Chargement des commits...", + "noCommitsFound": "Aucun commit trouvé", + "configureHistoryHint": "Configurez les options d'historique et cliquez sur « Charger les commits » pour prévisualiser.", + "selectBranchesHint": "Sélectionnez les deux branches et cliquez sur « Charger les commits » pour voir les changements.", + "continue": "Continuer", + "commitsFound": "{{count}} commit trouvé", + "commitsFound_plural": "{{count}} commits trouvés", + "task": "{{count}} tâche", + "task_plural": "{{count}} tâches", + "commit": "{{count}} commit", + "commit_plural": "{{count}} commits", + "item": "{{count}} élément", + "item_plural": "{{count}} éléments" + }, "prStatus": { "ci": { "success": "CI réussie", diff --git a/apps/desktop/src/shared/i18n/locales/fr/tasks.json b/apps/desktop/src/shared/i18n/locales/fr/tasks.json index afcdf1c6f1..c9663e8a58 100644 --- a/apps/desktop/src/shared/i18n/locales/fr/tasks.json +++ b/apps/desktop/src/shared/i18n/locales/fr/tasks.json @@ -32,7 +32,9 @@ "incomplete": "Incomplet", "recovering": "Récupération...", "needsRecovery": "Récupération requise", - "needsResume": "Reprise requise" + "needsResume": "Reprise requise", + "subtaskProgress": "{{completed}}/{{total}} sous-tâches", + "subtasksProgress": "{{completed}}/{{total}} sous-tâches" }, "reviewReason": { "completed": "Terminé", @@ -179,7 +181,15 @@ "severity": "sévérité", "pullRequest": "Pull Request", "showMore": "Afficher plus", - "showLess": "Afficher moins" + "showLess": "Afficher moins", + "rationale": "Justification", + "problemSolved": "Problème résolu", + "targetAudience": "Public cible", + "dependencies": "Dépendances", + "acceptanceCriteria": "Critères d'acceptation", + "affectedFiles": "Fichiers affectés", + "created": "Créé {{time}}", + "updated": "Mis à jour {{time}}" }, "images": { "removeImageAriaLabel": "Supprimer l'image {{filename}}", @@ -192,9 +202,22 @@ "doubleClickHint": "Double-cliquez pour agrandir", "lowResolution": "Aperçu basse résolution" }, + "tabs": { + "overview": "Aperçu", + "subtasks": "Sous-tâches ({{count}})", + "logs": "Journaux" + }, "notifications": { "backgroundTaskTitle": "La tâche continue en arrière-plan", - "backgroundTaskDescription": "La tâche est toujours en cours. Vous pouvez rouvrir cette boîte de dialogue pour suivre la progression." + "backgroundTaskDescription": "La tâche est toujours en cours. Vous pouvez rouvrir cette boîte de dialogue pour suivre la progression.", + "cannotResumeTitle": "Impossible de reprendre la tâche", + "cannotResumeDescription": "Échec du chargement du plan d'implémentation. Veuillez réessayer ou vérifier les fichiers de la tâche." + }, + "errors": { + "deleteFailed": "Échec de la suppression de la tâche", + "mergeFailed": "Échec de la fusion des changements", + "mergeUnknown": "Erreur inconnue lors de la fusion", + "discardFailed": "Échec de l'abandon des changements" }, "wizard": { "createTitle": "Créer une nouvelle tâche", diff --git a/apps/desktop/src/shared/i18n/locales/fr/terminal.json b/apps/desktop/src/shared/i18n/locales/fr/terminal.json index 062ce6802c..2b772ae411 100644 --- a/apps/desktop/src/shared/i18n/locales/fr/terminal.json +++ b/apps/desktop/src/shared/i18n/locales/fr/terminal.json @@ -20,6 +20,18 @@ "noSession": "Profil changé. Aucune session active à reprendre.", "migrationFailed": "Profil changé, mais la migration de session a échoué. Démarrage d'un nouveau terminal." }, + "grid": { + "title": "Terminaux d'agents", + "description": "Lancez plusieurs terminaux pour exécuter des agents Claude en parallèle.\nUtilisez Ctrl+T pour créer un nouveau terminal.", + "newTerminal": "Nouveau terminal", + "terminalCount": "{{count}} / {{max}} terminaux", + "history": "Historique", + "restoreSessionsFrom": "Restaurer les sessions de...", + "sessionCount": "{{count}} session", + "sessionCount_plural": "{{count}} sessions", + "invokeClaudeAll": "Invoquer Claude partout", + "clearTask": "Effacer la tâche" + }, "worktree": { "create": "Worktree", "createNew": "Nouveau Worktree", diff --git a/apps/desktop/src/shared/i18n/locales/pt-BR/common.json b/apps/desktop/src/shared/i18n/locales/pt-BR/common.json new file mode 100644 index 0000000000..b76983f04f --- /dev/null +++ b/apps/desktop/src/shared/i18n/locales/pt-BR/common.json @@ -0,0 +1,1044 @@ +{ + "competitorAnalysis": { + "addCompetitor": "Adicionar Concorrente", + "manualBadge": "Manual", + "noCompetitorsYet": "Nenhum concorrente adicionado ainda", + "addCompetitorToStart": "Adicione um concorrente para começar", + "analysisResults": "Resultados da Análise de Concorrentes", + "analysisDescription": "Analisados {{count}} concorrentes para identificar lacunas e oportunidades de mercado", + "visit": "Visitar", + "identifiedPainPoints": "Pontos de Dor Identificados ({{count}})", + "noPainPointsIdentified": "Nenhum ponto de dor identificado", + "source": "Fonte:", + "frequency": "Frequência:", + "opportunity": "Oportunidade:", + "marketInsightsSummary": "Resumo de Insights de Mercado", + "topPainPoints": "Principais Pontos de Dor:", + "differentiatorOpportunities": "Oportunidades de Diferenciação:", + "marketTrends": "Tendências de Mercado:" + }, + "projectTab": { + "settings": "Configurações do projeto", + "showArchived": "Mostrar arquivadas", + "hideArchived": "Ocultar arquivadas", + "showArchivedTasks": "Mostrar tarefas arquivadas", + "hideArchivedTasks": "Ocultar tarefas arquivadas", + "closeTab": "Fechar aba", + "closeTabAriaLabel": "Fechar aba (remove projeto do app)", + "addProjectAriaLabel": "Adicionar projeto" + }, + "accessibility": { + "deleteFeatureAriaLabel": "Excluir funcionalidade", + "archiveFeatureAriaLabel": "Arquivar funcionalidade", + "closeFeatureDetailsAriaLabel": "Fechar detalhes da funcionalidade", + "regenerateRoadmapAriaLabel": "Regenerar Roadmap", + "repositoryOwnerAriaLabel": "Proprietário do repositório", + "repositoryVisibilityAriaLabel": "Visibilidade do repositório", + "opensInNewWindow": "abre em nova janela", + "visitExternalLink": "Visitar {{name}} (abre em nova janela)", + "upgradeSubscriptionAriaLabel": "Upgrade de assinatura (abre em nova janela)", + "learnMoreAriaLabel": "Saiba mais (abre em nova janela)", + "toggleFolder": "Alternar pasta {{name}}", + "expandFolder": "Expandir pasta {{name}}", + "collapseFolder": "Recolher pasta {{name}}", + "newConversationAriaLabel": "Nova conversa", + "saveEditAriaLabel": "Salvar", + "cancelEditAriaLabel": "Cancelar", + "moreOptionsAriaLabel": "Mais opções", + "closePanelAriaLabel": "Fechar painel", + "openOnGitHubAriaLabel": "Abrir no GitHub (abre em nova janela)", + "openOnGitLabAriaLabel": "Abrir no GitLab (abre em nova janela)", + "toggleShowArchivedAriaLabel": "Alternar mostrar tarefas arquivadas", + "clearSelectionAriaLabel": "Limpar seleção", + "selectAllAriaLabel": "Selecionar tudo", + "showDismissedAriaLabel": "Mostrar dispensadas", + "hideDismissedAriaLabel": "Ocultar dispensadas", + "configureAriaLabel": "Configurar", + "addMoreAriaLabel": "Adicionar mais", + "dismissAllAriaLabel": "Dispensar todas as ideias", + "regenerateIdeasAriaLabel": "Regenerar ideias", + "dismissAriaLabel": "Dispensar", + "browseFilesAriaLabel": "Explorar arquivos", + "renameAriaLabel": "Renomear", + "deleteAriaLabel": "Excluir", + "refreshAriaLabel": "Atualizar", + "expandAriaLabel": "Expandir", + "collapseAriaLabel": "Recolher", + "selectIdeaAriaLabel": "Selecionar ideia: {{title}}", + "convertToTaskAriaLabel": "Converter em tarefa", + "goToTaskAriaLabel": "Ir para tarefa", + "reAuthenticateProfileAriaLabel": "Reautenticar perfil", + "hideTokenEntryAriaLabel": "Ocultar entrada de token", + "enterTokenManuallyAriaLabel": "Inserir token manualmente", + "renameProfileAriaLabel": "Renomear perfil", + "deleteProfileAriaLabel": "Excluir perfil" + }, + "buttons": { + "save": "Salvar", + "cancel": "Cancelar", + "skip": "Pular", + "next": "Próximo", + "back": "Voltar", + "close": "Fechar", + "initialize": "Inicializar", + "delete": "Excluir", + "confirm": "Confirmar", + "retry": "Tentar Novamente", + "create": "Criar", + "createPR": "Criar PR", + "openPR": "Abrir PR", + "open": "Abrir", + "start": "Iniciar", + "stop": "Parar", + "refresh": "Atualizar", + "refreshing": "Atualizando...", + "merge": "Merge", + "discard": "Descartar", + "switch": "Trocar", + "add": "Adicionar", + "apply": "Aplicar", + "gotIt": "Entendi", + "continue": "Continuar", + "saving": "Salvando...", + "deleting": "Excluindo..." + }, + "actions": { + "save": "Salvar", + "apply": "Aplicar", + "delete": "Excluir", + "settings": "Configurações", + "files": "Arquivos", + "success": "Sucesso" + }, + "os": { + "windows": "Windows", + "macos": "macOS", + "linux": "Linux", + "unknown": "seu SO" + }, + "labels": { + "loading": "Carregando...", + "error": "Erro", + "success": "Sucesso", + "initializing": "Inicializando...", + "saving": "Salvando...", + "creating": "Criando...", + "noData": "Sem dados", + "optional": "Opcional", + "required": "Obrigatório", + "dismiss": "Dispensar", + "important": "Importante", + "orphaned": "(órfã)" + }, + "selection": { + "select": "Selecionar", + "done": "Concluído", + "selected": "{{count}} selecionado(s)", + "selectAll": "Selecionar Tudo", + "clearSelection": "Limpar Seleção", + "deleteSelected": "Excluir Selecionados", + "archiveSelected": "Arquivar Selecionados", + "selectedOfTotal": "{{selected}} de {{total}} selecionados" + }, + "time": { + "justNow": "Agora mesmo", + "minutesAgo": "{{count}}min atrás", + "hoursAgo": "{{count}}h atrás", + "daysAgo": "{{count}}d atrás" + }, + "errors": { + "generic": "Ocorreu um erro", + "unknownError": "Ocorreu um erro desconhecido", + "operationFailed": "Operação falhou", + "networkError": "Erro de rede", + "notFound": "Não encontrado", + "unauthorized": "Não autorizado", + "bulkDeletePartialFailure": "Algumas worktrees não puderam ser excluídas:", + "taskNotFoundForWorktree": "Tarefa não encontrada para worktree: {{specName}}", + "failedToDeleteTaskWorktree": "Falha ao excluir worktree da tarefa: {{specName}}", + "terminalWorktreeNotFound": "Worktree do terminal não encontrada: {{name}}", + "failedToDeleteTerminalWorktree": "Falha ao excluir worktree do terminal: {{name}}" + }, + "worktrees": { + "deleteSuccess": "Worktree '{{branch}}' excluída com sucesso", + "bulkDeleteSuccess": "{{count}} worktree excluída com sucesso", + "bulkDeleteSuccess_plural": "{{count}} worktrees excluídas com sucesso" + }, + "notification": { + "accountSwitched": "Conta Trocada", + "swapFrom": "Trocou de", + "swapTo": "para", + "swapReason": "(troca por {{reason}})" + }, + "rateLimit": { + "title": "Limite de Uso Atingido", + "resetsAt": "Reseta {{time}}", + "hitLimit": "{{source}} atingiu o limite de uso", + "clickToManage": "Clique para gerenciar →", + "modalTitle": "Limite de Uso do Claude Code Atingido", + "modalDescription": "Você atingiu seu limite de uso do Claude Code para este período.", + "profile": "Perfil: {{name}}", + "autoSwitching": "Trocando automaticamente para {{name}}", + "autoSwitchingDescription": "O Claude reiniciará com sua outra conta automaticamente", + "resetsTime": "Reseta {{time}}", + "usageRestored": "Seu uso será restaurado neste horário", + "switchAccount": "Trocar Conta do Claude", + "useAnotherAccount": "Usar Outra Conta", + "recommended": "Recomendado: {{name}} tem mais capacidade disponível.", + "otherSubscriptions": "Você tem outras assinaturas do Claude configuradas. Troque para continuar trabalhando:", + "selectAccount": "Selecionar conta...", + "switching": "Trocando...", + "addNewAccount": "Adicionar nova conta...", + "addAnotherSubscription": "Adicione outra assinatura do Claude para trocar automaticamente quando atingir limites de uso.", + "addAnotherAccount": "Adicionar outra conta:", + "connectAccount": "Conectar uma conta Claude:", + "accountNamePlaceholder": "Nome da conta (ex.: Trabalho, Pessoal)", + "willOpenLogin": "Isso abrirá o login do Claude para autenticar a nova conta.", + "autoSwitchOnRateLimit": "Trocar automaticamente ao atingir limite", + "upgradeTitle": "Upgrade para mais uso", + "upgradeDescription": "Faça upgrade da sua assinatura do Claude para limites de uso maiores.", + "upgradeSubscription": "Upgrade de Assinatura", + "sources": { + "changelog": "Changelog", + "task": "Tarefa", + "roadmap": "Roadmap", + "ideation": "Ideação", + "titleGenerator": "Gerador de Títulos", + "claude": "Claude" + }, + "toast": { + "authenticating": "Autenticando \"{{profileName}}\"", + "checkTerminal": "Verifique a seção Terminais de Agentes na barra lateral para completar o login OAuth.", + "authStartFailed": "Falha ao iniciar autenticação", + "addProfileFailed": "Falha ao adicionar perfil", + "tryAgain": "Por favor, tente novamente." + }, + "sdk": { + "title": "Limite de Uso do Claude Code", + "interrupted": "{{source}} foi interrompido devido a limites de uso.", + "proactiveSwap": "✓ Troca Proativa", + "reactiveSwap": "⚡ Troca Reativa", + "proactiveSwapDesc": "Trocou automaticamente de {{from}} para {{to}} antes de atingir o limite de uso.", + "reactiveSwapDesc": "Limite de uso atingido em {{from}}. Trocou automaticamente para {{to}} e reiniciou.", + "continueWithoutInterruption": "Seu trabalho continuou sem interrupção.", + "rateLimitReached": "Limite de uso atingido", + "operationStopped": "A operação foi parada porque {{account}} atingiu seu limite de uso.", + "switchBelow": "Troque para outra conta abaixo para continuar.", + "addAccountToContinue": "Adicione outra conta Claude para continuar trabalhando.", + "upgradeToProButton": "Upgrade para Pro para Limites Maiores", + "resetsLabel": "Reseta {{time}}", + "weeklyLimit": "Limite semanal - reseta em aproximadamente uma semana", + "sessionLimit": "Limite de sessão - reseta em algumas horas", + "switchAccountRetry": "Trocar Conta e Tentar Novamente", + "retrying": "Tentando novamente...", + "retry": "Tentar Novamente", + "autoSwitchRetryLabel": "Trocar automaticamente e tentar novamente ao atingir limite", + "add": "Adicionar", + "whatHappened": "O que aconteceu:", + "whatHappenedDesc": "A operação de {{source}} foi parada porque sua conta Claude ({{account}}) atingiu seu limite de uso.", + "switchRetryOrAdd": "Você pode trocar para outra conta e tentar novamente, ou adicionar mais contas acima.", + "addOrWait": "Adicione outra conta Claude acima para continuar trabalhando, ou aguarde o limite ser resetado.", + "close": "Fechar" + } + }, + "prReview": { + "reviewing": "Revisando", + "reviewed": "Revisado", + "approved": "Aprovado", + "changesRequested": "Alterações Solicitadas", + "commented": "Comentado", + "readyForFollowup": "Pronto para Acompanhamento", + "readyToMerge": "Pronto para Merge", + "pendingPost": "Publicação Pendente", + "posted": "Publicado", + "notReviewed": "Não Revisado", + "allStatuses": "Todos os status", + "allContributors": "Todos os contribuidores", + "searchPlaceholder": "Buscar PRs...", + "contributors": "Contribuidores", + "contributorsSelected": "Contribuidores ({{count}})", + "status": "Status", + "filters": "Filtros", + "clearFilters": "Limpar", + "clearSearch": "Limpar busca", + "searchContributors": "Buscar contribuidores...", + "selectedCount": "{{count}} selecionado(s)", + "noResultsFound": "Nenhum resultado encontrado", + "reset": "Resetar", + "sort": { + "label": "Ordenar", + "newest": "Mais recentes", + "oldest": "Mais antigos", + "largest": "Maiores" + }, + "pullRequests": "Pull Requests", + "open": "aberto(s)", + "selectPRToView": "Selecione um pull request para ver detalhes", + "loadingPRs": "Carregando pull requests...", + "noOpenPRs": "Nenhum pull request aberto", + "notConnected": "GitHub Não Conectado", + "connectPrompt": "Conecte sua conta do GitHub para visualizar e revisar pull requests.", + "openSettings": "Abrir Configurações", + "runAIReview": "Executar Revisão IA", + "reviewStarted": "Revisão Iniciada", + "analysisInProgress": "Análise IA em Progresso...", + "analysisComplete": "Análise Completa ({{count}} achados)", + "findingsPostedToGitHub": "Achados Publicados no GitHub", + "newCommits": "{{count}} Novo Commit", + "newCommit": "{{count}} Novo Commit", + "runFollowup": "Executar Acompanhamento", + "aiReviewInProgress": "Revisão IA em Progresso", + "waitingForChanges": "Aguardando Alterações", + "reviewComplete": "Revisão Completa", + "reviewStatus": "Status da Revisão", + "files": "arquivos", + "filesChanged": "{{count}} arquivos alterados", + "clickToViewFiles": "Clique para ver arquivos alterados", + "loadingFiles": "Carregando arquivos...", + "noFilesAvailable": "Lista de arquivos não disponível", + "posting": "Publicando...", + "postingApproval": "Publicando Aprovação...", + "postFindings": "Publicar {{count}} Achado", + "postFindings_plural": "Publicar {{count}} Achados", + "approve": "Aprovar", + "merge": "Merge", + "mergeViaGitHub": "Merge via GitHub CLI. Pode falhar se regras de proteção de branch exigirem revisões ou verificações adicionais.", + "autoApprovePR": "Aprovar PR", + "suggestions": "com {{count}} sugestões", + "postedFindings": "{{count}} achado publicado", + "postedFindings_plural": "{{count}} achados publicados", + "resolved": "{{count}} resolvido", + "resolved_plural": "{{count}} resolvidos", + "stillOpen": "{{count}} ainda aberto", + "stillOpen_plural": "{{count}} ainda abertos", + "newIssue": "{{count}} novo problema", + "newIssue_plural": "{{count}} novos problemas", + "reviewFailed": "Revisão Falhou", + "externalReviewDetected": "Revisão Externa Detectada", + "reviewStartedExternally": "Esta revisão foi iniciada de outra sessão", + "description": "Descrição", + "noDescription": "Nenhuma descrição fornecida.", + "followupReviewDetails": "Detalhes da Revisão de Acompanhamento", + "aiAnalysisResults": "Resultados da Análise IA", + "cancel": "Cancelar", + "previousReview": "Revisão Anterior ({{count}} achados)", + "findingsPosted": "{{count}} Publicado(s)", + "followupInProgress": "Análise de Acompanhamento em Progresso...", + "severity": { + "critical": "Bloqueante", + "high": "Obrigatório", + "medium": "Recomendado", + "low": "Sugestão", + "criticalDesc": "Deve corrigir", + "highDesc": "Deveria corrigir", + "mediumDesc": "Melhorar qualidade", + "lowDesc": "Considerar" + }, + "category": { + "security": "Segurança", + "logic": "Lógica", + "quality": "Qualidade", + "performance": "Performance", + "style": "Estilo", + "documentation": "Documentação", + "testing": "Testes", + "other": "Outro" + }, + "state": { + "open": "Aberto", + "closed": "Fechado", + "merged": "Merged" + }, + "selectCriticalHigh": "Selecionar Bloqueante/Obrigatório ({{count}})", + "selectAll": "Selecionar Tudo", + "clear": "Limpar", + "noIssuesFound": "Nenhum problema encontrado! O código está bom.", + "allFindingsPosted": "Todos os achados publicados no GitHub", + "findingsPostedCount": "{{count}} achado publicado no GitHub", + "findingsPostedCount_plural": "{{count}} achados publicados no GitHub", + "selectedOfTotal": "{{selected}}/{{total}} selecionados", + "suggestedFix": "Correção sugerida:", + "runAIReviewDesc": "Execute uma revisão IA para analisar este PR", + "newCommitsSinceFollowup": "{{count}} novo commit desde o acompanhamento. Execute outro acompanhamento.", + "newCommitsSinceFollowup_plural": "{{count}} novos commits desde o acompanhamento. Execute outro acompanhamento.", + "allIssuesResolved": "Todos os {{count}} problema resolvido. Este PR pode ser mergeado.", + "allIssuesResolved_plural": "Todos os {{count}} problemas resolvidos. Este PR pode ser mergeado.", + "nonBlockingSuggestions": "{{resolved}} resolvidos. {{suggestions}} sugestão não bloqueante restante.", + "nonBlockingSuggestions_plural": "{{resolved}} resolvidos. {{suggestions}} sugestões não bloqueantes restantes.", + "blockingIssues": "Problemas Bloqueantes", + "blockingIssuesDesc": "{{resolved}} resolvidos, {{unresolved}} problema bloqueante ainda aberto.", + "blockingIssuesDesc_plural": "{{resolved}} resolvidos, {{unresolved}} problemas bloqueantes ainda abertos.", + "newCommitsSinceReview": "{{count}} novo commit desde a revisão. Execute acompanhamento para verificar se os problemas foram resolvidos.", + "newCommitsSinceReview_plural": "{{count}} novos commits desde a revisão. Execute acompanhamento para verificar se os problemas foram resolvidos.", + "noBlockingIssues": "Nenhum problema bloqueante encontrado. Este PR pode ser mergeado.", + "findingsPostedWaiting": "{{count}} achado publicado. Aguardando o contribuidor resolver os problemas.", + "findingsPostedWaiting_plural": "{{count}} achados publicados. Aguardando o contribuidor resolver os problemas.", + "findingsPostedNoBlockers": "{{count}} achado publicado. Nenhum problema bloqueante restante.", + "findingsPostedNoBlockers_plural": "{{count}} achados publicados. Nenhum problema bloqueante restante.", + "needsAttention": "Precisa de Atenção", + "findingsNeedPosting": "{{count}} achado precisa ser publicado no GitHub.", + "findingsNeedPosting_plural": "{{count}} achados precisam ser publicados no GitHub.", + "findingsFoundSelectPost": "{{count}} achado encontrado. Selecione e publique no GitHub.", + "findingsFoundSelectPost_plural": "{{count}} achados encontrados. Selecione e publique no GitHub.", + "reviewLogs": "Logs da Revisão", + "followup": "Acompanhamento", + "initial": "Inicial", + "rerunFollowup": "Reexecutar revisão de acompanhamento", + "retryReview": "Tentar Revisão Novamente", + "rerunReview": "Reexecutar revisão", + "updateBranch": "Atualizar Branch", + "updatingBranch": "Atualizando...", + "branchUpdated": "Branch atualizada", + "branchUpdateFailed": "Falha ao atualizar branch", + "allPRsLoaded": "Todos os PRs carregados", + "maxPRsShown": "Mostrando os primeiros 100 PRs", + "loadMore": "Carregar Mais", + "loadingMore": "Carregando...", + "workflowsAwaitingApproval": "{{count}} Workflow Aguardando Aprovação", + "workflowsAwaitingApproval_plural": "{{count}} Workflows Aguardando Aprovação", + "blockedByWorkflows": "Bloqueado", + "workflowsAwaitingDescription": "Este PR é de um fork e requer aprovação de workflow antes que as verificações de CI possam executar. Aprove os workflows para continuar.", + "viewOnGitHub": "Ver", + "approveWorkflow": "Aprovar", + "approveAllWorkflows": "Aprovar Todos os Workflows", + "postCleanReview": "Publicar Revisão Limpa", + "postingCleanReview": "Publicando...", + "cleanReviewPosted": "Revisão limpa publicada", + "cleanReviewMessageTitle": "## ✅ Revisão de PR Aperant - APROVADO", + "cleanReviewMessageStatus": "**Status:** Todo o código está bom", + "cleanReviewMessageFooter": "*Esta revisão automatizada não encontrou problemas. Gerada pelo Aperant.*", + "failedPostCleanReview": "Falha ao publicar revisão limpa", + "viewErrorDetails": "Ver detalhes", + "hideErrorDetails": "Ocultar detalhes", + "postBlockedStatus": "Publicar Status", + "postingBlockedStatus": "Publicando...", + "blockedStatusPosted": "Status publicado no PR", + "blockedStatusMessageTitle": "## 🤖 Revisão de PR Aperant", + "blockedStatusMessageFooter": "*Esta revisão identificou bloqueios que devem ser resolvidos antes do merge. Gerada pelo Aperant.*", + "failedPostBlockedStatus": "Falha ao publicar status", + "branchSynced": "Branch sincronizada ({{count}} commit da base)", + "branchSynced_plural": "Branch sincronizada ({{count}} commits da base)", + "newCommitsOverlap": "{{count}} novo commit ({{files}} arquivo(s) de achados modificado(s))", + "newCommitsOverlap_plural": "{{count}} novos commits ({{files}} arquivo(s) de achados modificado(s))", + "newCommitsNoOverlap": "{{count}} novo commit (sem sobreposição com achados)", + "newCommitsNoOverlap_plural": "{{count}} novos commits (sem sobreposição com achados)", + "verifyChanges": "Verificar Alterações", + "verifyAnyway": "Verificar", + "runFollowupAnyway": "Executar verificação de acompanhamento mesmo sem sobreposição de arquivos", + "disputed": "Contestado", + "disputedByValidator": "Contestado pelo Validador ({{count}})", + "crossValidatedBy": "Confirmado por {{count}} agentes", + "disputedSectionHint": "Estes achados foram reportados por especialistas mas contestados pelo validador. Você ainda pode selecioná-los e publicá-los.", + "logs": { + "agentActivity": "Atividade do Agente", + "showMore": "Mostrar mais {{count}}", + "hideMore": "Ocultar mais {{count}}" + } + }, + "downloads": { + "toggleExpand": "Alternar detalhes de download", + "downloading": "Baixando {{count}} modelo", + "downloading_plural": "Baixando {{count}} modelos", + "complete": "{{count}} download completo", + "complete_plural": "{{count}} downloads completos", + "failed": "{{count}} download falhou", + "failed_plural": "{{count}} downloads falharam", + "clearAll": "Limpar todos os downloads completos", + "done": "Concluído", + "failedLabel": "Falhou", + "starting": "Iniciando..." + }, + "insights": { + "suggestedTask": "Tarefa Sugerida", + "creating": "Criando...", + "taskCreated": "Tarefa Criada", + "createTask": "Criar Tarefa", + "chatHistory": "Histórico de Chat", + "archive": "Arquivar", + "unarchive": "Desarquivar", + "archiveSelected": "Arquivar Selecionadas", + "showArchived": "Mostrar Arquivadas", + "hideArchived": "Ocultar Arquivadas", + "bulkDeleteTitle": "Excluir Conversas", + "bulkDeleteDescription": "Tem certeza de que deseja excluir {{count}} conversa(s)? Esta ação não pode ser desfeita.", + "bulkDeleteConfirm": "Excluir {{count}} Conversa(s)", + "noConversations": "Sem conversas", + "archived": "Arquivada", + "conversationsToDelete": "Conversas a excluir", + "archiveConfirmDescription": "Tem certeza de que deseja arquivar as conversas selecionadas?", + "archiveConfirmTitle": "Arquivar Conversas", + "archiveConfirmButton": "Arquivar {{count}} Conversa(s)", + "deleteTitle": "Excluir Conversa", + "deleteDescription": "Tem certeza de que deseja excluir esta conversa? Esta ação não pode ser desfeita.", + "selectMode": "Selecionar", + "exitSelectMode": "Concluído", + "today": "Hoje", + "yesterday": "Ontem", + "daysAgo": "{{count}} dias atrás", + "messageCount": "{{count}} mensagem", + "messageCount_plural": "{{count}} mensagens", + "images": { + "pasteHint": "Cole uma imagem ou captura de tela", + "dropHint": "Solte a imagem aqui", + "screenshotButton": "Anexar captura de tela", + "removeImage": "Remover imagem", + "imageCount": "{{count}} imagem anexada", + "imageCount_plural": "{{count}} imagens anexadas", + "maxImagesReached": "Número máximo de imagens atingido", + "invalidType": "Tipo de arquivo inválido. Use PNG, JPEG, GIF ou WebP.", + "processFailed": "Falha ao processar imagem", + "dragOver": "Solte a imagem para anexar", + "analysisUnsupported": "Nota: Análise de imagem ainda não é suportada. Imagens são armazenadas para referência mas não podem ser analisadas pelo modelo.", + "screenshotTooLarge": "A captura de tela é muito grande ({{size}}MB). Tamanho máximo é {{max}}MB. Considere capturar uma área menor.", + "notAnalyzed": "Imagens foram armazenadas para referência mas não analisadas pelo modelo." + } + }, + "ideation": { + "converting": "Convertendo...", + "convertToTask": "Converter em Tarefa Auto-Build", + "dismissIdea": "Dispensar Ideia", + "description": "Descrição", + "rationale": "Justificativa", + "goToTask": "Ir para Tarefa", + "conversionFailed": "Conversão falhou", + "conversionFailedDescription": "Falha ao converter ideia em tarefa", + "conversionError": "Erro de conversão", + "conversionErrorDescription": "Ocorreu um erro ao converter a ideia" + }, + "issues": { + "loadingMore": "Carregando mais...", + "scrollForMore": "Role para mais", + "allLoaded": "Todas as issues carregadas" + }, + "usage": { + "dataUnavailable": "Dados de uso indisponíveis", + "dataUnavailableDescription": "O endpoint de monitoramento de uso deste provedor não está disponível ou não é suportado.", + "activeAccount": "Conta Ativa", + "usageAlert": "Alerta de Uso", + "accountExceedsThreshold": "O uso da conta excede o limite de 90%", + "authentication": "Autenticação", + "authenticationAriaLabel": "Autenticação: {{provider}}", + "authenticationDetails": "Detalhes de Autenticação", + "apiProfile": "Perfil de API", + "apiKey": "Chave de API", + "oauth": "OAuth", + "codex": "Codex", + "codexSubscription": "Assinatura Codex", + "claudeCode": "Claude Code", + "claudeCodeSubscription": "Assinatura Claude Code", + "subscription": "Assinatura", + "provider": "Provedor", + "providerAnthropic": "Anthropic", + "providerZai": "Z.AI", + "providerZhipu": "ZHIPU AI", + "crossProvider": "Multi-Provedor", + "crossProviderConfig": "Multi-Provedor", + "crossProviderUsage": "Uso Multi-Provedor", + "crossProviderActive": "Multi-Provedor Ativo", + "providerOpenRouter": "OpenRouter", + "providerUnknown": "Desconhecido", + "providerOpenAI": "OpenAI", + "providerGoogle": "Google AI", + "providerMistral": "Mistral", + "providerGroq": "Groq", + "providerXai": "xAI", + "providerBedrock": "AWS Bedrock", + "providerAzure": "Azure OpenAI", + "providerOllama": "Ollama", + "providerCustomEndpoint": "Endpoint Personalizado", + "billingSubscription": "Assinatura", + "billingPayPerUse": "Pagar por uso", + "unlimited": "Ilimitado", + "unlimitedApiKey": "Ilimitado (Chave de API)", + "noUsageMonitoring": "Monitoramento de uso não disponível para este provedor", + "subscriptionBadge": "Assinatura", + "subscriptionLimitsApply": "Limites de uso aplicáveis", + "subscriptionMonitoringComingSoon": "Esta conta de assinatura tem limites de uso, mas o monitoramento de uso ainda não está disponível para este provedor.", + "queuePosition": "Posição na Fila", + "inUse": "Em Uso", + "noAccount": "Sem Conta", + "noAccountDescription": "Adicione uma conta em Configurações para começar", + "accountName": "Conta", + "profile": "Perfil", + "id": "ID", + "created": "Criado em", + "apiEndpoint": "Endpoint da API", + "sessionQuota": "Cota de Sessão", + "notAvailable": "N/D", + "usageStatusAriaLabel": "Status de uso", + "usageBreakdown": "Detalhamento de Uso", + "used": "usado", + "loading": "Carregando...", + "sessionDefault": "Sessão", + "weeklyDefault": "Semanal", + "resetsInHours": "Reseta em {{hours}}h {{minutes}}m", + "resetsInDays": "Reseta em {{days}}d {{hours}}h", + "window5Hour": "Janela de 5 horas", + "window7Day": "Janela de 7 dias", + "window5HoursQuota": "Cota de 5 Horas", + "windowMonthlyToolsQuota": "Cota Mensal de Ferramentas", + "otherAccounts": "Outras Contas", + "next": "Próxima", + "weeklyLimitReached": "Limite semanal atingido", + "sessionLimitReached": "Limite de sessão atingido", + "notAuthenticated": "Não autenticado", + "needsReauth": "Precisa reautenticar", + "reauthRequired": "Reautenticação necessária", + "reauthRequiredDescription": "Sua sessão expirou. Reautentique para ver o uso e continuar usando esta conta.", + "reauthButton": "Reautenticar", + "clickToOpenSettings": "Clique para abrir Configurações →", + "sessionShort": "Uso de sessão de 5 horas", + "weeklyShort": "Uso semanal de 7 dias", + "swap": "Trocar" + }, + "oauth": { + "enterCode": "Entrada Manual de Código (Alternativa)", + "enterCodeDescription": "Este diálogo só é necessário se o navegador não redirecionou automaticamente. Se a autenticação já foi completada no seu navegador, você pode fechar este diálogo.", + "fallbackNote": "Use isso apenas se você vir uma página \"Cole isto no Claude Code\" no seu navegador.", + "step1": "Complete a autorização no seu navegador", + "step2": "Se você vir uma página com código, copie o código mostrado", + "step3": "Cole o código abaixo e clique em Enviar", + "codeLabel": "Código de Autorização", + "codePlaceholder": "Cole seu código aqui (apenas se necessário)...", + "codeHint": "O código é uma string longa mostrada apenas se o redirecionamento automático falhou", + "submit": "Enviar", + "submitting": "Enviando...", + "codeSubmitted": "Código Enviado", + "codeSubmittedDescription": "A autenticação deve ser concluída em breve. Verifique o terminal para confirmação.", + "codeSubmitFailed": "Falha ao Enviar Código", + "codeSubmitFailedDescription": "Por favor, tente novamente ou copie o código manualmente para o terminal.", + "authenticateTitle": "Autenticar com o Claude", + "authenticateDescription": "O Aperant requer autenticação do Claude AI para funcionalidades como geração de Roadmap, automação de Tarefas e Ideação.", + "authenticateTerminalInfo": "Isso abrirá um terminal com o CLI do Claude onde você pode autenticar. Suas credenciais são armazenadas de forma segura e são válidas por 1 ano.", + "completeAuthTitle": "Completar Autenticação", + "terminalOpened": "Uma janela de terminal foi aberta com o CLI do Claude.", + "completeStepsTitle": "Complete estes passos no terminal:", + "stepTypeLogin": "Digite /login e pressione Enter", + "stepBrowserOpen": "Seu navegador abrirá para autenticação do Claude", + "stepCompleteOAuth": "Complete o fluxo OAuth no seu navegador", + "stepReturnAndVerify": "Retorne aqui e clique em Verificar Autenticação", + "verifyAuth": "Verificar Autenticação", + "verifyingAuth": "Verificando Autenticação...", + "checkingCredentials": "Verificando suas credenciais do Claude.", + "successTitle": "Autenticado com Sucesso!", + "connectedAs": "Conectado como {{email}}", + "credentialsSaved": "Suas credenciais do Claude foram salvas", + "canUseFeatures": "Agora você pode usar todas as funcionalidades de IA do Aperant", + "authFailed": "Autenticação Falhou", + "skipForNow": "Pular por enquanto", + "manualTokenEntry": "Entrada Manual de Token", + "tokenCommandHint": "Execute claude setup-token para obter seu token", + "emailOptionalPlaceholder": "Email (opcional, para exibição)", + "saveToken": "Salvar Token", + "accountNamePlaceholder": "Nome da conta (ex.: Trabalho, Pessoal)", + "hasAuthenticatedAccount": "Você tem pelo menos uma conta Claude autenticada. Você pode continuar para o próximo passo.", + "authNotDetected": "Autenticação não detectada. Por favor, complete /login no terminal primeiro.", + "noProfileSelected": "Nenhum perfil selecionado para verificação", + "alerts": { + "profileCreatedAuthFailed": "Perfil criado, mas falha ao iniciar autenticação: {{error}}", + "authPrepareFailed": "Falha ao preparar autenticação: {{error}}", + "authStartFailedMessage": "Falha ao iniciar autenticação. Por favor, tente novamente." + }, + "badges": { + "default": "Padrão", + "active": "Ativo", + "authenticated": "Autenticado", + "needsAuth": "Precisa Auth" + }, + "buttons": { + "authenticate": "Autenticar", + "setActive": "Definir como Ativo", + "back": "Voltar", + "skip": "Pular", + "continue": "Continuar" + }, + "toast": { + "tokenSaved": "Token Salvo", + "tokenSavedDescription": "Seu token do Claude foi salvo de forma segura.", + "tokenSaveFailed": "Falha ao Salvar Token", + "addProfileFailed": "Falha ao Adicionar Perfil", + "tryAgain": "Por favor, tente novamente." + }, + "configureTitle": "Configurar Contas do Claude", + "addAccountsDesc": "Adicione e autentique suas contas do Claude para usar funcionalidades de IA.", + "multiAccountInfo": "Você pode adicionar múltiplas contas Claude. A conta ativa será usada para funcionalidades de IA. Você pode trocar de conta a qualquer momento.", + "keychainTitle": "Armazenamento Seguro", + "keychainDescription": "Seus tokens de autenticação são armazenados de forma segura no Keychain do macOS.", + "noAccountsYet": "Nenhuma conta adicionada ainda. Adicione sua primeira conta Claude abaixo." + }, + "authTerminal": { + "failedToCreate": "Falha ao criar terminal", + "unknownError": "Erro desconhecido", + "instructionTitle": "Autenticação do Claude", + "step1": "Pressione Enter para iniciar a autenticação", + "step2": "Complete a autenticação no seu navegador", + "step3": "Retorne aqui - a auth será detectada automaticamente", + "authFailed": "Autenticação falhou", + "connecting": "Conectando...", + "authenticate": "Autenticar: {{profileName}}", + "authenticatedAs": "Autenticado como {{email}}", + "authenticated": "Autenticado!", + "authError": "Erro de Autenticação", + "successMessage": "Autenticação bem-sucedida! Fechando..." + }, + "profileCreated": { + "title": "Perfil \"{{profileName}}\" foi criado.", + "instructions": "Para autenticar este perfil:", + "step1": "Vá para Configurações > Integrações", + "step2": "Encontre o perfil na seção Contas do Claude", + "step3": "Clique em \"Autenticar\" para completar o login", + "footer": "A conta estará disponível assim que você completar a autenticação." + }, + "roadmap": { + "emptyTitle": "Nenhum Roadmap Ainda", + "emptyDescription": "Gere um roadmap com IA que entende o público-alvo do seu projeto e cria um plano estratégico de funcionalidades.", + "generateButton": "Gerar Roadmap", + "taskCompleted": "Concluída", + "taskDeleted": "Excluída", + "taskArchived": "Arquivada", + "showMoreFeatures": "Mostrar mais {{count}} funcionalidade", + "showMoreFeatures_plural": "Mostrar mais {{count}} funcionalidades", + "showLessFeatures": "Mostrar menos", + "archiveFeature": "Arquivar", + "archiveFeatureConfirmTitle": "Arquivar Funcionalidade?", + "archiveFeatureConfirmDescription": "Isso removerá \"{{title}}\" do seu roadmap.", + "goToTask": "Ir para Tarefa", + "convertToTask": "Converter em Tarefa Auto-Build", + "build": "Construir", + "task": "Tarefa", + "viewTask": "Ver Tarefa", + "status": { + "underReview": "Em Revisão", + "planned": "Planejado", + "inProgress": "Em Progresso", + "done": "Concluído" + }, + "priority": { + "mustHave": "Essencial", + "shouldHave": "Importante", + "couldHave": "Desejável", + "wontHave": "Não Incluído" + }, + "complexity": { + "low": "Baixa", + "medium": "Média", + "high": "Alta" + }, + "featureDetail": { + "description": "Descrição", + "rationale": "Justificativa", + "complexity": "Complexidade", + "impact": "Impacto", + "dependencies": "Dependências", + "userStories": "Histórias de Usuário", + "acceptanceCriteria": "Critérios de Aceite", + "competitorInsights": "Pontos Fracos da Concorrência", + "deleteTitle": "Excluir Funcionalidade?", + "deleteConfirmMessage": "Isso removerá permanentemente \"{{title}}\" do seu roadmap.", + "delete": "Excluir", + "cancel": "Cancelar", + "severityLabel": "Severidade {{severity}}" + }, + "impact": { + "low": "Baixo", + "medium": "Médio", + "high": "Alto", + "label": "Impacto {{impact}}" + }, + "tabs": { + "kanban": "Kanban", + "phases": "Fases", + "allFeatures": "Todas as Funcionalidades", + "byPriority": "Por Prioridade" + }, + "kanban": { + "dropHere": "Solte aqui", + "noFeatures": "Sem funcionalidades", + "dragFeaturesHere": "Arraste funcionalidades para cá" + }, + "insight": "Insight", + "featuresCount": "{{count}} funcionalidade", + "featuresCount_plural": "{{count}} funcionalidades", + "phaseLabel": "Fase: {{phase}}", + "competitorInsight": { + "badge": "Insight Competitivo", + "tooltip": "Esta funcionalidade aborda pontos fracos da concorrência" + }, + "votesFromFeedback": "{{count}} votos do feedback de usuários", + "externalSource": "Externo", + "importedFrom": "Importado de {{provider}}", + "unknownStatus": "Status Desconhecido" + }, + "roadmapGeneration": { + "progress": "Progresso", + "elapsed": "Decorrido: {{time}}", + "stillWorking": "Ainda trabalhando...", + "stopping": "Parando...", + "stop": "Parar", + "stopTooltip": "Parar geração", + "phases": { + "analyzing": { + "label": "Analisando", + "description": "Analisando estrutura e código do projeto..." + }, + "discovering": { + "label": "Descobrindo", + "description": "Descobrindo público-alvo e necessidades dos usuários..." + }, + "generating": { + "label": "Gerando", + "description": "Gerando roadmap de funcionalidades..." + }, + "complete": { + "label": "Completo", + "description": "Geração do roadmap completa!" + }, + "error": { + "label": "Erro", + "description": "Geração falhou" + } + }, + "steps": { + "analyze": "Analisar", + "discover": "Descobrir", + "generate": "Gerar" + } + }, + "auth": { + "failure": { + "title": "Autenticação Necessária", + "profileLabel": "Perfil", + "unknownProfile": "Perfil Desconhecido", + "tokenExpired": "Seu token de autenticação expirou.", + "tokenInvalid": "Seu token de autenticação é inválido.", + "tokenMissing": "Nenhum token de autenticação encontrado.", + "authFailed": "Autenticação falhou.", + "description": "Por favor, reautentique seu perfil do Claude para continuar usando o Aperant.", + "taskAffected": "Tarefa afetada", + "technicalDetails": "Detalhes técnicos", + "goToSettings": "Ir para Configurações" + } + }, + "git": { + "branchGroups": { + "local": "Branches Locais", + "remote": "Branches Remotas" + }, + "branchType": { + "local": "Local", + "remote": "Remota" + } + }, + "githubErrors": { + "rateLimitTitle": "Limite de Uso do GitHub Atingido", + "authTitle": "Autenticação do GitHub Necessária", + "permissionTitle": "Permissão do GitHub Negada", + "notFoundTitle": "Recurso do GitHub Não Encontrado", + "networkTitle": "Erro de Conexão com o GitHub", + "unknownTitle": "Erro do GitHub", + "rateLimitMessage": "Limite de uso da API do GitHub atingido. Por favor, aguarde um momento antes de tentar novamente.", + "rateLimitMessageMinutes": "Limite de uso da API do GitHub atingido. Por favor, aguarde {{minutes}} minuto(s) antes de tentar novamente.", + "rateLimitMessageHours": "Limite de uso da API do GitHub atingido. O limite reseta em aproximadamente {{hours}} hora(s).", + "authMessage": "Autenticação do GitHub falhou. Por favor, verifique seu token do GitHub em Configurações e tente novamente.", + "permissionMessage": "Permissão do GitHub negada. Seu token pode não ter o acesso necessário. Por favor, verifique as permissões do seu token em Configurações.", + "permissionMessageScopes": "Permissão do GitHub negada. Seu token está sem os escopos necessários: {{scopes}}. Por favor, atualize seu token do GitHub em Configurações.", + "notFoundMessage": "O recurso do GitHub solicitado não foi encontrado. Por favor, verifique se o repositório existe e você tem acesso a ele.", + "networkMessage": "Não foi possível conectar ao GitHub. Por favor, verifique sua conexão com a internet e tente novamente.", + "unknownMessage": "Ocorreu um erro inesperado ao comunicar com o GitHub. Por favor, tente novamente.", + "resetsIn": "Reseta em {{time}}", + "countdownHoursMinutes": "{{hours}}h {{minutes}}m", + "countdownMinutesSeconds": "{{minutes}}m {{seconds}}s", + "rateLimitExpired": "O limite de uso foi resetado. Você pode tentar novamente.", + "requiredScopes": "Escopos necessários" + }, + "roadmapProgress": { + "elapsedTime": "Decorrido", + "lastActivity": "Última atividade", + "staleWarning": "Sem atividade há algum tempo", + "staleWarningTooltip": "Esta tarefa não teve atividade por {{minutes}} minutos", + "phases": { + "analyzing": { + "label": "Analisando", + "description": "Analisando estrutura e código do projeto..." + }, + "discovering": { + "label": "Descobrindo", + "description": "Descobrindo público-alvo e necessidades dos usuários..." + }, + "generating": { + "label": "Gerando", + "description": "Gerando roadmap de funcionalidades..." + }, + "complete": { + "label": "Completo", + "description": "Geração do roadmap completa!" + }, + "error": { + "label": "Erro", + "description": "Geração falhou" + } + }, + "steps": { + "analyze": "Analisar", + "discover": "Descobrir", + "generate": "Gerar" + }, + "processing": "Processando", + "processActiveTooltip": "Processo está executando ativamente", + "stopGeneration": "Parar geração", + "stopping": "Parando...", + "progress": "Progresso", + "lastActivityPrefix": "última atividade", + "lastProgressUpdateTooltip": "Última atualização de progresso recebida" + }, + "memory": { + "types": { + "gotcha": "Pegadinha", + "decision": "Decisão", + "preference": "Preferência", + "pattern": "Padrão", + "requirement": "Requisito", + "error_pattern": "Padrão de Erro", + "module_insight": "Insight de Módulo", + "prefetch_pattern": "Padrão de Prefetch", + "work_state": "Estado de Trabalho", + "causal_dependency": "Dependência Causal", + "task_calibration": "Calibração de Tarefa", + "e2e_observation": "Observação E2E", + "dead_end": "Beco sem Saída", + "work_unit_outcome": "Resultado da Unidade de Trabalho", + "workflow_recipe": "Receita de Workflow", + "context_cost": "Custo de Contexto" + }, + "filters": { + "all": "Todos", + "patterns": "Padrões", + "errors": "Erros e Pegadinhas", + "decisions": "Decisões", + "insights": "Insights de Código", + "calibration": "Calibração" + }, + "badges": { + "needsReview": "Precisa Revisão", + "verified": "Verificado", + "pinned": "Fixado", + "confidence": "Confiança" + }, + "sources": { + "agent_explicit": "Agente", + "observer_inferred": "Observador", + "qa_auto": "QA", + "mcp_auto": "MCP", + "commit_auto": "Commit", + "user_taught": "Usuário" + }, + "health": { + "totalMemories": "Total de Memórias", + "avgConfidence": "Confiança Média", + "verified": "Verificadas" + }, + "info": { + "database": "Banco de Dados", + "path": "Caminho", + "embedding": "Embedding", + "memories": "Memórias" + }, + "status": { + "title": "Status da Memória", + "connected": "Conectado", + "notAvailable": "Não Disponível", + "notConfigured": "Sistema de memória não configurado", + "enableInSettings": "Para habilitar a memória, configure nas configurações do projeto." + }, + "search": { + "title": "Buscar Memórias", + "placeholder": "Buscar memórias...", + "resultsCount": "{{count}} resultado encontrado", + "resultsCount_plural": "{{count}} resultados encontrados" + }, + "browser": { + "title": "Explorador de Memória", + "countOf": "{{filtered}} de {{total}} memórias" + }, + "empty": "Sem memórias ainda. Memórias são criadas automaticamente conforme os agentes trabalham nas tarefas.", + "emptyFilter": "Nenhuma memória corresponde ao filtro selecionado.", + "showAll": "Mostrar todas as memórias", + "expand": "Expandir", + "collapse": "Recolher", + "sections": { + "whatWorked": "O Que Funcionou", + "whatFailed": "O Que Falhou", + "approach": "Abordagem", + "recommendations": "Recomendações", + "patterns": "Padrões", + "gotchas": "Pegadinhas", + "changedFiles": "Arquivos Alterados", + "fileInsights": "Insights de Arquivos", + "subtasksCompleted": "Subtarefas Concluídas", + "relatedFiles": "Arquivos Relacionados", + "tags": "Tags", + "approachTried": "Abordagem Tentada", + "whyItFailed": "Por Que Falhou", + "alternativeUsed": "Alternativa Usada", + "steps": "Passos" + }, + "actions": { + "verify": "Verificar", + "pin": "Fixar", + "unpin": "Desfixar", + "deprecate": "Remover" + } + }, + "context": { + "tabs": { + "projectIndex": "Índice do Projeto", + "memories": "Memórias" + } + }, + "changelog": { + "tasksSelected": "{{selected}} de {{total}} tarefas selecionadas", + "selectAll": "Selecionar Tudo", + "clear": "Limpar", + "noCompletedTasks": "Sem Tarefas Concluídas", + "noCompletedTasksHint": "Conclua tarefas no quadro Kanban e marque como \"Concluído\" para incluí-las no seu changelog.", + "loadingCommits": "Carregando commits...", + "noCommitsFound": "Nenhum Commit Encontrado", + "configureHistoryHint": "Configure as opções de histórico e clique em \"Carregar Commits\" para visualizar.", + "selectBranchesHint": "Selecione ambas as branches e clique em \"Carregar Commits\" para ver as alterações.", + "continue": "Continuar", + "commitsFound": "{{count}} commit encontrado", + "commitsFound_plural": "{{count}} commits encontrados", + "task": "{{count}} tarefa", + "task_plural": "{{count}} tarefas", + "commit": "{{count}} commit", + "commit_plural": "{{count}} commits", + "item": "{{count}} item", + "item_plural": "{{count}} itens" + }, + "prStatus": { + "ci": { + "success": "CI Aprovado", + "pending": "CI Pendente", + "failure": "CI Falhou", + "successTooltip": "Todas as verificações de CI passaram", + "pendingTooltip": "Verificações de CI ainda estão executando", + "failureTooltip": "Uma ou mais verificações de CI falharam" + }, + "review": { + "approved": "Aprovado", + "changesRequested": "Alterações Solicitadas", + "pending": "Revisão Pendente", + "approvedTooltip": "Este PR foi aprovado", + "changesRequestedTooltip": "Alterações foram solicitadas neste PR", + "pendingTooltip": "Aguardando revisão" + }, + "merge": { + "ready": "Pronto para Merge", + "blocked": "Merge Bloqueado", + "conflict": "Tem Conflitos", + "readyTooltip": "Este PR está pronto para merge", + "blockedTooltip": "Este PR não pode ser mergeado devido a condições bloqueantes", + "conflictTooltip": "Este PR tem conflitos de merge que precisam ser resolvidos" + } + } +} diff --git a/apps/desktop/src/shared/i18n/locales/pt-BR/dialogs.json b/apps/desktop/src/shared/i18n/locales/pt-BR/dialogs.json new file mode 100644 index 0000000000..bd365c37f6 --- /dev/null +++ b/apps/desktop/src/shared/i18n/locales/pt-BR/dialogs.json @@ -0,0 +1,252 @@ +{ + "initialize": { + "title": "Inicializar Aperant", + "description": "Este projeto não tem o Aperant inicializado. Gostaria de configurá-lo agora?", + "willDo": "Isso irá:", + "createFolder": "Criar uma pasta .auto-claude no seu projeto", + "copyFramework": "Copiar os arquivos do framework Aperant", + "setupSpecs": "Configurar o diretório de specs para suas tarefas", + "sourcePathNotConfigured": "Caminho de origem não configurado", + "sourcePathNotConfiguredDescription": "Por favor, defina o caminho de origem do Aperant nas Configurações do App antes de inicializar.", + "initFailed": "Inicialização Falhou", + "initFailedDescription": "Falha ao inicializar o Aperant. Por favor, tente novamente." + }, + "gitSetup": { + "title": "Repositório Git Necessário", + "description": "O Aperant usa git para construir funcionalidades com segurança em espaços de trabalho isolados", + "notGitRepo": "Esta pasta não é um repositório git", + "noCommits": "O repositório git não tem commits", + "needsInit": "O Git precisa ser inicializado antes que o Aperant possa gerenciar seu código.", + "needsCommit": "Pelo menos um commit é necessário para que o Aperant possa criar worktrees.", + "willSetup": "Vamos configurar o git para você:", + "initRepo": "Inicializar um novo repositório git", + "createCommit": "Criar um commit inicial com seus arquivos atuais", + "manual": "Prefere fazer manualmente?", + "settingUp": "Configurando o Git", + "initializingRepo": "Inicializando repositório git e criando commit inicial...", + "success": "Git Inicializado", + "readyToUse": "Seu projeto está pronto para usar com o Aperant!" + }, + "githubSetup": { + "connectTitle": "Conectar ao GitHub", + "connectDescription": "O Aperant requer GitHub para gerenciar as branches do seu código e manter as tarefas atualizadas.", + "claudeTitle": "Conectar ao Claude AI", + "claudeDescription": "O Aperant usa Claude AI para funcionalidades inteligentes como geração de Roadmap, automação de Tarefas e Ideação.", + "aiProviderTitle": "Conectar à IA", + "aiProviderDescription": "Adicione uma conta de provedor de IA para alimentar funcionalidades como geração de Roadmap, automação de Tarefas e Ideação.", + "aiProviderReady": "Você tem pelo menos um provedor de IA configurado. Você pode continuar para o próximo passo.", + "skipForNow": "Pular por enquanto", + "continue": "Continuar", + "selectRepo": "Selecionar Repositório", + "repoDescription": "O Aperant usará este repositório para gerenciar branches de tarefas e manter seu código atualizado.", + "selectBranch": "Selecionar Branch Base", + "branchDescription": "Escolha qual branch o Aperant deve usar como base para criar branches de tarefas.", + "whyBranch": "Por que selecionar uma branch?", + "branchExplanation": "O Aperant cria espaços de trabalho isolados para cada tarefa. Selecionar a branch base correta garante que suas tarefas comecem com o código mais recente da sua linha de desenvolvimento principal.", + "ready": "O Aperant está pronto para usar! Agora você pode criar tarefas que serão automaticamente baseadas na branch {{branchName}}.", + "createRepoAriaLabel": "Criar novo repositório no GitHub", + "linkRepoAriaLabel": "Vincular a repositório existente", + "goBackAriaLabel": "Voltar para seleção de repositório", + "selectOwnerAriaLabel": "Selecionar {{owner}} como proprietário do repositório", + "selectOrgAriaLabel": "Selecionar {{org}} como proprietário do repositório", + "selectVisibilityAriaLabel": "Definir visibilidade do repositório como {{visibility}}" + }, + "worktrees": { + "title": "Worktrees", + "description": "Gerencie espaços de trabalho isolados para suas tarefas do Aperant", + "empty": "Sem Worktrees", + "emptyDescription": "Worktrees são criadas automaticamente quando o Aperant constrói funcionalidades. Elas fornecem espaços de trabalho isolados para cada tarefa.", + "merge": "Fazer Merge da Worktree", + "mergeDescription": "Fazer merge das alterações desta worktree na branch base.", + "delete": "Excluir Worktree?", + "deleteDescription": "Isso excluirá permanentemente a worktree e todas as alterações não commitadas. Esta ação não pode ser desfeita.", + "bulkDeleteTitle": "Excluir {{count}} Worktrees?", + "bulkDeleteDescription": "Isso excluirá permanentemente as worktrees selecionadas e todas as suas alterações não commitadas. Esta ação não pode ser desfeita.", + "deleting": "Excluindo...", + "deleteSelected": "Excluir Selecionadas", + "selectProject": "Selecione um projeto para ver as worktrees", + "filesChanged": "{{count}} arquivos alterados", + "commitsAhead": "{{count}} commits à frente", + "mergeTo": "Merge para {{branch}}", + "copyPath": "Copiar Caminho", + "createdAt": "Criada em {{date}}", + "sourceBranch": "Branch de Origem", + "targetBranch": "Branch de Destino", + "changes": "Alterações", + "changesSummary": "{{commits}} commits, {{files}} arquivos", + "mergeSuccessful": "Merge Realizado", + "mergeFailed": "Merge Falhou", + "conflictingFiles": "Arquivos em conflito:" + }, + "worktreeCleanup": { + "title": "Concluir Tarefa", + "hasWorktree": "A tarefa \"{{taskTitle}}\" ainda tem um espaço de trabalho isolado (worktree).", + "willDelete": "Para marcar esta tarefa como concluída, a worktree e sua branch associada serão excluídas.", + "warning": "Certifique-se de ter mergeado ou salvo quaisquer alterações que deseja manter antes de prosseguir.", + "confirm": "Excluir Worktree e Concluir", + "completing": "Concluindo...", + "retry": "Tentar Novamente", + "errorTitle": "Limpeza Falhou", + "errorDescription": "Falha ao limpar a worktree. Por favor, tente novamente." + }, + "update": { + "title": "Aperant", + "projectInitialized": "Projeto está inicializado." + }, + "addFeature": { + "title": "Adicionar Funcionalidade", + "description": "Adicione uma nova funcionalidade ao seu roadmap. Forneça detalhes sobre o que você quer construir e como ela se encaixa na sua estratégia de produto.", + "featureTitle": "Título da Funcionalidade", + "featureTitlePlaceholder": "ex.: Autenticação de Usuário, Suporte a Modo Escuro", + "featureDescription": "Descrição", + "featureDescriptionPlaceholder": "Descreva o que esta funcionalidade faz e por que é valiosa para os usuários.", + "rationale": "Justificativa", + "optional": "opcional", + "rationalePlaceholder": "Explique por que esta funcionalidade deve ser construída e como ela se encaixa na visão do produto.", + "phase": "Fase", + "selectPhase": "Selecionar fase", + "priority": "Prioridade", + "selectPriority": "Selecionar prioridade", + "complexity": "Complexidade", + "selectComplexity": "Selecionar complexidade", + "impact": "Impacto", + "selectImpact": "Selecionar impacto", + "lowComplexity": "Baixa", + "mediumComplexity": "Média", + "highComplexity": "Alta", + "lowImpact": "Baixo Impacto", + "mediumImpact": "Médio Impacto", + "highImpact": "Alto Impacto", + "titleRequired": "O título é obrigatório", + "descriptionRequired": "A descrição é obrigatória", + "phaseRequired": "Por favor, selecione uma fase", + "cancel": "Cancelar", + "adding": "Adicionando...", + "addFeature": "Adicionar Funcionalidade", + "failedToAdd": "Falha ao adicionar funcionalidade. Por favor, tente novamente." + }, + "addProject": { + "title": "Adicionar Projeto", + "description": "Escolha como gostaria de adicionar um projeto", + "openExisting": "Abrir Pasta Existente", + "openExistingDescription": "Navegue até um projeto existente no seu computador", + "createNew": "Criar Novo Projeto", + "createNewDescription": "Comece do zero com uma nova pasta de projeto", + "createNewTitle": "Criar Novo Projeto", + "createNewSubtitle": "Configure uma nova pasta de projeto", + "projectName": "Nome do Projeto", + "projectNamePlaceholder": "meu-projeto-incrivel", + "projectNameHelp": "Este será o nome da pasta. Use letras minúsculas com hifens.", + "location": "Localização", + "locationPlaceholder": "Selecione uma pasta...", + "willCreate": "Criará:", + "browse": "Procurar", + "initGit": "Inicializar repositório git", + "back": "Voltar", + "creating": "Criando...", + "createProject": "Criar Projeto", + "nameRequired": "Por favor, insira um nome para o projeto", + "locationRequired": "Por favor, selecione uma localização", + "failedToOpen": "Falha ao abrir projeto", + "failedToCreate": "Falha ao criar projeto", + "openExistingAriaLabel": "Abrir pasta de projeto existente", + "createNewAriaLabel": "Criar novo projeto" + }, + "customModel": { + "title": "Configuração de Modelo Personalizado", + "description": "Configure o modelo e o nível de raciocínio para esta sessão de chat.", + "model": "Modelo", + "thinkingLevel": "Nível de Raciocínio", + "cancel": "Cancelar", + "apply": "Aplicar" + }, + "removeProject": { + "title": "Remover Projeto?", + "description": "Isso removerá \"{{projectName}}\" do aplicativo. Seus arquivos serão preservados no disco e você pode readicionar o projeto depois.", + "cancel": "Cancelar", + "remove": "Remover", + "error": "Falha ao remover projeto" + }, + "appUpdate": { + "title": "Atualização do App Disponível", + "description": "Uma nova versão do Aperant está pronta para download", + "newVersion": "Nova Versão", + "released": "Lançada em", + "downloading": "Baixando...", + "downloadUpdate": "Baixar Atualização", + "installAndRestart": "Instalar e Reiniciar", + "installLater": "Instalar Depois", + "remindMeLater": "Lembrar Depois", + "updateDownloaded": "Atualização baixada com sucesso! Clique em Instalar para reiniciar e aplicar a atualização.", + "downloadError": "Falha ao baixar atualização", + "claudeCodeChangelog": "Ver Changelog do Claude Code", + "claudeCodeChangelogAriaLabel": "Ver Changelog do Claude Code (abre em nova janela)", + "readOnlyVolumeTitle": "Não é possível instalar a partir da imagem de disco", + "readOnlyVolumeDescription": "Por favor, mova o Aperant para a pasta Aplicativos antes de atualizar." + }, + "addCompetitor": { + "title": "Adicionar Concorrente", + "description": "Adicione um concorrente conhecido à sua análise...", + "competitorName": "Nome do Concorrente", + "competitorNamePlaceholder": "ex.: Slack, Notion, Figma", + "competitorUrl": "URL do Site", + "competitorUrlPlaceholder": "ex.: https://exemplo.com", + "competitorDescription": "Descrição", + "competitorDescriptionPlaceholder": "Breve descrição do que este concorrente faz...", + "relevance": "Relevância", + "selectRelevance": "Selecionar relevância", + "highRelevance": "Alta - Concorrente direto", + "mediumRelevance": "Média - Sobreposição parcial", + "lowRelevance": "Baixa - Tangencial", + "nameRequired": "O nome do concorrente é obrigatório", + "urlRequired": "A URL do site é obrigatória", + "invalidUrl": "Por favor, insira uma URL válida", + "optional": "opcional", + "cancel": "Cancelar", + "adding": "Adicionando...", + "addCompetitor": "Adicionar Concorrente", + "failedToAdd": "Falha ao adicionar concorrente" + }, + "competitorAnalysis": { + "title": "Habilitar Análise de Concorrentes?", + "description": "Aprimore seu roadmap com insights de produtos concorrentes", + "whatItDoes": "O que a análise de concorrentes faz:", + "identifiesCompetitors": "Identifica 3-5 concorrentes principais com base no tipo do seu projeto", + "searchesAppStores": "Pesquisa lojas de apps, fóruns e redes sociais por feedback de usuários e pontos de dor", + "suggestsFeatures": "Sugere funcionalidades que abordam lacunas nos produtos concorrentes", + "webSearchesTitle": "Pesquisas na web serão realizadas", + "webSearchesDescription": "Esta funcionalidade realizará pesquisas na web para coletar informações de concorrentes. O nome e tipo do seu projeto serão usados nas consultas de busca. Nenhum código ou dado sensível é compartilhado.", + "optionalInfo": "Você pode gerar um roadmap sem análise de concorrentes se preferir. O roadmap ainda será baseado na estrutura do seu projeto e melhores práticas.", + "skipAnalysis": "Não, Pular Análise", + "enableAnalysis": "Sim, Habilitar Análise", + "knowYourCompetitors": "Já conhece seus concorrentes?", + "addThemDirectly": "Adicione-os diretamente para melhorar a precisão da análise", + "addKnownCompetitors": "Adicionar Concorrentes Conhecidos", + "addKnownCompetitorsDescription": "Adicione manualmente concorrentes que você já conhece à análise existente.", + "competitorsAdded": "{{count}} adicionado(s)" + }, + "existingCompetitorAnalysis": { + "title": "Opções de Análise de Concorrentes", + "description": "Este projeto tem uma análise de concorrentes existente de {{date}}", + "recently": "recentemente", + "useExistingTitle": "Usar análise existente", + "recommended": "(Recomendado)", + "useExistingDescription": "Reutilize os insights de concorrentes que você já tem. Mais rápido e sem pesquisas web adicionais.", + "runNewTitle": "Executar nova análise", + "runNewDescription": "Realize novas pesquisas na web para obter informações atualizadas de concorrentes. Demora mais.", + "skipTitle": "Pular análise de concorrentes", + "skipDescription": "Gerar roadmap sem insights de concorrentes.", + "cancel": "Cancelar" + }, + "versionWarning": { + "title": "Ação Necessária", + "subtitle": "Atualização da Versão 2.7.5", + "description": "Devido a mudanças na autenticação nesta versão, você precisa reautenticar seu perfil do Claude.", + "instructions": "Para reautenticar:", + "step1": "Vá para Configurações", + "step2": "Navegue até Configurações do App > Integrações", + "step3": "Clique em \"Reautenticar\" no seu perfil", + "gotIt": "Entendi", + "goToSettings": "Ir para Configurações" + } +} diff --git a/apps/desktop/src/shared/i18n/locales/pt-BR/errors.json b/apps/desktop/src/shared/i18n/locales/pt-BR/errors.json new file mode 100644 index 0000000000..6679e8bbda --- /dev/null +++ b/apps/desktop/src/shared/i18n/locales/pt-BR/errors.json @@ -0,0 +1,9 @@ +{ + "task": { + "parseImplementationPlan": "Falha ao analisar implementation_plan.json para {{specId}}: {{error}}", + "jsonError": { + "titleSuffix": "(Erro JSON)", + "description": "⚠️ Erro de Parse JSON: {{error}}\n\nO arquivo implementation_plan.json está malformado. Execute a correção automática do backend ou repare o arquivo manualmente." + } + } +} diff --git a/apps/desktop/src/shared/i18n/locales/pt-BR/gitlab.json b/apps/desktop/src/shared/i18n/locales/pt-BR/gitlab.json new file mode 100644 index 0000000000..5bb0545374 --- /dev/null +++ b/apps/desktop/src/shared/i18n/locales/pt-BR/gitlab.json @@ -0,0 +1,208 @@ +{ + "title": "Issues do GitLab", + "states": { + "opened": "Aberta", + "closed": "Fechada" + }, + "complexity": { + "simple": "Simples", + "standard": "Padrão", + "complex": "Complexa" + }, + "header": { + "open": "abertas", + "searchPlaceholder": "Buscar issues..." + }, + "filters": { + "opened": "Abertas", + "closed": "Fechadas", + "all": "Todas" + }, + "empty": { + "noMatch": "Nenhuma issue corresponde à sua busca", + "selectIssue": "Selecione uma issue para ver detalhes" + }, + "notConnected": { + "title": "GitLab Não Conectado", + "description": "Configure seu token e projeto do GitLab nas configurações do projeto para sincronizar issues.", + "openSettings": "Abrir Configurações" + }, + "detail": { + "notes": "notas", + "viewTask": "Ver Tarefa", + "createTask": "Criar Tarefa", + "taskLinked": "Tarefa Vinculada", + "taskId": "ID da Tarefa", + "description": "Descrição", + "noDescription": "Nenhuma descrição fornecida.", + "assignees": "Responsáveis", + "milestone": "Marco" + }, + "investigation": { + "title": "Criar Tarefa a partir da Issue", + "issuePrefix": "Issue", + "description": "Crie uma tarefa a partir desta issue do GitLab. A tarefa será adicionada ao seu quadro Kanban na coluna Backlog.", + "selectNotes": "Selecionar Notas para Incluir", + "deselectAll": "Desmarcar Todas", + "selectAll": "Selecionar Todas", + "willInclude": "A tarefa incluirá:", + "includeTitle": "Título e descrição da issue", + "includeLink": "Link de volta para a issue do GitLab", + "includeLabels": "Labels e metadados da issue", + "noNotes": "Sem notas (esta issue não tem notas)", + "failedToLoadNotes": "Falha ao carregar notas", + "taskCreated": "Tarefa criada! Veja no seu quadro Kanban.", + "creating": "Criando...", + "cancel": "Cancelar", + "done": "Concluído", + "close": "Fechar" + }, + "settings": { + "enableIssues": "Habilitar Issues do GitLab", + "enableIssuesDescription": "Sincronize issues do GitLab e crie tarefas automaticamente", + "instance": "Instância do GitLab", + "instanceDescription": "Use https://gitlab.com ou a URL da sua instância self-hosted", + "connectedVia": "Conectado via CLI do GitLab", + "authenticatedAs": "Autenticado como", + "useDifferentToken": "Usar Token Diferente", + "authentication": "Autenticação do GitLab", + "useManualToken": "Usar Token Manual", + "authenticating": "Autenticando com o CLI do glab...", + "browserWindow": "Uma janela do navegador deve abrir para você fazer login.", + "personalAccessToken": "Token de Acesso Pessoal", + "useOAuth": "Usar OAuth", + "tokenScope": "Crie um token com", + "scopeApi": "api", + "scopeFrom": "escopo em", + "gitlabSettings": "Configurações do GitLab", + "project": "Projeto", + "enterManually": "Inserir Manualmente", + "loadingProjects": "Carregando projetos...", + "selectProject": "Selecione um projeto...", + "searchProjects": "Buscar projetos...", + "noMatchingProjects": "Nenhum projeto correspondente", + "noProjectsFound": "Nenhum projeto encontrado", + "selected": "Selecionado", + "projectFormat": "Formato:", + "projectFormatExample": "(ex.: gitlab-org/gitlab)", + "connectionStatus": "Status da Conexão", + "checking": "Verificando...", + "connectedTo": "Conectado a", + "notConnected": "Não conectado", + "issuesAvailable": "Issues Disponíveis", + "issuesAvailableDescription": "Acesse Issues do GitLab na barra lateral para visualizar, investigar e criar tarefas a partir de issues.", + "defaultBranch": "Branch Padrão", + "defaultBranchDescription": "Branch base para criar worktrees de tarefas", + "loadingBranches": "Carregando branches...", + "autoDetect": "Auto-detectar (main/master)", + "searchBranches": "Buscar branches...", + "noMatchingBranches": "Nenhuma branch correspondente", + "noBranchesFound": "Nenhuma branch encontrada", + "branchFromNote": "Todas as novas tarefas serão criadas a partir de", + "autoSyncOnLoad": "Sincronizar ao Carregar", + "autoSyncDescription": "Buscar issues automaticamente quando o projeto carregar", + "cli": { + "required": "CLI do GitLab Necessário", + "notInstalled": "O CLI do GitLab (glab) é necessário para autenticação OAuth. Instale-o para usar a opção 'Usar OAuth'.", + "installButton": "Instalar glab", + "installing": "Instalando...", + "installSuccess": "Instalação iniciada no seu terminal. Conclua e clique em Atualizar.", + "refresh": "Atualizar", + "learnMore": "Saiba mais", + "installed": "CLI do GitLab instalado:" + } + }, + "mergeRequests": { + "title": "Merge Requests do GitLab", + "newMR": "Novo Merge Request", + "selectMR": "Selecione um merge request para ver detalhes", + "states": { + "opened": "Aberto", + "closed": "Fechado", + "merged": "Merged", + "locked": "Bloqueado" + }, + "filters": { + "opened": "Abertos", + "closed": "Fechados", + "merged": "Merged", + "all": "Todos" + } + }, + "mrReview": { + "runReview": "Executar Revisão IA", + "reviewing": "Revisando...", + "followupReview": "Revisão de Acompanhamento", + "newCommits": "novo commit", + "newCommitsPlural": "novos commits", + "cancel": "Cancelar", + "postFindings": "Publicar Achados", + "posting": "Publicando...", + "postedTo": "Publicado no GitLab", + "approve": "Aprovar", + "approving": "Aprovando...", + "merge": "Fazer Merge do MR", + "merging": "Fazendo merge...", + "aiReviewResult": "Resultado da Revisão IA", + "followupReviewResult": "Revisão de Acompanhamento", + "description": "Descrição", + "noDescription": "Nenhuma descrição fornecida.", + "labels": "Labels", + "status": { + "notReviewed": "Não Revisado", + "notReviewedDesc": "Execute uma revisão IA para analisar este MR", + "reviewComplete": "Revisão Completa", + "reviewCompleteDesc": "achado(s) encontrado(s). Selecione e publique no GitLab.", + "waitingForChanges": "Aguardando Alterações", + "waitingForChangesDesc": "achado(s) publicado(s). Aguardando o contribuidor resolver os problemas.", + "readyToMerge": "Pronto para Merge", + "readyToMergeDesc": "Nenhum problema bloqueante encontrado. Este MR pode ser mergeado.", + "needsAttention": "Precisa de Atenção", + "needsAttentionDesc": "achado(s) precisam ser publicados no GitLab.", + "readyForFollowup": "Pronto para Acompanhamento", + "readyForFollowupDesc": "desde a revisão. Execute um acompanhamento para verificar se os problemas foram resolvidos.", + "blockingIssues": "Problemas Bloqueantes", + "blockingIssuesDesc": "problema(s) bloqueante(s) ainda aberto(s)." + }, + "overallStatus": { + "approve": "Aprovar", + "requestChanges": "Alterações Solicitadas", + "comment": "Comentário" + }, + "resolution": { + "resolved": "resolvido(s)", + "stillOpen": "ainda aberto(s)", + "newIssue": "novo problema", + "newIssues": "novos problemas" + } + }, + "findings": { + "summary": "selecionado(s)", + "selectCriticalHigh": "Selecionar Bloqueante/Obrigatório", + "selectAll": "Selecionar Todos", + "clear": "Limpar", + "noIssues": "Nenhum problema encontrado! O código está bom.", + "suggestedFix": "Correção sugerida:", + "posted": "Publicado", + "severity": { + "critical": "Bloqueante", + "criticalDesc": "Deve corrigir", + "high": "Obrigatório", + "highDesc": "Deveria corrigir", + "medium": "Recomendado", + "mediumDesc": "Melhorar qualidade", + "low": "Sugestão", + "lowDesc": "Considerar" + }, + "category": { + "security": "Segurança", + "quality": "Qualidade", + "style": "Estilo", + "test": "Teste", + "docs": "Documentação", + "pattern": "Padrão", + "performance": "Performance", + "logic": "Lógica" + } + } +} diff --git a/apps/desktop/src/shared/i18n/locales/pt-BR/navigation.json b/apps/desktop/src/shared/i18n/locales/pt-BR/navigation.json new file mode 100644 index 0000000000..72dc5e33c4 --- /dev/null +++ b/apps/desktop/src/shared/i18n/locales/pt-BR/navigation.json @@ -0,0 +1,87 @@ +{ + "sections": { + "project": "Projeto", + "tools": "Ferramentas" + }, + "items": { + "kanban": "Quadro Kanban", + "terminals": "Terminais", + "insights": "Análises", + "roadmap": "Planejamento", + "ideation": "Ideação", + "changelog": "Histórico", + "context": "Contexto", + "githubIssues": "Issues do GitHub", + "githubPRs": "PRs do GitHub", + "gitlabIssues": "Issues do GitLab", + "gitlabMRs": "MRs do GitLab", + "worktrees": "Worktrees", + "agentTools": "MCP" + }, + "actions": { + "settings": "Configurações", + "help": "Ajuda e Feedback", + "newTask": "Nova Tarefa", + "collapseSidebar": "Recolher Barra Lateral", + "expandSidebar": "Expandir Barra Lateral", + "sponsor": "Patrocine-nos" + }, + "tooltips": { + "settings": "Config. do App", + "help": "Ajuda e Feedback" + }, + "messages": { + "initializeToCreateTasks": "Inicialize o Aperant para criar tarefas" + }, + "updateBanner": { + "title": "Atualização Disponível", + "version": "Versão {{version}} está pronta", + "updateAndRestart": "Atualizar e Reiniciar", + "installAndRestart": "Instalar e Reiniciar", + "downloading": "Baixando...", + "dismiss": "Dispensar", + "downloadError": "Falha ao baixar atualização", + "readOnlyVolumeWarning": "Mova para a pasta Aplicativos para atualizar" + }, + "claudeCode": { + "checking": "Verificando Claude Code...", + "upToDate": "Claude Code está atualizado", + "updateAvailable": "Atualização do Claude Code disponível", + "notInstalled": "Claude Code não instalado", + "error": "Erro ao verificar Claude Code", + "installed": "Instalado", + "outdated": "Atualização disponível", + "missing": "Não instalado", + "current": "Atual", + "latest": "Mais recente", + "path": "Caminho", + "lastChecked": "Última verificação", + "learnMore": "Saiba mais sobre o Claude Code", + "learnMoreAriaLabel": "Saiba mais sobre o Claude Code (abre em nova janela)", + "viewChangelog": "Ver Changelog do Claude Code", + "viewChangelogAriaLabel": "Ver Changelog do Claude Code (abre em nova janela)", + "updateWarningTitle": "Atualizar Claude Code?", + "updateWarningDescription": "A atualização fechará todas as sessões do Claude Code em execução. Qualquer trabalho não salvo nessas sessões poderá ser perdido. Certifique-se de salvar seu trabalho antes de prosseguir.", + "updateWarningTerminalNote": "Uma janela de terminal será aberta para executar o comando de instalação. Aguarde a conclusão da instalação antes de continuar.", + "updateAnyway": "Abrir Terminal e Atualizar", + "switchVersion": "Trocar Versão", + "selectVersion": "Selecionar versão", + "loadingVersions": "Carregando versões...", + "failedToLoadVersions": "Falha ao carregar versões", + "installingVersion": "Instalando versão {{version}}...", + "rollbackWarningTitle": "Mudar para a versão {{version}}?", + "rollbackWarningDescription": "Trocar de versão fechará todas as sessões do Claude Code em execução. Qualquer trabalho não salvo nessas sessões poderá ser perdido. Certifique-se de salvar seu trabalho antes de prosseguir.", + "rollbackWarningTerminalNote": "Uma janela de terminal será aberta para executar o comando de instalação. Aguarde a conclusão da instalação antes de continuar.", + "switchAnyway": "Abrir Terminal e Trocar", + "currentVersion": "Atual", + "switchInstallation": "Trocar Instalação", + "selectInstallation": "Selecionar instalação", + "loadingInstallations": "Carregando instalações...", + "failedToLoadInstallations": "Falha ao carregar instalações", + "activeInstallation": "Ativa", + "pathChangeWarningTitle": "Trocar instalação do CLI?", + "pathChangeWarningDescription": "Trocar de instalação do CLI usará um binário diferente do Claude Code. Sessões em execução continuarão usando a instalação anterior até serem reiniciadas.", + "switchInstallationConfirm": "Trocar", + "versionUnknown": "versão desconhecida" + } +} diff --git a/apps/desktop/src/shared/i18n/locales/pt-BR/onboarding.json b/apps/desktop/src/shared/i18n/locales/pt-BR/onboarding.json new file mode 100644 index 0000000000..a40549d1de --- /dev/null +++ b/apps/desktop/src/shared/i18n/locales/pt-BR/onboarding.json @@ -0,0 +1,261 @@ +{ + "wizard": { + "title": "Assistente de Configuração", + "description": "Configure seu ambiente Aperant em poucos passos simples", + "helpText": "Este assistente ajudará você a configurar seu ambiente em poucos passos. Você pode configurar seu token OAuth do Claude, configurar funcionalidades de memória e criar sua primeira tarefa." + }, + "welcome": { + "title": "Bem-vindo ao Aperant", + "subtitle": "Construa software de forma autônoma com agentes movidos a IA", + "getStarted": "Começar", + "skip": "Pular Configuração", + "features": { + "aiPowered": { + "title": "Desenvolvimento com IA", + "description": "Gere código e construa funcionalidades usando agentes Claude Code" + }, + "specDriven": { + "title": "Workflow Orientado por Specs", + "description": "Defina tarefas com especificações claras e deixe o Aperant cuidar da implementação" + }, + "memory": { + "title": "Memória e Contexto", + "description": "Memória persistente entre sessões com Graphiti" + }, + "parallel": { + "title": "Execução Paralela", + "description": "Execute múltiplos agentes em paralelo para ciclos de desenvolvimento mais rápidos" + } + } + }, + "oauth": { + "title": "Autenticação do Claude", + "description": "Conecte sua conta Claude para habilitar funcionalidades de IA", + "configureTitle": "Configurar Autenticação do Claude", + "addAccountsDesc": "Adicione suas contas Claude para habilitar funcionalidades de IA", + "multiAccountInfo": "Adicione múltiplas assinaturas do Claude para alternar automaticamente entre elas quando atingir limites de uso.", + "noAccountsYet": "Nenhuma conta configurada ainda", + "badges": { + "default": "Padrão", + "active": "Ativa", + "authenticated": "Autenticada", + "needsAuth": "Precisa Auth" + }, + "buttons": { + "authenticate": "Autenticar", + "setActive": "Definir como Ativa", + "rename": "Renomear", + "delete": "Excluir", + "add": "Adicionar", + "adding": "Adicionando...", + "showToken": "Mostrar Token", + "hideToken": "Ocultar Token", + "copyToken": "Copiar Token", + "back": "Voltar", + "continue": "Continuar", + "skip": "Pular" + }, + "labels": { + "accountName": "Nome da conta", + "namePlaceholder": "Nome do perfil (ex.: Trabalho, Pessoal)", + "tokenLabel": "Token OAuth", + "tokenPlaceholder": "Insira o token aqui", + "tokenHint": "Cole o token mostrado no seu terminal após completar o login OAuth." + }, + "keychainTitle": "Armazenamento Seguro", + "keychainDescription": "Seus tokens são criptografados usando o keychain do sistema. Você pode ver um prompt de senha do macOS — clique em \"Sempre Permitir\" para não ver novamente.", + "toast": { + "authSuccess": "Perfil autenticado com sucesso", + "authSuccessWithEmail": "Conta: {{email}}", + "authSuccessGeneric": "Autenticação concluída. Agora você pode usar este perfil.", + "authStartFailed": "Falha ao iniciar autenticação", + "addProfileFailed": "Falha ao adicionar perfil", + "tokenSaved": "Token salvo", + "tokenSavedDescription": "Seu token foi salvo com sucesso.", + "tokenSaveFailed": "Falha ao salvar token", + "tryAgain": "Por favor, tente novamente." + }, + "alerts": { + "profileCreatedAuthFailed": "Perfil criado, mas falha ao preparar autenticação: {{error}}", + "authPrepareFailed": "Falha ao preparar autenticação: {{error}}", + "authStartFailedMessage": "Falha ao iniciar autenticação. Por favor, tente novamente." + } + }, + "memory": { + "title": "Memória", + "description": "Configure memória persistente entre sessões para agentes", + "contextDescription": "A Memória do Aperant ajuda a lembrar contexto entre suas sessões de codificação", + "enableMemory": "Habilitar Memória", + "enableMemoryDescription": "Memória persistente entre sessões usando um banco de dados embutido", + "memoryDisabledInfo": "A memória está desabilitada. Insights de sessão serão armazenados apenas em arquivos locais. Habilite a Memória para contexto persistente entre sessões com busca semântica.", + "embeddingProvider": "Provedor de Embeddings", + "embeddingProviderDescription": "Provedor para busca semântica (opcional - busca por palavras-chave funciona sem)", + "selectEmbeddingModel": "Selecionar Modelo de Embedding", + "openaiApiKey": "Chave da API OpenAI", + "openaiApiKeyDescription": "Necessária para embeddings da OpenAI", + "openaiGetKey": "Obtenha sua chave em", + "voyageApiKey": "Chave da API Voyage AI", + "voyageApiKeyDescription": "Necessária para embeddings da Voyage AI", + "voyageEmbeddingModel": "Modelo de Embedding", + "googleApiKey": "Chave da API Google AI", + "googleApiKeyDescription": "Necessária para embeddings do Google AI", + "azureConfig": "Configuração Azure OpenAI", + "azureApiKey": "Chave da API", + "azureBaseUrl": "URL Base", + "azureEmbeddingDeployment": "Nome do Deployment de Embedding", + "memoryInfo": "A Memória armazena descobertas, padrões e insights sobre seu código para que sessões futuras comecem com contexto já carregado.", + "learnMore": "Saiba mais sobre a Memória", + "back": "Voltar", + "skip": "Pular", + "saving": "Salvando...", + "saveAndContinue": "Salvar e Continuar", + "providers": { + "ollama": "Ollama (Local - Gratuito)", + "openai": "OpenAI", + "voyage": "Voyage AI", + "google": "Google AI", + "azure": "Azure OpenAI" + }, + "ollamaConfig": "Configuração do Ollama", + "checking": "Verificando...", + "connected": "Conectado", + "notRunning": "Não está executando", + "baseUrl": "URL Base", + "embeddingModel": "Modelo de Embedding", + "embeddingDim": "Dimensão do Embedding", + "embeddingDimDescription": "Necessário para embeddings do Ollama (ex.: 768 para nomic-embed-text)", + "modelRecommendation": "Recomendado: qwen3-embedding:4b (equilibrado), :8b (qualidade), :0.6b (rápido)" + }, + "completion": { + "title": "Tudo Pronto!", + "subtitle": "O Aperant está pronto para ajudá-lo a construir software incrível", + "setupComplete": "Configuração Completa", + "setupCompleteDescription": "Seu ambiente está configurado e pronto. Você pode começar a criar tarefas imediatamente ou explorar o aplicativo no seu ritmo.", + "whatsNext": "Próximos Passos", + "createTask": { + "title": "Criar uma Tarefa", + "description": "Comece criando sua primeira tarefa para ver o Aperant em ação.", + "action": "Abrir Criador de Tarefas" + }, + "customizeSettings": { + "title": "Personalizar Configurações", + "description": "Ajuste suas preferências, configure integrações ou execute este assistente novamente.", + "action": "Abrir Configurações" + }, + "exploreDocs": { + "title": "Explorar Documentação", + "description": "Saiba mais sobre funcionalidades avançadas, melhores práticas e solução de problemas." + }, + "finish": "Finalizar e Começar a Construir", + "rerunHint": "Você sempre pode executar este assistente novamente em Configurações → Aplicativo" + }, + "steps": { + "welcome": "Boas-vindas", + "accounts": "Contas", + "devtools": "Ferramentas Dev", + "privacy": "Privacidade", + "memory": "Memória", + "done": "Concluído" + }, + "privacy": { + "title": "Ajude a Melhorar o Aperant", + "subtitle": "Relatórios de erro anônimos nos ajudam a corrigir bugs mais rápido", + "whatWeCollect": { + "title": "O que coletamos", + "crashReports": "Relatórios de falhas e stack traces de erros", + "errorMessages": "Mensagens de erro (com caminhos de arquivo anonimizados)", + "appVersion": "Versão do app e informações da plataforma" + }, + "whatWeNeverCollect": { + "title": "O que nunca coletamos", + "code": "Seu código ou arquivos do projeto", + "filenames": "Caminhos completos de arquivos (nomes de usuário são mascarados)", + "apiKeys": "Chaves de API ou tokens", + "personalData": "Informações pessoais ou dados de uso" + }, + "toggle": { + "label": "Enviar relatórios de erro anônimos", + "description": "Ajude-nos a identificar e corrigir problemas" + } + }, + "claudeCode": { + "title": "CLI do Claude Code", + "description": "Instale ou atualize o CLI do Claude Code para habilitar funcionalidades de IA", + "detecting": "Verificando instalação do Claude Code...", + "info": { + "title": "O que é o Claude Code?", + "description": "Claude Code é o CLI oficial da Anthropic que alimenta as funcionalidades de IA do Aperant. Ele fornece autenticação segura e acesso direto aos modelos Claude." + }, + "status": { + "installed": "Instalado", + "outdated": "Atualização Disponível", + "notFound": "Não Instalado" + }, + "version": { + "current": "Versão Atual", + "latest": "Versão Mais Recente" + }, + "install": { + "button": "Instalar Claude Code", + "updating": "Atualizar Claude Code", + "inProgress": "Instalando...", + "success": "Comando de instalação enviado ao terminal. Complete a instalação lá.", + "instructions": "O instalador abrirá no seu terminal. Siga as instruções para completar a instalação." + }, + "learnMore": "Saiba mais sobre o Claude Code" + }, + "devtools": { + "title": "Ferramentas de Desenvolvimento", + "description": "Escolha sua IDE, terminal e CLI preferidos para trabalhar com worktrees do Aperant", + "detecting": "Detectando ferramentas instaladas...", + "detectAgain": "Detectar Novamente", + "whyConfigure": "Por que configurar isso?", + "whyConfigureDescription": "Quando o Aperant constrói funcionalidades em worktrees isoladas, você pode abri-las diretamente na sua IDE ou terminal preferido para testar e revisar alterações.", + "ide": { + "label": "IDE Preferida", + "description": "O Aperant abrirá worktrees neste editor", + "customPath": "Caminho da IDE Personalizada" + }, + "terminal": { + "label": "Terminal Preferido", + "description": "O Aperant abrirá sessões de terminal aqui", + "customPath": "Caminho do Terminal Personalizado" + }, + "cli": { + "label": "CLI Preferido", + "description": "Ferramenta CLI usada para sessões de terminal com IA", + "customPath": "Caminho do CLI Personalizado" + }, + "detectedSummary": "Detectado no seu sistema:", + "noToolsDetected": "Nenhuma ferramenta adicional detectada (VS Code e terminal do sistema serão usados)", + "custom": "Personalizado...", + "saveAndContinue": "Salvar e Continuar" + }, + "accounts": { + "title": "Adicione Suas Contas de IA", + "description": "Conecte suas contas de provedor de IA. Você pode adicionar mais depois em Configurações.", + "buttons": { + "back": "Voltar", + "continue": "Continuar", + "skip": "Pular por enquanto" + } + }, + "ollama": { + "notInstalled": { + "title": "Ollama não instalado", + "description": "O Ollama fornece modelos de embedding locais e gratuitos para busca semântica. Instale com um clique para habilitar esta funcionalidade.", + "installSuccess": "Instalação iniciada no seu terminal. Complete a instalação lá e clique em Tentar Novamente.", + "installButton": "Instalar Ollama", + "installing": "Instalando...", + "retry": "Tentar Novamente", + "learnMore": "Saiba mais", + "fallbackNote": "A memória ainda funcionará com busca por palavras-chave mesmo sem o Ollama." + }, + "notRunning": { + "title": "Ollama não está executando", + "description": "O Ollama está instalado, mas não está executando. Inicie o Ollama para usar modelos de embedding locais.", + "retry": "Tentar Novamente", + "fallbackNote": "A memória ainda funcionará com busca por palavras-chave mesmo sem embeddings." + } + } +} diff --git a/apps/desktop/src/shared/i18n/locales/pt-BR/settings.json b/apps/desktop/src/shared/i18n/locales/pt-BR/settings.json new file mode 100644 index 0000000000..86533954b3 --- /dev/null +++ b/apps/desktop/src/shared/i18n/locales/pt-BR/settings.json @@ -0,0 +1,1188 @@ +{ + "title": "Configurações", + "tabs": { + "app": "Config. do App", + "project": "Projeto" + }, + "sections": { + "appearance": { + "title": "Aparência", + "description": "Aparência do app" + }, + "display": { + "title": "Exibição", + "description": "Tamanho da interface" + }, + "language": { + "title": "Idioma", + "description": "Idioma preferido" + }, + "devtools": { + "title": "Ferramentas Dev", + "description": "IDE e terminal" + }, + "agent": { + "title": "Config. do Agente", + "description": "Modelo e framework" + }, + "paths": { + "title": "Caminhos", + "description": "CLI e frameworks" + }, + "accounts": { + "title": "Contas", + "description": "Claude e API endpoints" + }, + "updates": { + "title": "Atualizações", + "description": "Updates do app" + }, + "notifications": { + "title": "Notificações", + "description": "Alertas e avisos" + }, + "debug": { + "title": "Debug e Logs", + "description": "Diagnóstico" + }, + "terminal-fonts": { + "title": "Fontes do Terminal", + "description": "Fontes do terminal" + } + }, + "apiProfiles": { + "title": "Perfis de API", + "description": "Endpoints compatíveis com Anthropic", + "addButton": "Adicionar Perfil", + "presets": { + "anthropic": "Anthropic", + "openrouter": "OpenRouter", + "groq": "Groq", + "zaiGlobal": "z.AI (Global)", + "zaiChina": "z.AI (China)" + }, + "fields": { + "name": "Nome", + "preset": "Preset", + "baseUrl": "URL Base", + "apiKey": "Chave de API" + }, + "placeholders": { + "name": "Minha API Personalizada", + "preset": "Escolha um preset de provedor", + "baseUrl": "https://api.anthropic.com", + "apiKey": "sk-ant-..." + }, + "hints": { + "preset": "Presets preenchem a URL base; você ainda precisa colar sua chave de API.", + "baseUrl": "Exemplo: https://api.anthropic.com ou http://localhost:8080" + }, + "validation": { + "nameRequired": "O nome é obrigatório", + "baseUrlRequired": "A URL base é obrigatória", + "baseUrlInvalid": "Formato de URL inválido (deve ser http:// ou https://)", + "apiKeyRequired": "A chave de API é obrigatória", + "apiKeyInvalid": "Formato de chave de API inválido" + }, + "actions": { + "save": "Salvar Perfil", + "saving": "Salvando...", + "cancel": "Cancelar", + "changeKey": "Alterar", + "cancelKeyChange": "Cancelar" + }, + "testConnection": { + "label": "Testar Conexão", + "testing": "Testando...", + "success": "Conexão Bem-sucedida", + "failure": "Conexão Falhou" + }, + "models": { + "title": "Opcional: Mapeamento de Nomes de Modelos", + "description": "Selecione modelos do seu provedor de API. Deixe em branco para usar os padrões.", + "defaultLabel": "Modelo Padrão (Opcional)", + "haikuLabel": "Modelo Haiku (Opcional)", + "sonnetLabel": "Modelo Sonnet (Opcional)", + "opusLabel": "Modelo Opus (Opcional)", + "defaultPlaceholder": "ex., claude-sonnet-4-6", + "haikuPlaceholder": "ex., claude-haiku-4-5-20251001", + "sonnetPlaceholder": "ex., claude-sonnet-4-6", + "opusPlaceholder": "ex., claude-opus-4-6", + "opus1mPlaceholder": "ex., claude-opus-4-6 (1M context)" + }, + "empty": { + "title": "Nenhum perfil de API configurado", + "description": "Crie um perfil para configurar endpoints de API personalizados para seus builds.", + "action": "Criar Primeiro Perfil" + }, + "switchToOauth": { + "label": "Mudar para OAuth", + "loading": "Alternando..." + }, + "activeBadge": "Ativo", + "customModels": "Modelos personalizados: {{models}}", + "setActive": { + "label": "Definir como Ativo", + "loading": "Definindo..." + }, + "tooltips": { + "edit": "Editar perfil", + "deleteActive": "Mude para OAuth antes de excluir", + "deleteInactive": "Excluir perfil" + }, + "deleteAriaLabel": "Excluir perfil {{name}}", + "toast": { + "create": { + "title": "Perfil criado", + "description": "\"{{name}}\" foi adicionado com sucesso." + }, + "update": { + "title": "Perfil atualizado", + "description": "\"{{name}}\" foi atualizado com sucesso." + }, + "delete": { + "title": "Perfil excluído", + "description": "\"{{name}}\" foi removido.", + "errorTitle": "Falha ao excluir perfil", + "errorFallback": "Ocorreu um erro ao excluir o perfil." + }, + "switch": { + "oauthTitle": "Alternado para OAuth", + "oauthDescription": "Agora usando autenticação OAuth", + "profileTitle": "Perfil ativado", + "profileDescription": "Agora usando {{name}}", + "errorTitle": "Falha ao alternar autenticação", + "errorFallback": "Ocorreu um erro ao alternar o método de autenticação." + } + }, + "dialog": { + "createTitle": "Adicionar Perfil de API", + "editTitle": "Editar Perfil", + "description": "Configure um endpoint de API compatível com Anthropic para seus builds.", + "deleteTitle": "Excluir Perfil?", + "deleteDescription": "Tem certeza de que deseja excluir \"{{name}}\"? Esta ação não pode ser desfeita.", + "cancel": "Cancelar", + "delete": "Excluir", + "deleting": "Excluindo..." + } + }, + "modelSelect": { + "placeholder": "Selecione um modelo ou digite manualmente", + "placeholderManual": "Digite o nome do modelo (ex., claude-sonnet-4-6)", + "searchPlaceholder": "Buscar modelos...", + "noResults": "Nenhum modelo corresponde à sua busca", + "discoveryNotAvailable": "Descoberta de modelos não disponível. Digite o nome do modelo manualmente.", + "ollamaLoading": "Carregando modelos do Ollama...", + "ollamaNoModels": "Nenhum modelo do Ollama instalado", + "ollamaNoModelsHint": "Instale modelos em Configurações do Agente → aba Ollama", + "apiKeyOnly": "Chave de API" + }, + "language": { + "label": "Idioma da Interface", + "description": "Selecione o idioma da interface do aplicativo" + }, + "scale": { + "presets": "Presets de Escala", + "presetsDescription": "Opções rápidas de escala para preferências comuns", + "fineTune": "Ajuste Fino de Escala", + "fineTuneDescription": "Ajuste de 75% a 200% em incrementos de 5%", + "default": "Padrão", + "comfortable": "Confortável", + "large": "Grande" + }, + "logOrder": { + "label": "Ordem dos Logs", + "description": "Escolha como os logs são exibidos na visualização de detalhes da tarefa", + "chronological": "Cronológico (mais antigos primeiro)", + "reverseChronological": "Cronológico reverso (mais recentes primeiro)" + }, + "gpuAcceleration": { + "label": "Aceleração por GPU", + "description": "Usar WebGL para renderização do terminal (experimental, mais rápido com muitos terminais)", + "auto": "Automático (usar WebGL quando suportado)", + "on": "Sempre ativo", + "off": "Desativado (padrão)", + "helperText": "Alterações se aplicam apenas a novos terminais" + }, + "general": { + "otherAgentSettings": "Outras Configurações do Agente", + "otherAgentSettingsDescription": "Opções adicionais de configuração do agente", + "agentFramework": "Framework do Agente", + "agentFrameworkDescription": "O framework de codificação usado para tarefas autônomas", + "agentFrameworkAutoClaude": "Aperant", + "aiTerminalNaming": "Nomeação de Terminal por IA", + "aiTerminalNamingDescription": "Nomear terminais automaticamente com base nos comandos (usa o modelo de Nomeação por IA)", + "featureModelSettings": "Configurações de Modelo de Funcionalidades", + "featureModelSettingsDescription": "Modelo e nível de raciocínio para Insights, Ideação e Roadmap", + "model": "Modelo", + "thinkingLevel": "Nível de Raciocínio", + "paths": "Caminhos", + "pathsDescription": "Configure caminhos de executáveis e frameworks", + "pythonPath": "Caminho do Python", + "pythonPathDescription": "Caminho para o executável Python (deixe vazio para detecção automática)", + "pythonPathPlaceholder": "python3 (padrão)", + "gitPath": "Caminho do Git", + "gitPathDescription": "Caminho para o executável Git (deixe vazio para detecção automática)", + "gitPathPlaceholder": "git (padrão)", + "githubCLIPath": "Caminho do GitHub CLI", + "githubCLIPathDescription": "Caminho para o executável GitHub CLI (gh) (deixe vazio para detecção automática)", + "githubCLIPathPlaceholder": "gh (padrão)", + "gitlabCLIPath": "Caminho do GitLab CLI", + "gitlabCLIPathDescription": "Caminho para o executável GitLab CLI (glab) (deixe vazio para detecção automática)", + "gitlabCLIPathPlaceholder": "glab (padrão)", + "claudePath": "Caminho do Claude CLI", + "claudePathDescription": "Caminho para o executável Claude CLI (deixe vazio para detecção automática)", + "claudePathPlaceholder": "claude (padrão)", + "detectedPath": "Detectado automaticamente", + "detectedVersion": "Versão", + "detectedSource": "Origem", + "sourceUserConfig": "Configuração do Usuário", + "sourceVenv": "Ambiente Virtual", + "sourceHomebrew": "Homebrew", + "sourceNvm": "NVM", + "sourceSystemPath": "PATH do Sistema", + "sourceBundled": "Incluído", + "sourceFallback": "Fallback", + "notDetected": "Não detectado", + "autoClaudePath": "Caminho do Aperant", + "autoClaudePathDescription": "Caminho relativo para o diretório auto-claude nos projetos", + "autoClaudePathPlaceholder": "auto-claude (padrão)", + "autoNameTerminals": "Nomear terminais automaticamente", + "autoNameTerminalsDescription": "Usar IA para gerar nomes descritivos para abas de terminal com base na atividade" + }, + "theme": { + "title": "Aparência", + "description": "Personalize a aparência do Aperant", + "mode": "Modo", + "modeDescription": "Escolha entre temas claro e escuro", + "light": "Claro", + "dark": "Escuro", + "system": "Sistema", + "colorTheme": "Tema de Cores", + "colorThemeDescription": "Escolha sua paleta de cores preferida" + }, + "devtools": { + "title": "Ferramentas de Desenvolvedor", + "description": "Configure sua IDE preferida, terminal e configurações de fonte do terminal", + "detecting": "Detectando ferramentas instaladas...", + "detectAgain": "Detectar Novamente", + "tabTools": "Ferramentas", + "tabTerminalFonts": "Fontes do Terminal", + "ide": { + "label": "IDE Preferida", + "description": "O Aperant abrirá worktrees neste editor", + "placeholder": "Selecionar IDE...", + "customPath": "Caminho da IDE Personalizada", + "customPathPlaceholder": "/caminho/para/sua/ide" + }, + "terminal": { + "label": "Terminal Preferido", + "description": "O Aperant abrirá sessões de terminal aqui", + "placeholder": "Selecionar terminal...", + "customPath": "Caminho do Terminal Personalizado", + "customPathPlaceholder": "/caminho/para/seu/terminal" + }, + "cli": { + "label": "CLI Preferido", + "description": "Ferramenta CLI usada para sessões de terminal com IA", + "placeholder": "Selecionar CLI...", + "customPath": "Caminho do CLI Personalizado", + "customPathPlaceholder": "/caminho/para/seu/cli" + }, + "detected": "Detectado", + "notInstalled": "Não instalado", + "detectedSummary": "Detectados no seu sistema:", + "noToolsDetected": "Nenhuma ferramenta adicional detectada (VS Code e terminal do sistema serão usados)", + "autoNameClaude": { + "label": "Nomear terminais Claude automaticamente", + "description": "Usar IA para gerar um nome descritivo para terminais Claude com base na sua primeira mensagem" + }, + "yoloMode": { + "label": "Modo YOLO", + "description": "Iniciar Claude com a flag --dangerously-skip-permissions, ignorando todas as confirmações de segurança. Use com extrema cautela.", + "warning": "Este modo ignora o sistema de permissões do Claude. Ative apenas se você confia totalmente no código sendo executado." + } + }, + "updates": { + "title": "Atualizações", + "description": "Gerenciar atualizações do Aperant", + "appUpdateReady": "Atualização do App Pronta", + "newVersion": "Nova Versão", + "released": "Lançada em", + "downloading": "Baixando...", + "updateDownloaded": "Atualização baixada! Clique em Instalar para reiniciar e aplicar a atualização.", + "installAndRestart": "Instalar e Reiniciar", + "downloadUpdate": "Baixar Atualização", + "version": "Versão", + "loading": "Carregando...", + "checkingForUpdates": "Verificando atualizações...", + "newVersionAvailable": "Nova versão disponível:", + "latestVersion": "Você está usando a versão mais recente.", + "viewRelease": "Ver lançamento completo no GitHub", + "unableToCheck": "Não foi possível verificar atualizações", + "checkForUpdates": "Verificar Atualizações", + "autoUpdateProjects": "Atualizar Projetos Automaticamente", + "autoUpdateProjectsDescription": "Atualizar automaticamente o Aperant nos projetos quando uma nova versão estiver disponível", + "betaUpdates": "Atualizações Beta", + "betaUpdatesDescription": "Receber versões beta pré-lançamento com novos recursos (pode ser menos estável)", + "stableDowngradeAvailable": "Versão Estável Disponível", + "stableDowngradeDescription": "Você está usando uma versão beta. Como as atualizações beta estão desativadas, você pode voltar para a versão estável mais recente.", + "stableVersion": "Versão Estável", + "downloadStableVersion": "Baixar Versão Estável", + "readOnlyVolumeTitle": "Não é Possível Instalar a Partir de Imagem de Disco", + "readOnlyVolumeDescription": "O Aperant está sendo executado a partir de uma imagem de disco somente leitura (DMG). Arraste o app para a pasta Aplicativos e abra-o de lá para instalar atualizações.", + "downloadError": "Falha ao baixar atualização" + }, + "notifications": { + "title": "Notificações", + "description": "Configure as preferências padrão de notificação", + "onTaskComplete": "Ao Concluir Tarefa", + "onTaskCompleteDescription": "Notificar quando uma tarefa for concluída com sucesso", + "onTaskFailed": "Ao Falhar Tarefa", + "onTaskFailedDescription": "Notificar quando uma tarefa encontrar um erro", + "onReviewNeeded": "Ao Necessitar Revisão", + "onReviewNeededDescription": "Notificar quando o QA precisar da sua revisão", + "sound": "Som", + "soundDescription": "Reproduzir som com as notificações" + }, + "actions": { + "save": "Salvar Configurações", + "rerunWizard": "Reexecutar Assistente", + "rerunWizardDescription": "Reiniciar configuração" + }, + "projectSections": { + "general": { + "title": "Geral", + "description": "Auto-Build e agente", + "useClaudeMd": "Usar CLAUDE.md", + "useClaudeMdDescription": "Incluir instruções do CLAUDE.md no contexto do agente" + }, + "claude": { + "title": "Autenticação Claude", + "description": "Autenticação do Claude" + }, + "linear": { + "title": "Linear", + "description": "Integração com Linear", + "integrationTitle": "Integração com Linear", + "integrationDescription": "Conecte-se ao Linear para rastreamento de issues e importação de tarefas", + "syncDescription": "Sincronizar com o Linear para rastreamento de issues" + }, + "github": { + "title": "GitHub", + "description": "Sincronização de issues do GitHub", + "integrationTitle": "Integração com GitHub", + "integrationDescription": "Conecte-se ao GitHub para rastreamento de issues", + "syncDescription": "Sincronizar com GitHub Issues", + "defaultBranch": { + "label": "Branch Padrão", + "description": "Branch base para criar worktrees de tarefas", + "autoDetect": "Detectar automaticamente (main/master)", + "searchPlaceholder": "Buscar branches...", + "noBranchesFound": "Nenhuma branch encontrada", + "selectedBranchHelp": "Todas as novas tarefas serão criadas a partir da branch {{branch}}" + }, + "pushNewBranches": { + "label": "Push Automático de Novas Branches", + "description": "Fazer push de novas branches de tarefas e worktrees para o GitHub e configurar o upstream tracking automaticamente" + } + }, + "gitlab": { + "title": "GitLab", + "description": "Sincronização de issues do GitLab", + "integrationTitle": "Integração com GitLab", + "integrationDescription": "Conecte-se ao GitLab para rastreamento de issues", + "syncDescription": "Sincronizar com GitLab Issues" + }, + "memory": { + "title": "Memória", + "description": "Backend de memória Graphiti", + "integrationTitle": "Memória", + "integrationDescription": "Configure a memória persistente entre sessões para os agentes", + "syncDescription": "Configurar memória persistente" + } + }, + "agentProfile": { + "label": "Perfil do Agente", + "title": "Perfil Padrão do Agente", + "sectionDescription": "Selecione uma configuração predefinida para modelo e nível de raciocínio", + "profilesInfo": "Perfis de agente fornecem configurações predefinidas para o modelo Claude e nível de raciocínio. Ao criar uma nova tarefa, essas configurações serão usadas como padrão. Você sempre pode substituí-las no assistente de criação de tarefas.", + "custom": "Personalizado", + "customConfiguration": "Configuração Personalizada", + "customDescription": "Escolha modelo e nível de raciocínio", + "phaseConfiguration": "Configuração por Fase", + "phaseConfigurationDescription": "Personalize modelo e nível de raciocínio para cada fase", + "clickToCustomize": "Clique para personalizar", + "model": "Modelo", + "thinking": "Raciocínio", + "thinkingLevel": "Nível de Raciocínio", + "selectModel": "Selecionar modelo", + "selectThinkingLevel": "Selecionar nível de raciocínio", + "perPhaseOptimization": "(otimização por fase)", + "resetToDefaults": "Restaurar padrões", + "resetToProfileDefaults": "Restaurar padrões de {{profile}}", + "customized": "Personalizado", + "ollamaNotConfigured": "Selecione os modelos abaixo", + "phaseConfigNote": "Essas configurações serão usadas como padrão ao criar novas tarefas com este perfil. Você pode substituí-las por tarefa no assistente de criação de tarefas.", + "adaptiveThinking": { + "badge": "Adaptativo", + "tooltip": "O Opus usa raciocínio adaptativo — ele decide dinamicamente o quanto pensar dentro do limite de orçamento definido pelo nível de raciocínio." + }, + "reasoning": { + "adaptive": "Adaptativo", + "budget": "Orçamento", + "reasoning": "Raciocínio", + "thinking": "Raciocínio", + "noThinking": "(Sem raciocínio)", + "toggle": { + "off": "Desligado", + "on": "Ligado" + }, + "badgeTooltip": { + "adaptive_effort": "Decide dinamicamente o quanto pensar dentro do limite de orçamento", + "thinking_tokens": "Raciocínio baseado em orçamento com alocação configurável de tokens", + "reasoning_effort": "Níveis de esforço de raciocínio (baixo/médio/alto)", + "thinking_toggle": "Ativar/desativar raciocínio", + "none": "Raciocínio estendido não suportado" + } + }, + "phases": { + "spec": { + "label": "Criação de Spec", + "description": "Descoberta, requisitos, coleta de contexto" + }, + "planning": { + "label": "Planejamento", + "description": "Planejamento de implementação e arquitetura" + }, + "coding": { + "label": "Codificação", + "description": "Implementação do código" + }, + "qa": { + "label": "Revisão QA", + "description": "Garantia de qualidade e validação" + } + }, + "providerOverrides": { + "title": "Mapeamento de Modelos por Provedor", + "description": "Personalize qual modelo cada provedor usa para cada atalho", + "defaultMapping": "Padrão", + "yourOverride": "Sua Substituição", + "shorthand": "Atalho", + "useDefault": "Usar Padrão", + "resetAll": "Resetar Tudo", + "noConnectedProviders": "Nenhum provedor conectado. Adicione contas nas configurações de Contas para configurar mapeamentos de modelos.", + "equivalentNote": "Quando um provedor não-Anthropic está ativo, esses mapeamentos determinam qual modelo é usado para cada fase." + }, + "providerTabs": { + "moreProviders": "Mais", + "noProviders": "Nenhum provedor conectado. Adicione contas nas configurações de Contas para configurar as configurações de agente específicas do provedor.", + "configureFor": "Configurar agente para {{provider}}", + "crossProvider": "Multi-Provedor", + "crossProviderDisabledTooltip": "Conecte duas ou mais contas de provedor para habilitar capacidades multi-provedor", + "needsSetup": "Configuração necessária" + }, + "crossProviderTab": { + "title": "Configuração Multi-Provedor", + "description": "Atribua um provedor e modelo diferente para cada fase do pipeline para máxima flexibilidade.", + "activateInfo": "Tarefas criadas enquanto esta configuração está ativa usarão a configuração multi-provedor.", + "featureModelsTitle": "Modelos de Funcionalidades", + "featureModelsDescription": "Configure modelos para funcionalidades fora do pipeline (Insights, Ideação, etc.)" + }, + "customProfile": { + "name": "Personalizado (Multi-Provedor)", + "description": "Combine diferentes provedores e modelos para cada fase", + "phaseAssignment": "Atribua um provedor e modelo para cada fase" + }, + "ollamaModels": { + "title": "Modelos Ollama", + "description": "Gerencie modelos instalados localmente para tarefas de agentes de IA", + "installed": "Modelos Instalados", + "installedCount": "{{count}} modelo(s)", + "noModels": "Nenhum modelo LLM instalado", + "recommended": "Recomendados para Codificação", + "recommendedDescription": "Modelos populares otimizados para geração de código e raciocínio", + "download": "Baixar", + "downloading": "Baixando...", + "refresh": "Atualizar", + "loading": "Carregando modelos...", + "ollamaNotAvailable": "Conecte o Ollama nas Configurações de Conta para gerenciar modelos" + } + }, + "workspace": { + "roles": { + "backend": "Backend", + "frontend": "Frontend", + "mobile": "Mobile", + "shared": "Compartilhado", + "apiGateway": "API Gateway", + "worker": "Worker", + "other": "Outro" + } + }, + "integrations": { + "title": "Integrações", + "description": "Gerencie contas Claude e chaves de API", + "claudeAccounts": "Contas Claude", + "claudeAccountsDescription": "Adicione múltiplas assinaturas Claude para alternar automaticamente entre elas quando atingir limites de uso.", + "claudeAccountsWarning": "Ao autenticar, certifique-se de estar logado na conta Claude correta no seu navegador. Cada perfil deve usar uma assinatura diferente.", + "noAccountsYet": "Nenhuma conta configurada ainda", + "default": "Padrão", + "active": "Ativo", + "authenticated": "Autenticado", + "needsAuth": "Autenticação Necessária", + "authenticate": "Autenticar", + "authenticating": "Autenticando...", + "setActive": "Definir como Ativo", + "manualTokenEntry": "Inserção Manual de Token", + "runSetupToken": "Execute claude e digite /login para autenticar", + "tokenPlaceholder": "sk-ant-oat01-...", + "emailPlaceholder": "Email (opcional, para exibição)", + "saveToken": "Salvar Token", + "accountNamePlaceholder": "Nome da conta (ex., Trabalho, Pessoal)", + "autoSwitching": "Troca Automática de Conta", + "autoSwitchingDescription": "Alterne automaticamente entre contas Claude para evitar interrupções. Configure o monitoramento proativo para trocar antes de atingir os limites.", + "enableAutoSwitching": "Habilitar troca automática", + "masterSwitch": "Controle principal para todas as funcionalidades de troca automática", + "proactiveMonitoring": "Monitoramento Proativo", + "proactiveDescription": "Verificar uso regularmente e trocar antes de atingir os limites", + "checkUsageEvery": "Verificar uso a cada", + "seconds15": "15 segundos", + "seconds30": "30 segundos (recomendado)", + "minute1": "1 minuto", + "disabled": "Desabilitado", + "sessionThreshold": "Limite de uso da sessão", + "sessionThresholdDescription": "Trocar quando o uso da sessão atingir este nível (recomendado: 95%)", + "weeklyThreshold": "Limite de uso semanal", + "weeklyThresholdDescription": "Trocar quando o uso semanal atingir este nível (recomendado: 99%)", + "reactiveRecovery": "Recuperação Reativa", + "reactiveDescription": "Trocar automaticamente quando um limite de uso inesperado for atingido", + "autoSwitchOnAuthFailure": "Troca automática em falha de autenticação", + "autoSwitchOnAuthFailureDescription": "Trocar automaticamente para outra conta autenticada quando a autenticação falhar", + "apiKeys": "Chaves de API", + "apiKeysInfo": "As chaves definidas aqui são usadas como padrão. Projetos individuais podem sobrescrevê-las em suas configurações.", + "openaiKey": "Chave de API OpenAI", + "openaiKeyDescription": "Necessária para o backend de memória Graphiti (embeddings)", + "toast": { + "authSuccess": "Perfil Autenticado", + "authSuccessWithEmail": "Conectado como {{email}}", + "authSuccessGeneric": "Autenticação concluída. Agora você pode usar este perfil.", + "authStartFailed": "Falha na Autenticação", + "addProfileFailed": "Falha ao Adicionar Perfil", + "loadProfilesFailed": "Falha ao Carregar Perfis", + "deleteProfileFailed": "Falha ao Excluir Perfil", + "renameProfileFailed": "Falha ao Renomear Perfil", + "setActiveProfileFailed": "Falha ao Definir Perfil Ativo", + "profileCreatedAuthFailed": "Perfil Criado - Autenticação Necessária", + "profileCreatedAuthFailedDescription": "O perfil foi adicionado, mas a autenticação não pôde ser iniciada. Clique no botão de login para autenticar.", + "tokenSaved": "Token Salvo", + "tokenSavedDescription": "Seu token foi salvo com sucesso.", + "tokenSaveFailed": "Falha ao Salvar Token", + "settingsUpdateFailed": "Falha ao Atualizar Configurações", + "tryAgain": "Tente novamente.", + "terminalCreationFailed": "Falha ao criar terminal de autenticação", + "terminalCreationFailedDescription": "Não foi possível iniciar o processo de autenticação. {{error}}", + "maxTerminalsReached": "Limite máximo de terminais atingido", + "maxTerminalsReachedDescription": "Feche alguns terminais e tente novamente. Você pode ter até 12 terminais abertos.", + "terminalError": "Erro no Terminal", + "terminalErrorDescription": "Falha ao criar terminal: {{error}}", + "authProcessFailed": "O processo de autenticação falhou ao iniciar", + "authProcessFailedDescription": "O terminal de autenticação não pôde ser criado. Tente novamente ou verifique os logs para mais detalhes." + }, + "alerts": { + "profileCreatedAuthFailed": "Perfil criado, mas falha ao preparar autenticação: {{error}}", + "authPrepareFailed": "Falha ao preparar autenticação: {{error}}", + "authStartFailedMessage": "Falha ao iniciar autenticação. Tente novamente." + } + }, + "accounts": { + "title": "Contas", + "description": "Gerencie contas Claude e endpoints de API", + "tabs": { + "claudeCode": "Claude Code", + "customEndpoints": "Endpoints Personalizados" + }, + "claudeCode": { + "description": "Adicione múltiplas assinaturas Claude para alternar automaticamente entre elas quando atingir limites de uso.", + "noAccountsYet": "Nenhuma conta configurada ainda", + "default": "Padrão", + "active": "Ativo", + "authenticated": "Autenticado", + "needsAuth": "Autenticação Necessária", + "authenticate": "Autenticar", + "authenticating": "Autenticando...", + "setActive": "Definir como Ativo", + "manualTokenEntry": "Inserção Manual de Token", + "runSetupToken": "Execute claude e digite /login para autenticar", + "tokenPlaceholder": "sk-ant-oat01-...", + "emailPlaceholder": "Email (opcional, para exibição)", + "saveToken": "Salvar Token", + "accountNamePlaceholder": "Nome da conta (ex., Trabalho, Pessoal)" + }, + "customEndpoints": { + "description": "Configure endpoints de API compatíveis com Anthropic", + "addButton": "Adicionar Perfil", + "activeBadge": "Ativo", + "customModels": "Modelos personalizados: {{models}}", + "setActive": { + "label": "Definir como Ativo", + "loading": "Definindo..." + }, + "switchToOauth": { + "label": "Usar Claude Code", + "loading": "Alternando..." + }, + "tooltips": { + "edit": "Editar perfil", + "deleteActive": "Não é possível excluir perfil ativo", + "deleteInactive": "Excluir perfil" + }, + "empty": { + "title": "Nenhum Endpoint Personalizado", + "description": "Configure endpoints de API compatíveis com Anthropic para usar provedores alternativos.", + "action": "Adicionar Perfil" + }, + "dialog": { + "deleteTitle": "Excluir Perfil", + "deleteDescription": "Tem certeza de que deseja excluir \"{{name}}\"? Esta ação não pode ser desfeita.", + "cancel": "Cancelar", + "delete": "Excluir", + "deleting": "Excluindo..." + } + }, + "autoSwitching": { + "title": "Troca Automática de Conta", + "description": "Alterne automaticamente entre contas para evitar interrupções. Configure o monitoramento proativo para trocar antes de atingir os limites.", + "enableAutoSwitching": "Habilitar troca automática", + "masterSwitch": "Controle principal para todas as funcionalidades de troca automática", + "proactiveMonitoring": "Monitoramento Proativo", + "proactiveDescription": "Verificar uso regularmente e trocar antes de atingir os limites", + "sessionThreshold": "Limite de uso da sessão", + "sessionThresholdDescription": "Trocar quando o uso da sessão atingir este nível (recomendado: 95%)", + "weeklyThreshold": "Limite de uso semanal", + "weeklyThresholdDescription": "Trocar quando o uso semanal atingir este nível (recomendado: 99%)", + "reactiveRecovery": "Recuperação Reativa", + "reactiveDescription": "Trocar automaticamente quando um limite de uso inesperado for atingido", + "autoSwitchOnAuthFailure": "Troca automática em falha de autenticação", + "autoSwitchOnAuthFailureDescription": "Trocar automaticamente para outra conta autenticada quando a autenticação falhar" + }, + "priority": { + "title": "Ordem de Prioridade das Contas", + "description": "Arraste para reordenar. O sistema trocará para a próxima conta disponível em ordem.", + "tabs": { + "default": "Padrão", + "crossProvider": "Multi-Provedor" + }, + "crossProviderDescription": "Esta ordem de prioridade é usada quando o modo multi-provedor está ativo. Quando múltiplas contas compartilham um provedor, o sistema seleciona a melhor disponível com base nesta ordem.", + "setActive": "Definir como ativo", + "setActiveTooltip": "Tornar esta a conta principal", + "noAccounts": "Nenhuma conta configurada. Adicione contas acima para definir a prioridade.", + "noEmail": "Sem email", + "active": "Ativo", + "inUse": "Em Uso", + "next": "Próximo", + "unlimited": "Ilimitado", + "unavailable": "Indisponível", + "typeOAuth": "OAuth", + "typeAPI": "API", + "payPerUse": "Pago por uso", + "needsAuth": "Não autenticado", + "duplicateUsage": "Padrão de uso duplicado", + "duplicateUsageHint": "Esses perfis OAuth compartilham valores de uso idênticos. Verifique se cada perfil está associado a uma conta diferente, caso isso não tenha sido intencional.", + "needsReauth": "Reautenticação necessária", + "needsReauthHint": "O token de atualização deste perfil é inválido. Clique para reautenticar.", + "sessionUsage": "Uso da sessão (janela de 5 horas)", + "weeklyUsage": "Uso semanal (janela de 7 dias)", + "oauthSection": "Contas Claude (ciclar primeiro)", + "apiSection": "Endpoints de Fallback (quando todas as contas se esgotarem)", + "tipTitle": "Como a prioridade funciona", + "tipDescription": "Contas Claude estão incluídas na sua assinatura e serão cicladas primeiro. Endpoints de API cobram por requisição e são usados como fallback quando todas as contas Claude atingem seus limites.", + "status": { + "healthy": "Saudável", + "moderate": "Moderado", + "highUsage": "Uso elevado", + "nearLimit": "Próximo do limite", + "rateLimited": "Limite de uso atingido" + } + }, + "toast": { + "loadProfilesFailed": "Falha ao Carregar Perfis", + "addProfileFailed": "Falha ao Adicionar Perfil", + "deleteProfileFailed": "Falha ao Excluir Perfil", + "renameProfileFailed": "Falha ao Renomear Perfil", + "setActiveProfileFailed": "Falha ao Definir Perfil Ativo", + "tokenSaved": "Token Salvo", + "tokenSavedDescription": "Seu token foi salvo com sucesso.", + "tokenSaveFailed": "Falha ao Salvar Token", + "settingsUpdateFailed": "Falha ao Atualizar Configurações", + "tryAgain": "Tente novamente." + }, + "alerts": { + "profileCreatedAuthFailed": "Perfil criado, mas falha ao preparar autenticação: {{error}}", + "authPrepareFailed": "Falha ao preparar autenticação: {{error}}", + "authStartFailedMessage": "Falha ao iniciar autenticação. Tente novamente." + } + }, + "providers": { + "card": { + "oauth": "OAuth", + "codex": "Codex", + "codexSubscription": "Assinatura Codex", + "claudeCode": "Claude Code", + "claudeCodeSubscription": "Assinatura Claude Code", + "zaiCodingPlan": "Plano de Codificação", + "zaiUsageBased": "Baseado em Uso", + "zaiCodingPlanSubscription": "Plano de Codificação Z.AI", + "apiKey": "Chave de API", + "active": "Ativo", + "setDefault": "Definir como Ativo", + "edit": "Editar conta", + "reauth": "Reautenticar", + "delete": "Excluir conta", + "showKey": "Mostrar chave de API", + "hideKey": "Ocultar chave de API", + "oauthAccount": "Conta OAuth", + "oauthLinked": "Conta vinculada", + "noEndpoint": "Sem endpoint", + "customModels": "{{count}} modelo(s) configurado(s)" + }, + "section": { + "envDetected": "Do ambiente", + "envCredentialDetected": "Credenciais detectadas na variável de ambiente {{envVar}}", + "noAccounts": "Nenhuma conta configurada", + "addOAuth": "Adicionar Conta OAuth", + "addClaudeCode": "Adicionar Conta Claude Code", + "addCodexSubscription": "Adicionar Assinatura Codex", + "addCodingPlan": "Adicionar Plano de Codificação", + "addUsageBased": "Adicionar Chave de API Baseada em Uso", + "addApiKey": "Adicionar Chave de API", + "addEndpoint": "Adicionar Endpoint" + }, + "dialog": { + "addTitle": "Adicionar Conta", + "editTitle": "Editar Conta", + "deleteTitle": "Excluir Conta?", + "deleteDescription": "Tem certeza de que deseja excluir esta conta? Esta ação não pode ser desfeita.", + "cancel": "Cancelar", + "close": "Fechar", + "delete": "Excluir", + "deleting": "Excluindo...", + "save": "Salvar Alterações", + "add": "Adicionar Conta", + "optional": "(opcional)", + "oauthDescription": "Conectar usando autenticação OAuth", + "apiKeyDescription": "Adicione sua chave de API e configuração", + "zaiCodingPlanDescription": "Adicione sua chave de API do Plano de Codificação Z.AI para usar modelos GLM com sua assinatura", + "zaiUsageBasedDescription": "Adicione sua chave de API Z.AI baseada em uso para acesso pago por uso aos modelos GLM", + "codexOAuthDescription": "Faça login com sua assinatura ChatGPT Plus ou Pro para usar modelos Codex", + "codexAuthenticating": "Abrindo login da OpenAI no seu navegador...", + "codexWaiting": "Aguardando autenticação no navegador...", + "codexSuccess": "Autenticado com OpenAI Codex", + "codexError": "Falha na autenticação OpenAI: {{error}}", + "codexAuthenticate": "Autenticar com OpenAI", + "codexReauthenticate": "Reautenticar com OpenAI", + "oauthInstructions": "Para adicionar uma conta OAuth, use o fluxo de autenticação do Claude Code na aba Claude Code acima. Contas OAuth estão vinculadas à sua assinatura Claude.ai.", + "oauthAuthenticate": "Autenticar com Anthropic", + "oauthReauthenticate": "Reautenticar com Anthropic", + "oauthAuthenticating": "Abrindo navegador...", + "oauthWaiting": "Aguardando autorização...", + "oauthSuccess": "Autenticado como {{email}}", + "oauthError": "Falha na autenticação: {{error}}", + "oauthFallback": "Usar Terminal (Fallback)", + "oauthFallbackDescription": "Se o login pelo navegador não funcionar, use o terminal integrado", + "oauthNameRequired": "Insira um nome de conta antes de autenticar", + "modelsDescription": "Adicione os IDs dos modelos disponíveis neste endpoint. Eles aparecerão no seletor de modelos.", + "fields": { + "name": "Nome da Conta", + "apiKey": "Chave de API", + "baseUrl": "URL Base", + "region": "Região AWS", + "models": "Modelos" + }, + "placeholders": { + "name": "Minha Conta", + "apiKey": "sk-...", + "baseUrl": "https://...", + "modelId": "ID do Modelo (ex., llama-3.1-70b)", + "modelLabel": "Nome de exibição" + }, + "toast": { + "added": "Conta adicionada", + "updated": "Conta atualizada", + "error": "Falha ao salvar conta", + "duplicateEmail": "Este email já está registrado como \"{{existingName}}\"", + "createProfileFailed": "Falha ao criar perfil", + "authPrepareFailed": "Falha ao preparar terminal", + "unexpectedError": "Erro inesperado" + } + }, + "toast": { + "deleted": "Conta excluída", + "deleteFailed": "Falha ao excluir conta", + "reauthStarted": "Abrindo autenticação...", + "reauthSuccess": "Reautenticado com sucesso", + "reauthFailed": "Falha na reautenticação" + }, + "categories": { + "popular": "Populares", + "infrastructure": "Infraestrutura", + "local": "Local e Personalizado" + }, + "ollama": { + "connection": { + "checking": "Verificando conexão com Ollama...", + "connected": "Conectado", + "connectedDescription": "O Ollama está em execução e pronto para uso", + "modelsAvailable": "{{count}} modelo(s) LLM instalado(s)", + "noModels": "Nenhum modelo LLM instalado ainda", + "customUrl": "URL Personalizada", + "customUrlPlaceholder": "http://localhost:11434", + "notInstalled": "Ollama Não Instalado", + "notInstalledDescription": "Instale o Ollama para executar modelos de IA de código aberto localmente", + "notRunning": "Ollama Não Está em Execução", + "notRunningDescription": "Inicie o serviço Ollama para conectar", + "install": "Instalar Ollama", + "retry": "Tentar Novamente", + "learnMore": "Saiba Mais", + "autoConnected": "Conectado automaticamente como provedor local", + "startCommand": "Execute 'ollama serve' no seu terminal" + } + } + }, + "debug": { + "title": "Debug e Logs", + "description": "Acesse logs e informações de debug para diagnóstico", + "errorReporting": { + "label": "Relatório Anônimo de Erros", + "description": "Envie relatórios de falhas para ajudar a melhorar o Aperant. Nenhum dado pessoal ou código é coletado." + }, + "openLogsFolder": "Abrir Pasta de Logs", + "copyDebugInfo": "Copiar Informações de Debug", + "copied": "Copiado!", + "loadInfo": "Carregar Informações de Debug", + "systemInfo": "Informações do Sistema", + "logsLocation": "Localização dos Logs", + "recentErrors": "Erros Recentes", + "noRecentErrors": "Nenhum erro recente", + "helpTitle": "Reportando Problemas", + "helpText": "Ao reportar bugs, clique em \"Copiar Informações de Debug\" para obter informações do sistema e erros recentes que nos ajudam a diagnosticar o problema." + }, + "projectSettings": { + "noProjectSelected": { + "title": "Nenhum Projeto Selecionado", + "description": "Selecione um projeto na barra lateral para configurar suas opções." + } + }, + "mcp": { + "title": "Visão Geral dos Servidores MCP", + "titleWithProject": "Visão Geral dos Servidores MCP para {{projectName}}", + "description": "Configure quais servidores MCP estão disponíveis para os agentes neste projeto", + "descriptionNoProject": "Selecione um projeto para configurar os servidores MCP", + "serversEnabled": "{{count}} servidores habilitados", + "configuration": "Configuração de Servidores MCP", + "configurationHint": "Servidores desabilitados reduzem o uso de contexto e o tempo de inicialização", + "noProjectSelected": "Nenhum Projeto Selecionado", + "noProjectSelectedDescription": "Selecione um projeto no dropdown para visualizar e configurar os servidores MCP.", + "projectNotInitialized": "Projeto Não Inicializado", + "projectNotInitializedDescription": "Inicialize o Aperant para este projeto para configurar os servidores MCP.", + "browserAutomation": "Automação de Navegador (apenas agentes QA)", + "alwaysEnabled": "sempre habilitado", + "addServer": "Adicionar Servidor", + "addMcpTo": "Adicionar Servidor MCP ao {{agent}}", + "addMcpDescription": "Selecione um servidor MCP para adicionar a este agente", + "allMcpsAdded": "Todos os servidores MCP disponíveis já foram adicionados", + "added": "adicionado", + "removed": "removido", + "remove": "Remover", + "restore": "Restaurar", + "noMcpServers": "Nenhum servidor MCP", + "cannotRemove": "Não é possível remover (obrigatório)", + "servers": { + "context7": { + "name": "Context7", + "description": "Consulta de documentação para bibliotecas" + }, + "graphiti": { + "name": "Memória Graphiti", + "description": "Grafo de conhecimento para contexto entre sessões", + "notConfigured": "Requer configuração de memória (veja configurações de Memória)" + }, + "linear": { + "name": "Linear", + "description": "Integração de gerenciamento de projetos", + "notConfigured": "Requer integração com Linear (veja configurações do Linear)" + }, + "electron": { + "name": "Electron", + "description": "Automação de app desktop via Chrome DevTools" + }, + "puppeteer": { + "name": "Puppeteer", + "description": "Automação de navegador web para testes" + }, + "autoClaude": { + "name": "Ferramentas Aperant", + "description": "Rastreamento de progresso de build" + } + }, + "customServers": "Servidores Personalizados", + "addCustomServer": "Adicionar Servidor Personalizado", + "editCustomServer": "Editar Servidor Personalizado", + "customServerDescription": "Adicione um servidor MCP baseado em comando ou HTTP", + "serverType": "Tipo de Servidor", + "typeCommand": "Comando (npx/npm)", + "typeHttp": "HTTP", + "serverName": "Nome", + "serverNamePlaceholder": "Meu Servidor MCP", + "serverDescription": "Descrição", + "serverDescriptionPlaceholder": "O que este servidor faz", + "command": "Comando", + "args": "Argumentos", + "argsHint": "Argumentos separados por espaço", + "url": "URL", + "headers": "Cabeçalhos", + "headerName": "Nome do Cabeçalho", + "headerValue": "Valor do Cabeçalho", + "noCustomServers": "Nenhum servidor personalizado configurado. Adicione um para usar com seus agentes.", + "errorNameRequired": "O nome do servidor é obrigatório", + "errorIdExists": "Um servidor com este ID já existe", + "errorCommandRequired": "O comando é obrigatório para servidores baseados em comando", + "errorUrlRequired": "A URL é obrigatória para servidores baseados em HTTP", + "testConnection": "Testar", + "testing": "Testando...", + "authToken": "Token de Autenticação", + "authTokenPlaceholder": "Cole seu token de API ou PAT aqui", + "authTokenHint": "Usado como token Bearer no cabeçalho Authorization", + "advancedHeaders": "Cabeçalhos Adicionais", + "status": { + "healthy": "O servidor está respondendo", + "unhealthy": "O servidor não está respondendo", + "needsAuth": "Autenticação necessária", + "checking": "Verificando...", + "unknown": "Status desconhecido" + }, + "hints": { + "github": "Parece ser um servidor MCP do GitHub. Você precisará de um Personal Access Token com os escopos apropriados.", + "createGithubPat": "Criar PAT do GitHub", + "google": "Parece ser uma API do Google. Você precisará de um token OAuth ou chave de API.", + "createGoogleToken": "Criar Credenciais do Google", + "anthropic": "Parece ser uma API da Anthropic. Você precisará de uma chave de API.", + "createAnthropicKey": "Criar Chave de API Anthropic", + "openai": "Parece ser uma API da OpenAI. Você precisará de uma chave de API.", + "createOpenaiKey": "Criar Chave de API OpenAI" + } + }, + "terminalFonts": { + "title": "Fontes do Terminal", + "description": "Personalize a aparência e o comportamento das fontes do terminal", + "configActions": "Configuração:", + "export": "Exportar JSON", + "import": "Importar JSON", + "copy": "Copiar para Área de Transferência", + "fontConfig": { + "title": "Configuração de Fonte", + "description": "Personalize família de fontes, tamanho, peso, altura de linha e espaçamento entre caracteres", + "fontFamily": "Família de Fontes", + "fontFamilyDescription": "Fonte monoespaçada principal para texto do terminal", + "selectFont": "Selecionar uma fonte...", + "searchFont": "Buscar fontes...", + "noFonts": "Nenhuma fonte encontrada", + "fontChain": "Cadeia de fontes:", + "fontSize": "Tamanho da Fonte", + "fontSizeDescription": "Tamanho base da fonte em pixels (10-24px)", + "decreaseFontSize": "Diminuir tamanho da fonte em {{step}}px", + "increaseFontSize": "Aumentar tamanho da fonte em {{step}}px", + "pixels": "pixels", + "fontWeight": "Peso da Fonte", + "fontWeightDescription": "Peso da fonte de 100 (fino) a 900 (ultra-negrito), em incrementos de 100", + "commonWeights": "Comuns: 400 (normal), 600 (seminegrito), 700 (negrito)", + "decreaseFontWeight": "Diminuir peso da fonte em {{step}}", + "increaseFontWeight": "Aumentar peso da fonte em {{step}}", + "lineHeight": "Altura de Linha", + "lineHeightDescription": "Altura de linha como múltiplo do tamanho da fonte (1.0-2.0)", + "letterSpacing": "Espaçamento entre Caracteres", + "letterSpacingDescription": "Espaçamento horizontal entre caracteres (-2 a 5px)" + }, + "cursorConfig": { + "title": "Configuração do Cursor", + "description": "Personalize o estilo do cursor, comportamento de piscar e cor de destaque", + "cursorStyle": "Estilo do Cursor", + "cursorStyleDescription": "Escolha a aparência do cursor do terminal", + "selectStyle": "Selecionar estilo do cursor...", + "currentStyle": "Atual:", + "styleBlock": "Bloco", + "styleBlockDescription": "Cursor de bloco completo", + "styleUnderline": "Sublinhado", + "styleUnderlineDescription": "Cursor sublinhado", + "styleBar": "Barra", + "styleBarDescription": "Cursor de barra vertical", + "cursorBlink": "Cursor Piscante", + "cursorBlinkDescription": "Habilitar ou desabilitar a animação de piscar do cursor", + "blinkStatus": "Status:", + "enabled": "Habilitado", + "disabled": "Desabilitado", + "cursorAccentColor": "Cor de Destaque do Cursor", + "cursorAccentColorDescription": "Escolha a cor do cursor do terminal", + "cursorColorLabel": "Cor de destaque do cursor", + "cursorColorDescription": "Cor atual: {{color}}", + "pickColor": "Clique para escolher uma cor", + "resetColor": "Resetar para preto", + "reset": "Resetar", + "preview": "Pré-visualização:" + }, + "performanceConfig": { + "title": "Configurações de Performance", + "description": "Ajuste o limite de scrollback e outras configurações relacionadas à performance", + "presets": "Presets Rápidos", + "presetsDescription": "Limites de scrollback comuns para diferentes casos de uso", + "scrollback": "Limite de Scrollback", + "scrollbackDescription": "Número máximo de linhas para manter no histórico do terminal", + "scrollbackPresets": "Presets Rápidos", + "presetMinimal": "Mínimo", + "presetMinimalDescription": "Histórico mínimo (1K linhas)", + "presetStandard": "Padrão", + "presetStandardDescription": "Histórico padrão (10K linhas)", + "presetExtended": "Estendido", + "presetExtendedDescription": "Histórico estendido (50K linhas)", + "presetMaximum": "Máximo", + "presetMaximumDescription": "Histórico máximo (100K linhas)", + "decreaseScrollback": "Diminuir scrollback em {{step}}", + "increaseScrollback": "Aumentar scrollback em {{step}}", + "lines": "linhas", + "kValue": "{{value}}K", + "scrollbackValue": "{{value}} linhas" + }, + "presets": { + "title": "Presets Rápidos", + "description": "Aplique configurações pré-definidas de fonte do terminal ou salve as suas", + "builtin": "Presets Integrados", + "builtinDescription": "Clique para aplicar um preset pré-configurado", + "vscode": "Consolas 14px, cursor bloco", + "vscodeName": "VS Code", + "intellij": "JetBrains Mono 13px, cursor bloco", + "intellijName": "IntelliJ IDEA", + "macos": "SF Mono 13px, cursor bloco", + "macosName": "Terminal macOS", + "ubuntu": "Ubuntu Mono 13px, cursor bloco", + "ubuntuName": "Terminal Ubuntu", + "reset": "Restaurar Padrões", + "resetDescription": "Restaurar as configurações padrão do seu sistema operacional", + "resetToOS": "Restaurar padrões do {{os}}", + "resetButton": "Restaurar Padrão do SO", + "custom": "Presets Personalizados", + "customDescription": "Salve sua configuração atual como um preset personalizado", + "presetNamePlaceholder": "Nome do preset...", + "savePreset": "Salvar configuração atual como preset", + "applyPreset": "Aplicar este preset", + "deletePreset": "Excluir este preset", + "noCustomPresets": "Nenhum preset personalizado ainda. Salve sua configuração atual para começar.", + "duplicateName": "Um preset com este nome já existe", + "saved": "Preset \"{{name}}\" salvo", + "deleted": "Preset \"{{name}}\" excluído", + "unknownFont": "Desconhecida", + "applyFailed": "Falha ao aplicar preset \"{{name}}\"", + "presetNameLabel": "Nome do preset", + "summary": "{{font}}, {{size}}px, cursor {{cursor}}" + }, + "preview": { + "title": "Pré-visualização ao Vivo", + "description": "Pré-visualize suas configurações de terminal em tempo real (atualiza em 300ms)", + "ariaLabel": "Pré-visualização da fonte do terminal", + "infoText": "Esta pré-visualização atualiza em 300ms a cada alteração para mostrar como suas configurações ficarão nos terminais reais." + }, + "importExport": { + "exportSuccess": "Configurações exportadas com sucesso", + "exportFailed": "Falha ao exportar configurações", + "importSuccess": "Configurações importadas com sucesso", + "importFailed": "Falha ao importar configurações: Formato JSON inválido", + "importFailedRange": "Falha ao importar configurações: Valores fora do intervalo válido", + "copySuccess": "Configurações copiadas para a área de transferência", + "copyFailed": "Falha ao copiar para a área de transferência", + "fileTooLarge": "Arquivo de importação muito grande (máximo 10KB)", + "readError": "Falha ao ler arquivo" + }, + "slider": { + "decrease": "Diminuir {{label}} em {{step}}", + "increase": "Aumentar {{label}} em {{step}}", + "currentValue": "Valor atual: {{value}}" + } + }, + "agents": { + "pr_template_filler": { + "label": "Preenchedor de Template de PR", + "description": "IA preenche templates de PR do GitHub a partir das alterações de código" + } + }, + "provider": { + "title": "Provedor de IA", + "description": "Configure seu provedor de IA e preferências de modelo", + "selection": { + "label": "Provedor", + "description": "Selecione qual provedor de IA usar para tarefas de agente", + "anthropic": "Anthropic", + "openai": "OpenAI", + "ollama": "Ollama (Local)", + "openrouter": "OpenRouter" + }, + "apiKey": { + "label": "Chave de API", + "description": "Sua chave de API para o provedor selecionado", + "placeholder": "Insira sua chave de API", + "anthropicPlaceholder": "sk-ant-...", + "openaiPlaceholder": "sk-...", + "openrouterPlaceholder": "sk-or-...", + "validation": { + "required": "A chave de API é obrigatória para este provedor", + "invalid": "Formato de chave de API inválido" + } + }, + "ollama": { + "endpointUrl": "URL do Endpoint Ollama", + "endpointDescription": "A URL onde sua instância do Ollama está em execução", + "endpointPlaceholder": "http://localhost:11434", + "validation": { + "urlRequired": "A URL do endpoint é obrigatória para o Ollama", + "urlInvalid": "Formato de URL inválido (deve ser http:// ou https://)" + } + }, + "phaseModels": { + "title": "Preferências de Modelo por Fase", + "description": "Configure qual modelo usar para cada fase do pipeline", + "spec": { + "label": "Modelo de Criação de Spec", + "description": "Modelo usado para descoberta, requisitos e coleta de contexto" + }, + "planning": { + "label": "Modelo de Planejamento", + "description": "Modelo usado para planejamento de implementação e arquitetura" + }, + "coding": { + "label": "Modelo de Codificação", + "description": "Modelo usado para implementação de código" + }, + "qa": { + "label": "Modelo de Revisão QA", + "description": "Modelo usado para garantia de qualidade e validação" + }, + "placeholder": "Selecionar um modelo", + "useDefault": "Usar modelo padrão" + }, + "testConnection": { + "label": "Testar Conexão", + "testing": "Testando...", + "success": "Conexão bem-sucedida", + "failure": "Conexão falhou" + }, + "toast": { + "saved": { + "title": "Configurações do provedor salvas", + "description": "Sua configuração de provedor de IA foi atualizada." + }, + "error": { + "title": "Falha ao salvar configurações do provedor", + "description": "Ocorreu um erro ao salvar a configuração do provedor." + } + } + } +} \ No newline at end of file diff --git a/apps/desktop/src/shared/i18n/locales/pt-BR/taskReview.json b/apps/desktop/src/shared/i18n/locales/pt-BR/taskReview.json new file mode 100644 index 0000000000..64c8709799 --- /dev/null +++ b/apps/desktop/src/shared/i18n/locales/pt-BR/taskReview.json @@ -0,0 +1,162 @@ +{ + "terminal": { + "openTerminal": "Abrir terminal", + "openInbuilt": "Abrir no Terminal Integrado", + "openExternal": "Abrir no Terminal Externo" + }, + "merge": { + "branchHasNewCommits": "A branch {{branch}} tem {{count}} novo commit.", + "branchHasNewCommits_other": "A branch {{branch}} tem {{count}} novos commits.", + "branchHasNewCommitsSinceWorktree": "A branch {{branch}} tem {{count}} novo commit desde que esta worktree foi criada.", + "branchHasNewCommitsSinceWorktree_other": "A branch {{branch}} tem {{count}} novos commits desde que esta worktree foi criada.", + "filesNeedMerging": "{{count}} arquivo precisa de merge.", + "filesNeedMerging_other": "{{count}} arquivos precisam de merge.", + "filesNeedIntelligentMerging": "{{count}} arquivo precisará de merge inteligente:", + "filesNeedIntelligentMerging_other": "{{count}} arquivos precisarão de merge inteligente:", + "branchHasNewCommitsSinceBuild": "A branch {{branch}} tem {{count}} novo commit desde que esta build começou.", + "branchHasNewCommitsSinceBuild_other": "A branch {{branch}} tem {{count}} novos commits desde que esta build começou.", + "filesNeedAIMergeDueToRenames": "{{count}} arquivo precisa de merge IA devido a {{renameCount}} renomeação de arquivo.", + "filesNeedAIMergeDueToRenames_other": "{{count}} arquivos precisam de merge IA devido a {{renameCount}} renomeações de arquivos.", + "filesNeedAIMergeDueToRenamesPlural": "{{count}} arquivo precisa de merge IA devido a {{renameCount}} renomeações de arquivos.", + "filesNeedAIMergeDueToRenamesPlural_other": "{{count}} arquivos precisam de merge IA devido a {{renameCount}} renomeações de arquivos.", + "fileRenamesDetected": "{{count}} renomeação de arquivo detectada - a IA cuidará do merge.", + "fileRenamesDetected_other": "{{count}} renomeações de arquivos detectadas - a IA cuidará do merge.", + "filesRenamedOrMoved": "Arquivos podem ter sido renomeados ou movidos - a IA cuidará do merge.", + "alreadyMergedTitle": "Alterações já na sua branch", + "alreadyMergedDescription": "Essas alterações parecem já existir na sua branch atual. Você pode marcar esta tarefa como concluída com segurança.", + "alreadyMergedTooltip": "As alterações da tarefa já estão presentes na sua branch. Marcar como concluída limpará a worktree sem fazer merge.", + "matchingFiles": "Arquivos correspondentes", + "supersededTitle": "Alterações substituídas", + "supersededDescription": "Sua branch atual tem uma versão mais recente dessas alterações. Considere descartar esta tarefa ou visualizar a comparação.", + "supersededCompareTooltip": "Veja uma comparação detalhada para ver como a branch atual difere das alterações desta tarefa.", + "supersededDiscardTooltip": "Remova a worktree desta tarefa, já que as alterações não são mais necessárias.", + "status": { + "branchDiverged": "Branch Divergiu", + "aiWillResolve": "IA resolverá", + "filesRenamed": "Arquivos Renomeados", + "branchBehind": "Branch Atrasada", + "readyToMerge": "Pronto para merge", + "files": "arquivos", + "file": "arquivo", + "conflict": "conflito", + "conflicts": "conflitos", + "details": "Detalhes", + "refresh": "Atualizar", + "stageOnly": "Apenas preparar (revisar na IDE antes de commitar)", + "discardBuild": "Descartar build" + }, + "buttons": { + "stageWithAIMerge": "Preparar com Merge IA", + "mergeWithAI": "Merge com IA", + "stageTo": "Preparar para {{branch}}", + "mergeTo": "Merge para {{branch}}", + "resolving": "Resolvendo...", + "staging": "Preparando...", + "merging": "Fazendo merge...", + "completing": "Concluindo..." + }, + "actions": { + "markAsDone": "Marcar como Concluída", + "discardTask": "Descartar Tarefa", + "viewComparison": "Ver Comparação" + } + }, + "pr": { + "title": "Criar Pull Request", + "description": "Fazer push da branch e criar um pull request para \"{{taskTitle}}\"", + "errors": { + "unknown": "Ocorreu um erro desconhecido ao criar o pull request", + "invalidBranchName": "O nome da branch contém caracteres inválidos. Use apenas letras, números, hifens (-), underscores (_) e barras (/).", + "emptyTitle": "O título do pull request não pode estar vazio." + }, + "success": { + "created": "Pull request criado com sucesso!", + "alreadyExists": "Já existe um pull request para esta branch" + }, + "actions": { + "retry": "Tentar Novamente", + "creating": "Criando PR...", + "create": "Criar Pull Request" + }, + "labels": { + "sourceBranch": "Branch de origem", + "targetBranch": "Branch de destino", + "commits": "Commits", + "changes": "Alterações", + "prTitle": "Título do PR (opcional)", + "draftPR": "Criar como PR rascunho", + "unknown": "Desconhecido" + }, + "hints": { + "targetBranch": "Deixe vazio para usar a branch padrão", + "prTitle": "Deixe vazio para usar o título da tarefa" + } + }, + "mergeProgress": { + "stages": { + "analyzing": "Analisando alterações", + "detectingConflicts": "Detectando conflitos", + "resolving": "Resolvendo conflitos", + "validating": "Validando merge", + "complete": "Merge completo", + "error": "Merge falhou", + "stalled": "Merge parado" + }, + "conflictCounter": "{{found}} encontrado(s), {{resolved}} resolvido(s)", + "currentFile": "Arquivo atual", + "viewLogs": "Ver logs", + "hideLogs": "Ocultar logs", + "logTypes": { + "info": "Info", + "warning": "Aviso", + "error": "Erro", + "conflict": "Conflito", + "resolution": "Resolução" + }, + "completionMessage": "Todas as alterações foram mergeadas com sucesso.", + "errorMessage": "Ocorreu um erro durante o processo de merge." + }, + "stagedSuccess": { + "title": "Alterações Preparadas com Sucesso", + "aiCommitMessage": "Mensagem de commit gerada por IA", + "copied": "Copiado!", + "copy": "Copiar", + "editHint": "Edite conforme necessário, depois copie e use com", + "nextSteps": "Próximos passos:", + "reviewChanges": "Revise as alterações preparadas com", + "commitWhenReady": "Faça o commit quando estiver pronto:", + "pushToRemote": "Faça push para o remoto quando estiver satisfeito", + "cleaningUp": "Limpando...", + "markingDone": "Marcando como concluída...", + "resetting": "Redefinindo...", + "deleteWorktreeAndMarkDone": "Excluir Worktree e Marcar como Concluída", + "markDoneOnly": "Apenas Marcar como Concluída", + "markAsDone": "Marcar como Concluída", + "reviewAgain": "Revisar Novamente", + "commitMessagePlaceholder": "Mensagem de commit...", + "worktreeExplanation": "\"Excluir Worktree e Marcar como Concluída\" limpa o espaço de trabalho isolado. \"Apenas Marcar como Concluída\" mantém para referência.", + "errors": { + "failedToDeleteWorktree": "Falha ao excluir worktree", + "worktreeDeletedButStatusFailed": "Worktree excluída, mas falha ao atualizar o status da tarefa: {{error}}", + "failedToMarkAsDone": "Falha ao marcar como concluída", + "failedToResetStagedState": "Falha ao redefinir estado preparado" + } + }, + "bulkPR": { + "title": "Criar Pull Requests", + "description": "Criar pull requests para {{count}} tarefas selecionadas", + "creating": "Criando PR {{current}} de {{total}}...", + "creatingPR": "Criando PR {{current}} de {{total}}", + "resultsDescription": "{{success}} com sucesso, {{failed}} falharam", + "tasksToProcess": "Tarefas a processar", + "targetBranchHint": "Deixe vazio para usar a branch padrão de cada tarefa. Isso será aplicado a todos os PRs.", + "createAll": "Criar {{count}} PRs", + "completed": "concluído", + "succeeded": "sucesso", + "failed": "falhou", + "skipped": "ignorado", + "alreadyExisted": "já existia", + "noWorktree": "Nenhuma worktree encontrada para esta tarefa", + "resultsDescriptionWithSkipped": "{{success}} com sucesso, {{skipped}} ignorados, {{failed}} falharam" + } +} diff --git a/apps/desktop/src/shared/i18n/locales/pt-BR/tasks.json b/apps/desktop/src/shared/i18n/locales/pt-BR/tasks.json new file mode 100644 index 0000000000..4da4c0c3a7 --- /dev/null +++ b/apps/desktop/src/shared/i18n/locales/pt-BR/tasks.json @@ -0,0 +1,380 @@ +{ + "refreshTasks": "Atualizar Tarefas", + "status": { + "backlog": "Backlog", + "queue": "Fila", + "todo": "A Fazer", + "in_progress": "Em Progresso", + "review": "Revisão", + "prCreated": "PR Criado", + "complete": "Completa", + "archived": "Arquivada" + }, + "actions": { + "start": "Iniciar", + "stop": "Parar", + "recover": "Recuperar", + "resume": "Retomar", + "archive": "Arquivar", + "delete": "Excluir", + "view": "Ver Detalhes", + "viewPR": "Ver PR", + "moveTo": "Mover para", + "taskActions": "Ações da tarefa", + "selectTask": "Selecionar tarefa: {{title}}" + }, + "labels": { + "running": "Executando", + "aiReview": "Revisão IA", + "needsReview": "Precisa de Revisão", + "pending": "Pendente", + "stuck": "Travada", + "incomplete": "Incompleta", + "recovering": "Recuperando...", + "needsRecovery": "Precisa de Recuperação", + "needsResume": "Precisa Retomar", + "subtasksProgress": "{{completed}}/{{total}} subtarefas", + "subtaskProgress": "{{completed}}/{{total}} subtarefas" + }, + "reviewReason": { + "completed": "Concluída", + "hasErrors": "Tem Erros", + "qaIssues": "Problemas de QA", + "approvePlan": "Aprovar Plano", + "stopped": "Parada" + }, + "tooltips": { + "archiveTask": "Arquivar tarefa", + "archiveAllDone": "Arquivar todas as tarefas concluídas", + "viewPR": "Abrir pull request no navegador" + }, + "creation": { + "title": "Criar Nova Tarefa", + "description": "Descreva o que você quer construir", + "placeholder": "Descreva sua tarefa..." + }, + "empty": { + "title": "Nenhuma tarefa ainda", + "description": "Crie sua primeira tarefa para começar" + }, + "columns": { + "backlog": "Planejamento", + "queue": "Fila", + "in_progress": "Em Progresso", + "ai_review": "Revisão IA", + "human_review": "Revisão Humana", + "done": "Concluídas", + "pr_created": "PR Criado", + "error": "Erro" + }, + "kanban": { + "emptyBacklog": "Nenhuma tarefa planejada", + "emptyBacklogHint": "Adicione uma tarefa para começar", + "emptyQueue": "Fila vazia", + "emptyQueueHint": "Tarefas aguardarão aqui quando o limite de tarefas paralelas for atingido", + "emptyInProgress": "Nada executando", + "emptyInProgressHint": "Inicie uma tarefa do Planejamento", + "emptyAiReview": "Nenhuma tarefa em revisão", + "emptyAiReviewHint": "A IA revisará tarefas concluídas", + "emptyHumanReview": "Nada para revisar", + "emptyHumanReviewHint": "Tarefas aguardam sua aprovação aqui", + "emptyDone": "Nenhuma tarefa concluída", + "emptyDoneHint": "Tarefas aprovadas aparecem aqui", + "emptyDefault": "Sem tarefas", + "dropHere": "Solte aqui", + "showArchived": "Mostrar arquivadas", + "addTaskAriaLabel": "Adicionar nova tarefa ao backlog", + "queueAllAriaLabel": "Mover todas as tarefas para a fila", + "closeTaskDetailsAriaLabel": "Fechar detalhes da tarefa", + "editTask": "Editar tarefa", + "cannotEditWhileRunning": "Não é possível editar enquanto a tarefa está executando", + "worktreeCleanupTitle": "Limpeza de Worktree", + "worktreeCleanupStaged": "Esta tarefa foi preparada e tem uma worktree. Gostaria de limpar a worktree?", + "worktreeCleanupNotStaged": "Esta tarefa tem uma worktree com alterações que não foram mergeadas. Exclua a worktree para marcar como concluída, ou cancele para revisar as alterações primeiro.", + "keepWorktree": "Manter Worktree", + "deleteWorktree": "Excluir Worktree e Marcar como Concluída", + "refreshTasks": "Atualizar Tarefas", + "queueSettings": "Configurações da Fila", + "orderSaveFailedTitle": "Reordenação não salva", + "orderSaveFailedDescription": "A mudança na ordem das tarefas foi aplicada, mas não pôde ser salva no armazenamento. Será perdida ao atualizar.", + "selectAll": "Selecionar todas", + "deselectAll": "Desmarcar todas", + "selectedCount": "{{count}} selecionada(s)", + "selectedCountOne": "{{count}} tarefa selecionada", + "selectedCountOther": "{{count}} tarefas selecionadas", + "createPRs": "Criar PRs", + "deleteSelected": "Excluir", + "deleteConfirmTitle": "Excluir Tarefas Selecionadas", + "deleteConfirmDescription": "Tem certeza de que deseja excluir permanentemente estas tarefas?", + "deleteWarning": "Esta ação não pode ser desfeita. Todos os arquivos da tarefa, incluindo a spec, plano de implementação e qualquer código gerado serão permanentemente excluídos do projeto.", + "tasksToDelete": "Tarefas a excluir", + "deleteConfirmButton": "Excluir {{count}} Tarefas", + "deleteSuccess": "{{count}} tarefa(s) excluída(s) com sucesso", + "deleteError": "Falha ao excluir algumas tarefas", + "clearSelection": "Limpar Seleção", + "collapseColumn": "Recolher coluna", + "expandColumn": "Expandir coluna", + "resizeColumn": "Redimensionar coluna", + "lockColumn": "Travar largura da coluna", + "unlockColumn": "Destravar largura da coluna", + "columnLocked": "Largura da coluna está travada", + "expandAll": "Expandir todas as colunas" + }, + "queue": { + "limitReached": "Limite de tarefas paralelas atingido ({{current}}/{{max}}). Tarefa movida para a fila.", + "movedToQueue": "Tarefa movida para a fila.", + "autoPromoted": "Tarefa promovida automaticamente da fila para Em Progresso.", + "capacityAvailable": "{{count}} vaga(s) disponível(is) em Em Progresso.", + "queueAll": "Adicionar Todas à Fila", + "queueAllSuccess": "{{count}} tarefas movidas para a fila.", + "settings": { + "title": "Configurações da Fila", + "description": "Configure o número máximo de tarefas que podem executar em paralelo no quadro \"Em Progresso\"", + "maxParallelLabel": "Máximo de Tarefas Paralelas", + "minValueError": "Deve ser pelo menos 1", + "maxValueError": "Não pode exceder 10", + "hint": "Quando este limite for atingido, novas tarefas aguardarão na fila antes de mover para \"Em Progresso\"", + "saved": "Configurações da fila salvas", + "saveFailed": "Falha ao salvar configurações da fila", + "retry": "Por favor, tente novamente" + } + }, + "execution": { + "phases": { + "idle": "Ociosa", + "planning": "Planejando", + "coding": "Codificando", + "rate_limit_paused": "Limite de Uso", + "auth_failure_paused": "Auth Necessária", + "reviewing": "Revisando", + "fixing": "Corrigindo", + "complete": "Completa", + "failed": "Falhou" + }, + "labels": { + "interrupted": "Interrompida", + "progress": "Progresso", + "entry": "entrada", + "entries": "entradas" + }, + "shortPhases": { + "plan": "Plano", + "code": "Código", + "qa": "QA" + } + }, + "files": { + "title": "Arquivos", + "tab": "Arquivos", + "noSpecPath": "Nenhum arquivo de spec disponível", + "noFiles": "Nenhum arquivo encontrado", + "loading": "Carregando arquivos...", + "loadingContent": "Carregando conteúdo...", + "errorLoading": "Falha ao carregar arquivos", + "errorLoadingContent": "Falha ao carregar conteúdo do arquivo", + "retry": "Tentar Novamente", + "selectFile": "Selecione um arquivo para ver seu conteúdo", + "openInIDE": "Abrir na IDE" + }, + "metadata": { + "fastMode": "Rápido", + "severity": "severidade", + "pullRequest": "Pull Request", + "showMore": "Mostrar mais", + "showLess": "Mostrar menos", + "rationale": "Justificativa", + "problemSolved": "Problema Resolvido", + "targetAudience": "Público-Alvo", + "dependencies": "Dependências", + "acceptanceCriteria": "Critérios de Aceite", + "affectedFiles": "Arquivos Afetados", + "created": "Criado {{time}}", + "updated": "Atualizado {{time}}" + }, + "images": { + "removeImageAriaLabel": "Remover imagem {{filename}}", + "pasteHint": "Dica: Cole capturas de tela diretamente com {{shortcut}} para adicionar imagens de referência." + }, + "imagePreview": { + "close": "Fechar prévia", + "unavailable": "Imagem indisponível", + "description": "Prévia de {{filename}}", + "doubleClickHint": "Clique duas vezes para ampliar", + "lowResolution": "Prévia em baixa resolução" + }, + "tabs": { + "overview": "Visão Geral", + "subtasks": "Subtarefas ({{count}})", + "logs": "Logs" + }, + "notifications": { + "backgroundTaskTitle": "Tarefa continua em segundo plano", + "backgroundTaskDescription": "A tarefa ainda está executando. Você pode reabrir este diálogo para monitorar o progresso.", + "cannotResumeTitle": "Não é Possível Retomar a Tarefa", + "cannotResumeDescription": "Falha ao carregar o plano de implementação. Por favor, tente novamente ou verifique os arquivos da tarefa." + }, + "errors": { + "deleteFailed": "Falha ao excluir tarefa", + "mergeFailed": "Falha ao fazer merge das alterações", + "mergeUnknown": "Erro desconhecido durante o merge", + "discardFailed": "Falha ao descartar alterações" + }, + "wizard": { + "createTitle": "Criar Nova Tarefa", + "createDescription": "Descreva o que você quer construir. A IA analisará seu pedido e criará uma especificação detalhada.", + "descriptionPlaceholder": "Descreva a funcionalidade, correção de bug ou melhoria que você quer implementar. Seja o mais específico possível sobre requisitos, restrições e comportamento esperado. Digite @ para referenciar arquivos.", + "draftRestored": "Rascunho restaurado", + "startFresh": "Começar do Zero", + "hideFiles": "Ocultar Arquivos", + "browseFiles": "Explorar Arquivos", + "creating": "Criando...", + "createTask": "Criar Tarefa", + "worktreeNotice": { + "title": "Espaço de Trabalho Isolado", + "description": "Esta tarefa executa em uma worktree git isolada. Sua branch principal permanece segura até você escolher fazer merge." + }, + "gitOptions": { + "title": "Opções Git (opcional)", + "baseBranchLabel": "Branch Base (opcional)", + "useProjectDefault": "Usar padrão do projeto", + "useProjectDefaultWithBranch": "Usar padrão do projeto ({{branch}})", + "searchBranches": "Buscar branches...", + "noBranchesFound": "Nenhuma branch encontrada", + "helpText": "Substitua a branch a partir da qual a worktree desta tarefa será criada. Deixe vazio para usar a branch padrão configurada do projeto.", + "pushNewBranchesLabel": "Fazer push da nova branch automaticamente", + "pushNewBranchesDescription": "Publique a branch desta tarefa no GitHub e configure rastreamento upstream automaticamente. Desative para mantê-la apenas local.", + "useWorktreeLabel": "Usar espaço de trabalho isolado (recomendado)", + "useWorktreeDescription": "Cria alterações em uma worktree git separada para revisão segura antes do merge. Desative para construir diretamente no seu projeto (mais rápido, mas mais arriscado)." + }, + "errors": { + "createFailed": "Falha ao criar tarefa. Por favor, tente novamente.", + "startFailed": "Falha ao iniciar tarefa" + } + }, + "feedback": { + "dragDropHint": "Arraste e solte imagens ou cole capturas de tela", + "imageAdded": "Imagem adicionada com sucesso", + "maxImagesError": "Máximo de {{count}} imagens permitidas", + "invalidTypeError": "Tipo de imagem inválido. Permitidos: {{types}}", + "removeImage": "Remover imagem", + "processingError": "Falha ao processar imagem" + }, + "review": { + "mergeTooltip": "Faz merge das alterações da branch da worktree da tarefa de volta para sua branch base. A IA resolverá quaisquer conflitos. Você pode então escolher se mantém ou remove a worktree." + }, + "edit": { + "title": "Editar Tarefa", + "description": "Atualize os detalhes da tarefa incluindo título, descrição, classificação, imagens e configurações. As alterações serão salvas nos arquivos de spec.", + "saveChanges": "Salvar Alterações", + "errors": { + "updateFailed": "Falha ao atualizar tarefa. Por favor, tente novamente." + } + }, + "form": { + "description": "Descrição", + "descriptionPlaceholder": "Descreva a funcionalidade, correção de bug ou melhoria que você quer implementar. Seja o mais específico possível sobre requisitos, restrições e comportamento esperado.", + "imageAddedSuccess": "Imagem adicionada com sucesso!", + "taskTitle": "Título da Tarefa", + "titlePlaceholder": "Deixe vazio para gerar automaticamente a partir da descrição", + "titleHelpText": "Um título curto e descritivo será gerado automaticamente se deixado vazio.", + "classificationOptional": "Classificação (opcional)", + "requireReviewLabel": "Exigir revisão humana antes de codificar", + "requireReviewDescription": "Quando habilitado, você será solicitado a revisar a spec e o plano de implementação antes da fase de codificação começar. Isso permite aprovar, solicitar alterações ou fornecer feedback.", + "fastModeLabel": "Modo Rápido", + "fastModeDescription": "Mesmo modelo Opus 4.6 com saída mais rápida. Custo maior por token.", + "fastModeNotice": "Requer \"uso extra\" habilitado na sua assinatura do Claude.", + "errors": { + "descriptionRequired": "Por favor, forneça uma descrição", + "maxImagesReached": "Máximo de 5 imagens permitidas", + "invalidImageType": "Tipo de imagem inválido. Permitidos: PNG, JPEG, GIF, WebP", + "processPasteFailed": "Falha ao processar imagem colada", + "processDropFailed": "Falha ao processar imagem solta" + }, + "classification": { + "category": "Categoria", + "selectCategory": "Selecionar categoria", + "priority": "Prioridade", + "selectPriority": "Selecionar prioridade", + "complexity": "Complexidade", + "selectComplexity": "Selecionar complexidade", + "impact": "Impacto", + "selectImpact": "Selecionar impacto", + "helpText": "Esses rótulos ajudam a organizar e priorizar tarefas. São opcionais, mas úteis para filtragem.", + "values": { + "category": { + "feature": "Funcionalidade", + "bug_fix": "Correção de Bug", + "refactoring": "Refatoração", + "documentation": "Docs", + "security": "Segurança" + }, + "priority": { + "low": "Baixa", + "medium": "Média", + "high": "Alta", + "urgent": "Urgente" + }, + "complexity": { + "trivial": "Trivial", + "small": "Pequena", + "medium": "Média", + "large": "Grande", + "complex": "Complexa" + }, + "impact": { + "low": "Baixo Impacto", + "medium": "Médio Impacto", + "high": "Alto Impacto", + "critical": "Impacto Crítico" + } + } + } + }, + "subtasks": { + "untitled": "Subtarefa sem título", + "expandAll": "Expandir todas", + "collapseAll": "Recolher todas" + }, + "bulkPR": { + "selectAllInColumn": "Selecionar todas as tarefas na coluna", + "deselectAllInColumn": "Desmarcar todas as tarefas", + "selectionMode": "Modo de seleção ativo", + "exitSelectionMode": "Sair do modo de seleção", + "noTasksToSelect": "Nenhuma tarefa disponível para selecionar", + "confirmBulkAction": "Confirmar ação em lote para {{count}} tarefas", + "processingTasks": "Processando tarefas selecionadas..." + }, + "screenshot": { + "title": "Capturar Tela", + "description": "Selecione uma tela ou janela para capturar como imagem de referência", + "capture": "Capturar", + "capturing": "Capturando...", + "noSources": "Nenhuma tela ou janela encontrada", + "errors": { + "getSources": "Falha ao obter fontes de captura", + "fetchSources": "Falha ao buscar fontes de captura", + "capture": "Falha ao capturar tela", + "captureFailed": "Falha ao capturar tela" + }, + "devMode": { + "title": "Captura de tela indisponível", + "description": "A captura de tela não está disponível no modo de desenvolvimento devido a restrições de permissão do sistema.", + "hint": "Use uma ferramenta de captura de tela externa e cole diretamente na descrição da tarefa com {{shortcut}}." + } + }, + "deleteDialog": { + "title": "Excluir Tarefa", + "confirmMessage": "Tem certeza de que deseja excluir", + "destructiveWarning": "Esta ação não pode ser desfeita. Todos os arquivos da tarefa, incluindo a spec, plano de implementação e qualquer código gerado serão permanentemente excluídos do projeto.", + "checkingChanges": "Verificando alterações não commitadas...", + "uncommittedChanges": "A worktree desta tarefa tem {{count}} arquivo(s) não commitado(s)", + "uncommittedChangesHint": "Essas alterações não foram commitadas ou mergeadas. Excluir esta tarefa descartará permanentemente todo o trabalho não commitado na worktree.", + "cancel": "Cancelar", + "deletePermanently": "Excluir Permanentemente", + "deleting": "Excluindo..." + }, + "referenceImages": { + "title": "Imagens de Referência (opcional)", + "description": "Adicione referências visuais como capturas de tela ou designs para ajudar a IA a entender seus requisitos." + } +} diff --git a/apps/desktop/src/shared/i18n/locales/pt-BR/terminal.json b/apps/desktop/src/shared/i18n/locales/pt-BR/terminal.json new file mode 100644 index 0000000000..1f4cb93bdb --- /dev/null +++ b/apps/desktop/src/shared/i18n/locales/pt-BR/terminal.json @@ -0,0 +1,70 @@ +{ + "expand": { + "expand": "Expandir terminal", + "collapse": "Recolher terminal" + }, + "resume": { + "pending": "Retomada Disponível", + "pendingTooltip": "Clique para retomar a sessão anterior do Claude", + "resumeAllSessions": "Retomar Todas" + }, + "auth": { + "terminalTitle": "Auth: {{profileName}}", + "maxTerminalsReached": "Não é possível abrir terminal de autenticação: número máximo de terminais atingido. Feche um terminal primeiro." + }, + "swap": { + "inProgress": "Trocando perfil...", + "resumingSession": "Retomando sessão do Claude...", + "sessionResumed": "Sessão retomada com o novo perfil", + "resumeFailed": "Não foi possível retomar a sessão. Você pode iniciar uma nova sessão.", + "noSession": "Perfil trocado. Nenhuma sessão ativa para retomar.", + "migrationFailed": "Perfil trocado, mas a migração da sessão falhou. Iniciando terminal limpo." + }, + "grid": { + "title": "Terminais de Agentes", + "description": "Crie múltiplos terminais para executar agentes Claude em paralelo.\nUse Ctrl+T para criar um novo terminal.", + "newTerminal": "Novo Terminal", + "terminalCount": "{{count}} / {{max}} terminais", + "history": "Histórico", + "restoreSessionsFrom": "Restaurar sessões de...", + "sessionCount": "{{count}} sessão", + "sessionCount_plural": "{{count}} sessões", + "invokeClaudeAll": "Invocar Claude em Todos", + "clearTask": "Limpar tarefa" + }, + "worktree": { + "create": "Worktree", + "createNew": "Nova Worktree", + "existing": "Worktrees do Terminal", + "taskWorktrees": "Worktrees de Tarefas", + "otherWorktrees": "Outras", + "createTitle": "Criar Worktree do Terminal", + "createDescription": "Crie um espaço de trabalho isolado para este terminal. Todo o trabalho acontecerá no diretório da worktree.", + "name": "Nome da Worktree", + "namePlaceholder": "minha-feature", + "nameRequired": "O nome da worktree é obrigatório", + "nameInvalid": "O nome deve começar e terminar com uma letra ou número", + "nameHelp": "Letras minúsculas, números, hifens e underscores (espaços viram hifens)", + "associateTask": "Vincular à Tarefa", + "selectTask": "Selecione uma tarefa...", + "noTask": "Sem tarefa (worktree independente)", + "createBranch": "Criar Branch Git", + "branchHelp": "Cria a branch: {{branch}}", + "baseBranch": "Branch Base", + "selectBaseBranch": "Selecione a branch base...", + "searchBranch": "Buscar branches...", + "noBranchFound": "Nenhuma branch encontrada", + "useProjectDefault": "Usar padrão do projeto ({{branch}})", + "baseBranchHelp": "A branch a partir da qual a worktree será criada", + "openInIDE": "Abrir na IDE", + "maxReached": "Máximo de 12 worktrees de terminal atingido", + "alreadyExists": "Já existe uma worktree com este nome", + "searchPlaceholder": "Buscar worktrees...", + "noResults": "Nenhuma worktree encontrada", + "deleteTitle": "Excluir Worktree?", + "deleteDescription": "Isso excluirá permanentemente a worktree e sua branch. Quaisquer alterações não commitadas serão perdidas.", + "detached": "(desanexada)", + "remotePushFailed": "Rastreamento Remoto Não Configurado", + "remotePushFailedDescription": "Worktree criada, mas não foi possível fazer push da branch para o remoto. Pode ser necessário executar git push -u manualmente." + } +} diff --git a/apps/desktop/src/shared/i18n/locales/pt-BR/welcome.json b/apps/desktop/src/shared/i18n/locales/pt-BR/welcome.json new file mode 100644 index 0000000000..e65a44e79a --- /dev/null +++ b/apps/desktop/src/shared/i18n/locales/pt-BR/welcome.json @@ -0,0 +1,17 @@ +{ + "hero": { + "title": "Bem-vindo ao Aperant", + "subtitle": "Construa software de forma autônoma com agentes movidos a IA" + }, + "actions": { + "newProject": "Novo Projeto", + "openProject": "Abrir Projeto" + }, + "recentProjects": { + "title": "Projetos Recentes", + "empty": "Nenhum projeto ainda", + "emptyDescription": "Crie um novo projeto ou abra um existente para começar", + "openFolder": "Abrir Pasta", + "openProjectAriaLabel": "Abrir projeto {{name}}" + } +} diff --git a/package-lock.json b/package-lock.json index 329ca0f1c9..792f1792ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -559,6 +559,7 @@ "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", @@ -1133,6 +1134,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -1176,6 +1178,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -1215,6 +1218,7 @@ "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", "license": "MIT", + "peer": true, "dependencies": { "@dnd-kit/accessibility": "^3.1.1", "@dnd-kit/utilities": "^3.2.2", @@ -2865,6 +2869,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=8.0.0" } @@ -2886,6 +2891,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.6.0.tgz", "integrity": "sha512-L8UyDwqpTcbkIK5cgwDRDYDoEhQoj8wp8BwsO19w3LB1Z41yEQm2VJyNfAi9DrLP/YTqXqWpKHyZfR9/tFYo1Q==", "license": "Apache-2.0", + "peer": true, "engines": { "node": "^18.19.0 || >=20.6.0" }, @@ -2898,6 +2904,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.6.0.tgz", "integrity": "sha512-HLM1v2cbZ4TgYN6KEOj+Bbj8rAKriOdkF9Ed3tG25FoprSiQl7kYc+RRT6fUZGOvx0oMi5U67GoFdT+XUn8zEg==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, @@ -2913,6 +2920,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.211.0.tgz", "integrity": "sha512-h0nrZEC/zvI994nhg7EgQ8URIHt0uDTwN90r3qQUdZORS455bbx+YebnGeEuFghUT0HlJSrLF4iHw67f+odY+Q==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@opentelemetry/api-logs": "0.211.0", "import-in-the-middle": "^2.0.0", @@ -3321,6 +3329,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.6.0.tgz", "integrity": "sha512-D4y/+OGe3JSuYUCBxtH5T9DSAWNcvCb/nQWIga8HNtXTVPQn59j0nTBAgaAXxUVBDl40mG3Tc76b46wPlZaiJQ==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -3337,6 +3346,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.6.0.tgz", "integrity": "sha512-g/OZVkqlxllgFM7qMKqbPV9c1DUPhQ7d4n3pgZFcrnrNft9eJXZM2TNHTPYREJBrtNdRytYyvwjgL5geDKl3EQ==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@opentelemetry/core": "2.6.0", "@opentelemetry/resources": "2.6.0", @@ -3354,6 +3364,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.40.0.tgz", "integrity": "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==", "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=14" } @@ -5662,6 +5673,7 @@ "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -5970,6 +5982,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -5980,6 +5993,7 @@ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -6338,6 +6352,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6368,6 +6383,7 @@ "resolved": "https://registry.npmjs.org/ai/-/ai-6.0.116.tgz", "integrity": "sha512-7yM+cTmyRLeNIXwt4Vj+mrrJgVQ9RMIW5WO0ydoLoYkewIvsMcvUmqS4j2RJTUXaF1HphwmSKUMQ/HypNRGOmA==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@ai-sdk/gateway": "3.0.66", "@ai-sdk/provider": "3.0.8", @@ -6387,6 +6403,7 @@ "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -7004,6 +7021,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -8141,6 +8159,7 @@ "integrity": "sha512-glMJgnTreo8CFINujtAhCgN96QAqApDMZ8Vl1r8f0QT8QprvC1UCltV4CcWj20YoIyLZx6IUskaJZ0NV8fokcg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "app-builder-lib": "26.8.1", "builder-util": "26.8.1", @@ -8303,6 +8322,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^24.9.0", @@ -8608,16 +8628,6 @@ "node": ">= 0.8" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -9792,6 +9802,7 @@ "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.10.tgz", "integrity": "sha512-kyWP5PAiMooEvGrA9jcD3IXF7ATu8+o7B3KCbPXid5se52NPqnOpM/r9qeW2heMnOekF4kqR1fXJqCYeCLKrZg==", "license": "MIT", + "peer": true, "engines": { "node": ">=16.9.0" } @@ -9981,6 +9992,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.6" }, @@ -10373,6 +10385,7 @@ "integrity": "sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@acemir/cssom": "^0.9.28", "@asamuzakjp/dom-selector": "^6.7.6", @@ -13013,6 +13026,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -13313,6 +13327,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -13322,6 +13337,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -14866,6 +14882,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -15205,6 +15222,7 @@ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -15797,6 +15815,7 @@ "integrity": "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/expect": "4.1.0", "@vitest/mocker": "4.1.0", @@ -16251,6 +16270,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" }