Files
arboretum/packages/web/src/i18n/en.ts
Johan LEROY c88ae9b2ae feat: clean install (Gitea en dur, scan off) + durcissement sécurité entreprise
Gitea
- lien « Code source » hardcodé (REPO_SOURCE_URL) vers le dépôt, toujours visible
- retrait complet du réglage configurable (api.ts, route+store settings, SettingsView, i18n, help, tests)

Découverte des dépôts
- aucune racine de scan par défaut → pas de scan au premier démarrage (clean install)
- corrige la découverte des dépôts à l'INTÉRIEUR d'une racine qui est elle-même un repo
  (depth 0 = conteneur de scan, on descend ; depth > 0 = feuille)

Sécurité « enterprise-deployable »
- en-têtes HTTP durcis (CSP, X-Frame-Options, nosniff, Referrer-Policy, HSTS conditionnel, no-store API), header Server retiré
- permissions DB 0o600 / dossier de données 0o700 ; error handler sanitisé ; garde Content-Type sur les mutations
- chiffrement au repos AES-256-GCM des secrets (server_secret, clé privée VAPID) via SecretBox
- journal d'audit (migration #7) + endpoint /audit-logs + RGPD export/effacement + UI Réglages
- SECURITY.md, docs/ENTERPRISE_DEPLOYMENT.md, sections README EN/FR, SBOM CycloneDX en CI

CI
- pack-smoke packe depuis le contexte du package (cd packages/server) au lieu de « npm pack -w » :
  corrige l'embarquement de @arboretum/shared dans le tarball

Purge des données personnelles du dépôt public
- suppression de spikes/s4-discovery/result.json, reformulation du VERDICT
- chemin de test générique, anonymisation des 5 fixtures de dialogues

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:44:25 +02:00

375 lines
11 KiB
TypeScript

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',
clients: 'no client | 1 client | {n} clients',
exitCode: 'exit code {code}',
statusLabel: {
starting: 'starting',
running: 'running',
exited: 'exited',
},
registryStatus: {
busy: 'busy',
idle: 'idle',
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 cross-repo feature',
},
crossRepo: {
title: 'New cross-repo feature',
intro: 'Create the same worktree across the selected repos, in one action.',
branchLabel: 'Branch name',
branchPlaceholder: 'feature/…',
newBranch: 'create branch',
baseRefLabel: 'Base ref (optional)',
startLabel: 'Start session',
startNone: 'no session',
reposLabel: 'Apply to',
create: 'Create across {n} repos',
creating: 'Creating…',
retryFailed: 'Retry failed',
close: 'Close',
pending: 'pending…',
ok: 'created',
error: 'failed',
},
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',
start: 'Start',
startNone: 'no session',
delete: 'Delete',
confirmDelete: 'Confirm delete',
forceDelete: 'Force delete',
prune: 'Prune',
main: 'main',
detached: 'detached',
locked: 'locked',
prunable: 'prunable',
clean: 'clean',
dirty: '{n} changed',
noSession: 'no session',
},
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.',
},
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',
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: 'Idle',
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',
repoAdded: 'Repository added',
repoRemoved: 'Repository removed',
worktreeCreated: 'Worktree created',
worktreeDeleted: 'Worktree deleted',
pruned: 'Worktrees pruned',
groupCreated: 'Group created',
groupUpdated: 'Group updated',
groupDeleted: 'Group deleted',
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.',
// 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}',
},
help: {
title: 'Help',
intro: 'Everything Arboretum can do, and how to use it.',
searchPlaceholder: 'Search help…',
noMatch: 'No matching topic',
},
};