Files
arboretum/packages/web/src/i18n/en.ts
Johan LEROY 92670a796a feat(p9): commit/push avancé dans l'IDE (staging sélectif, discard, amend, fetch/pull)
- components/workspace/CommitPanel.vue : staging sélectif par fichier (stage/unstage/stage all/unstage all), discard avec confirmation (includeUntracked), zone de commit (message + amend), commit mode 'staged', push, fetch, pull --ff-only (rebase proposé en cas de divergence), gestion 409 ALREADY_PUSHED
- components/workspace/FileRow.vue : ligne de fichier réutilisable (badge statut M/A/D/?/U + clic → diff + slot actions)
- WorkspaceView : CommitPanel remplace ChangedFilesPanel ; @changed → reload des changements
- stores/worktrees : applyWorktree (upsert depuis les mutations git → header live)
- i18n EN+FR (commit.*) ; acceptance-p9.mjs (staging sélectif, amend OK/409, pull ff-only OK + divergence refusée)
2026-06-27 13:53:05 +02:00

518 lines
16 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export default {
common: {
appName: 'Arboretum',
loading: 'Loading…',
cancel: 'Cancel',
logout: 'Log out',
language: 'Language',
refresh: 'Refresh',
back: 'Back',
search: 'Search',
settings: 'Settings',
close: 'Close',
retry: 'Retry',
},
login: {
title: 'Sign in with your access token',
tokenLabel: 'Access token',
tokenPlaceholder: 'arb_…',
submit: 'Sign in',
submitting: 'Signing in…',
invalidToken: 'Invalid token',
rateLimited: 'Too many attempts — please wait before retrying',
genericError: 'Sign-in failed ({status})',
},
sessions: {
title: 'Sessions',
refresh: 'Refresh',
empty: 'No sessions yet — start one below.',
newSession: 'New session',
cwdLabel: 'Working directory',
cwdPlaceholder: '/absolute/path/to/project',
commandLabel: 'Command',
creating: 'Creating…',
open: 'Open',
observe: 'Observe',
view: 'View',
resume: 'Resume',
fork: 'Fork',
kill: 'Kill',
confirmKill: 'Confirm kill',
live: 'live',
resumable: 'resumable',
sourceDiscovered: 'discovered',
hide: 'Hide',
unhide: 'Unhide',
hiddenBadge: 'hidden',
hideDiscovered: 'Hide external history',
showHidden: 'Show hidden',
hideHidden: 'Hide hidden',
archive: 'Archive',
unarchive: 'Unarchive',
archivedBadge: 'archived',
showArchived: 'Show archived',
hideArchived: 'Hide archived',
clients: 'no client | 1 client | {n} clients',
exitCode: 'exit code {code}',
statusLabel: {
starting: 'starting',
running: 'running',
exited: 'exited',
},
registryStatus: {
busy: 'busy',
idle: 'available',
waiting: 'waiting',
},
dialog: {
waiting: 'Waiting for your input',
deny: 'Deny (Esc)',
kind: {
trust: 'Trust',
permission: 'Permission',
question: 'Question',
plan: 'Plan',
},
},
},
dashboard: {
title: 'Worktrees',
allSessions: 'All sessions',
groups: 'Groups',
},
groups: {
title: 'Groups',
new: 'New group',
create: 'Create',
creating: 'Creating…',
nameLabel: 'Group name',
namePlaceholder: 'e.g. Payments stack',
colorLabel: 'Color',
reposLabel: 'Repositories',
empty: 'No group yet — create one above.',
noRepos: 'No repository selected.',
noReposInGroup: 'No repository in this group yet — add some below.',
noReposRegistered: 'No repository registered yet — add some from the dashboard first.',
open: 'Open',
edit: 'Edit repositories',
editDone: 'Done',
remove: 'Delete',
confirmDelete: 'Confirm delete',
repoCount: 'no repo | 1 repo | {n} repos',
dashboard: 'Dashboard',
missingRepo: 'Repository unavailable',
removeFromGroup: 'Remove from group',
sessionsActive: 'no active session | 1 active session | {n} active sessions',
viewList: 'Repos',
viewGrid: 'Terminals',
gridEmpty: 'No active session in this group.',
gridCapped: 'Showing {shown} of {total} sessions — close some terminals to see the rest.',
newFeature: 'New group session',
spanBadge: 'group · {n} repo | group · {n} repos',
},
crossRepo: {
title: 'New group session',
intro: 'Launch one Claude session that spans every repo in this group — a single conversation across all of them.',
modeLabel: 'Directories',
modeFeature: 'New branch in each repo',
modeMain: 'Main checkouts',
branchLabel: 'Branch name',
branchPlaceholder: 'feature/…',
branchHint: 'Created where missing, reused where it already exists in the repo.',
baseRefLabel: 'Base branch (optional)',
baseRefPlaceholder: "repo's default branch",
commandLabel: 'Session',
reposLabel: 'Repos in this session',
launch: 'Launch session',
launching: 'Launching…',
close: 'Close',
ok: 'worktree ready',
error: 'failed',
skippedLabel: 'skipped',
done: 'Group session started.',
sessionFailed: 'Could not start the session.',
},
repos: {
add: 'Add repo',
adding: 'Adding…',
remove: 'Remove',
pathLabel: 'Repository path',
pathPlaceholder: '/absolute/path/to/repo',
empty: 'No repository registered yet — add one above, or scan for repos.',
invalid: 'unavailable',
scan: 'Scan',
scanResult: 'No new repository found | 1 new repository added | {n} new repositories added',
hide: 'Hide',
show: 'Show',
showHidden: 'Show hidden ({n})',
},
worktrees: {
new: 'New worktree',
create: 'Create',
creating: 'Creating…',
branch: 'Branch',
newBranch: 'create branch',
baseRefLabel: 'Base branch',
baseRefPlaceholder: 'default branch',
start: 'Start',
starting: 'Starting…',
startNone: 'no session',
startWork: 'Start work',
modeLabel: 'Mode',
modeWorktree: 'Worktree',
modeMain: 'Main branch',
branchModeLabel: 'Branch',
currentBranch: 'current branch',
newBranchOpt: 'new branch',
commandLabel: 'Command',
delete: 'Delete',
confirmDelete: 'Confirm delete',
forceDelete: 'Force delete',
prune: 'Prune',
commit: 'Commit',
commitPlaceholder: 'Commit message',
committing: 'Committing…',
push: 'Push',
pushing: 'Pushing…',
promote: 'Make main',
promoting: 'Promoting…',
promoteConfirm:
'Branch “{branch}” will become the repositorys main checkout; this worktree will be removed (the previous main branch is kept). Continue?',
forcePromote: 'Force (dirty tree)',
main: 'main',
detached: 'detached',
locked: 'locked',
prunable: 'prunable',
clean: 'clean',
dirty: '{n} changed',
noSession: 'no session',
externalSessions: 'external',
showExternalSessions: 'Show external sessions ({n})',
},
project: {
new: 'New project',
title: 'New project',
intro: 'Creates a new folder under the chosen root, then starts a session in it.',
nameLabel: 'Project name',
namePlaceholder: 'my-project',
rootLabel: 'Root folder',
rootPlaceholder: '/absolute/path/root',
gitInit: 'Initialize a git repository (git init)',
commandLabel: 'Command',
create: 'Create',
creating: 'Creating…',
},
workspace: {
open: 'Open IDE',
files: 'Files',
changes: 'Changes',
noChanges: 'No changes',
changesTruncated: 'Too many changes — list truncated.',
terminal: 'Terminal',
editor: 'Editor',
diff: 'Diff',
noFileOpen: 'No file open',
noFileHint: 'Pick a file in the tree to edit it, or a changed file to view its diff.',
noSession: 'No session here',
noSessionHint: 'Start a session on this worktree from the dashboard to get a terminal.',
},
editor: {
save: 'Save',
unsaved: 'Unsaved changes',
conflict: 'This file changed on disk since you opened it.',
reload: 'Reload',
overwrite: 'Overwrite',
},
diff: {
binary: 'Binary file — no text diff.',
tooLarge: 'Diff too large to display.',
noChanges: 'No changes in this file.',
},
git: {
ahead: 'commits ahead',
behind: 'commits behind',
staged: 'staged',
unstaged: 'unstaged',
conflicts: 'conflicts',
},
commit: {
staged: 'Staged',
changes: 'Changes',
stage: 'Stage',
unstage: 'Unstage',
stageAll: 'Stage all',
unstageAll: 'Unstage all',
discard: 'Discard',
confirmDiscard: 'Confirm discard (destructive)',
amend: 'Amend last commit',
amendPlaceholder: 'New message (leave empty to keep the previous one)',
messagePlaceholder: 'Commit message…',
commit: 'Commit',
push: 'Push',
fetch: 'Fetch',
pull: 'Pull (fast-forward)',
pullRebase: 'Pull --rebase',
alreadyPushed: 'Cannot amend: this commit was already pushed.',
},
terminal: {
observer: 'observer (read-only)',
sessionEnded: 'Session ended',
back: 'Sessions',
notAttachable: 'This session runs outside Arboretum — fork it to interact, or resume it once it has stopped.',
fullscreen: 'Fullscreen',
exitFullscreen: 'Exit fullscreen',
maximize: 'Maximize',
restore: 'Restore',
openFullscreen: 'Open fullscreen',
group: 'Group',
covers: 'covers',
},
push: {
enable: 'Enable notifications',
disable: 'Notifications on',
denied: 'Notification permission denied — enable it in your browser settings.',
unsupported: 'Push needs HTTPS (e.g. Tailscale Serve); on iOS, install the app to your home screen first.',
},
fs: {
browse: 'Browse…',
up: 'Up',
useFolder: 'Use this folder',
showHidden: 'Show hidden',
loading: 'Loading…',
empty: 'No subfolders',
repoBadge: 'repo',
},
ws: {
reconnecting: 'Connection lost — reconnecting…',
},
nav: {
worktrees: 'Worktrees',
sessions: 'Sessions',
groups: 'Groups',
settings: 'Settings',
help: 'Help',
more: 'More',
gitea: 'Source code',
buymeacoffee: 'Buy me a coffee',
waiting: 'waiting',
},
controls: {
searchPlaceholder: 'Search…',
results: 'no result | 1 result | {n} results',
sortBy: 'Sort by',
filters: 'Filters',
clearAll: 'Clear',
},
sort: {
asc: 'Ascending',
desc: 'Descending',
session: {
state: 'State',
recent: 'Most recent',
clients: 'Clients',
cwd: 'Directory',
command: 'Command',
},
worktree: {
main: 'Main first',
branch: 'Branch',
dirty: 'Changes',
ahead: 'Ahead',
behind: 'Behind',
activity: 'Activity',
},
repo: {
label: 'Name',
created: 'Created',
worktrees: 'Worktrees',
activity: 'Activity',
},
group: {
label: 'Name',
created: 'Created',
repos: 'Repositories',
activeSessions: 'Active sessions',
},
},
filter: {
state: {
label: 'State',
live: 'Live',
waiting: 'Waiting',
busy: 'Busy',
idle: 'Available',
exited: 'Exited',
resumable: 'Resumable',
},
command: {
label: 'Command',
},
source: {
label: 'Source',
managed: 'Managed',
discovered: 'Discovered',
},
repo: {
label: 'Repository',
},
worktree: {
dirtiness: 'Changes',
dirty: 'Dirty',
clean: 'Clean',
session: 'Session',
with: 'With session',
without: 'Without session',
flags: 'Flags',
locked: 'Locked',
prunable: 'Prunable',
},
},
pagination: {
prev: 'Previous',
next: 'Next',
pageOf: 'Page {page} / {pageCount}',
perPage: 'Per page',
all: 'All',
},
palette: {
placeholder: 'Jump to repo, worktree, session, group…',
empty: 'No match',
hint: '↑↓ navigate · ↵ open · esc close',
types: {
repo: 'Repo',
worktree: 'Worktree',
session: 'Session',
group: 'Group',
action: 'Action',
},
actions: {
newSession: 'New session',
addRepo: 'Add repo',
newGroup: 'New group',
},
},
toast: {
sessionCreated: 'Session started',
sessionKilled: 'Session killed',
sessionResumed: 'Session resumed',
sessionForked: 'Session forked',
sessionHidden: 'Session hidden',
sessionUnhidden: 'Session shown',
sessionsHidden: 'no session hidden | 1 session hidden | {n} sessions hidden',
sessionArchived: 'Session archived',
sessionUnarchived: 'Session unarchived',
repoAdded: 'Repository added',
repoRemoved: 'Repository removed',
worktreeCreated: 'Worktree created',
worktreeDeleted: 'Worktree deleted',
pruned: 'Worktrees pruned',
groupCreated: 'Group created',
groupUpdated: 'Group updated',
groupDeleted: 'Group deleted',
groupSessionLaunched: 'Group session started',
groupSessionPartial: 'Group session started ({n} repo(s) skipped)',
projectCreated: 'Project created',
genericError: 'Something went wrong',
dismiss: 'Dismiss',
},
attention: {
title: 'Needs attention',
count: 'no session waiting | 1 session waiting | {n} sessions waiting',
empty: 'Nothing waiting',
},
settings: {
title: 'Settings',
// Préférences
preferences: 'Preferences',
preferencesHint: 'These apply to this browser only.',
language: 'Language',
notifications: 'Notifications',
notificationsEnabled: 'Enabled — you will be notified when a session needs input.',
notificationsDisabled: 'Disabled.',
enableNotifications: 'Enable notifications',
disableNotifications: 'Disable notifications',
testNotification: 'Send a test',
testSent: 'Test notification sent',
pushUnsupported: 'Push needs HTTPS (e.g. Tailscale Serve); on iOS, install the app to your home screen first.',
// Accès & sécurité
security: 'Access & security',
securityHint: 'Tokens grant full access to this server. Create one per device and revoke any you no longer use.',
tokens: 'Access tokens',
newTokenLabel: 'Label',
newTokenPlaceholder: 'e.g. phone, laptop',
createToken: 'Create token',
tokenCreated: 'Token created',
copyTokenHint: 'Copy this token now — for security it will never be shown again.',
copy: 'Copy',
copied: 'Copied',
current: 'current',
created: 'Created {date}',
lastUsed: 'last used {date}',
neverUsed: 'never used',
revoke: 'Revoke',
confirmRevoke: 'Confirm revoke',
tokenRevoked: 'Token revoked',
lastTokenError: 'You cannot revoke the last active token — create another one first.',
save: 'Save',
saved: 'Saved',
// Sécurité & conformité
compliance: 'Security & compliance',
complianceHint: 'Export or erase the data tied to your token (GDPR), and review the audit log of sensitive operations.',
exportData: 'Export my data',
refreshAudit: 'Audit log',
deleteData: 'Erase my data',
deleteConfirm: 'Erase the data tied to your token (push subscriptions) and revoke this token? This cannot be undone.',
deleteDone: 'Your data has been erased.',
// Découverte des dépôts
discovery: 'Repository discovery',
discoveryHint: 'Arboretum scans these folders for git repositories and registers them automatically. Hidden repos are kept and never re-added.',
scanRoots: 'Scan folders',
scanRootsEmpty: 'No folder configured — your home directory is used by default.',
addRoot: 'Add folder',
removeRoot: 'Remove',
scanInterval: 'Re-scan interval (minutes)',
scanIntervalHint: '0 disables periodic scanning. Changes apply on the next daemon restart.',
// Sessions (rétention / archivage auto)
sessions: 'Sessions',
sessionsHint: 'Finished sessions older than the retention window are automatically archived (hidden from the list by default). Nothing is deleted — archived sessions stay resumable and forkable.',
retentionDays: 'Auto-archive after (days)',
retentionDaysHint: '0 never archives. Archived sessions are hidden by default; toggle "Show archived" in the sessions list to see them.',
// Claude CLI
claudeCli: 'Claude CLI',
claudeCliHint: 'Where Arboretum finds the `claude` binary and its data. Handy when the daemon runs as a service with a minimal PATH that does not include ~/.local/bin.',
claudeBinStatusOk: 'Detected',
claudeBinStatusNotFound: 'Not found — sessions cannot start until this is resolved.',
claudeBinStatusBadPath: 'The configured path is not an executable file.',
claudeBinSourceConfigured: 'configured',
claudeBinSourcePath: 'PATH',
claudeBinPathLabel: 'Binary path override',
claudeBinPathHint: 'Absolute path to the `claude` executable. Leave empty to auto-detect via PATH. Takes effect on the next session.',
claudeBinPathPlaceholder: 'e.g. /home/you/.local/bin/claude',
claudeHomeLabel: 'Claude home directory',
claudeHomeHint: 'Override the ~/.claude location (transcripts & session registry). Applies on the next daemon restart.',
claudeHomePlaceholder: 'e.g. /home/you/.claude',
// Serveur (lecture seule)
server: 'Server',
serverHint: 'Set at startup via CLI flags — changing them requires restarting the daemon.',
version: 'Version',
port: 'Port',
bind: 'Bind address',
allowedOrigins: 'Allowed origins',
dataDir: 'Data directory',
vapidPublicKey: 'VAPID public key',
vapidContact: 'VAPID contact',
none: 'none',
flagHint: 'CLI flag: {flag}',
// Support
support: 'Support',
supportHint: 'Arboretum is a free, self-funded side project. If it saves you time, you can support its development.',
supportCta: 'Buy me a coffee',
},
help: {
title: 'Help',
intro: 'Everything Arboretum can do, and how to use it.',
searchPlaceholder: 'Search help…',
noMatch: 'No matching topic',
},
};