feat(web): add i18n support with FR/EN locales and keyboard layout awareness
All checks were successful
Beta Release / beta (push) Successful in 36s
All checks were successful
Beta Release / beta (push) Successful in 36s
Add full internationalization system with React context, French/English translations, and AZERTY/QWERTY keyboard layout support. Dashboard now uses a tabbed layout (Tools, Notifications, Workflows). Config page exposes language and keyboard preferences persisted via new /api/preferences endpoint. 💕 Generated with Crush Assisted-by: GLM-5-Turbo via Crush <crush@charm.land>
This commit is contained in:
@@ -168,6 +168,12 @@ input::placeholder { color: var(--text-disabled); }
|
||||
color: var(--text-disabled);
|
||||
}
|
||||
.statusbar-left, .statusbar-right { display: flex; align-items: center; gap: 12px; }
|
||||
.statusbar-shortcut { display: inline-flex; align-items: center; gap: 4px; }
|
||||
.statusbar-shortcut kbd {
|
||||
display: inline-block; padding: 1px 5px; border-radius: 3px;
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
font-family: var(--font-mono); font-size: 10px; color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
.card {
|
||||
background: var(--bg-card);
|
||||
@@ -328,6 +334,60 @@ input::placeholder { color: var(--text-disabled); }
|
||||
|
||||
.empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 40px 20px; color: var(--text-disabled); font-size: 13px; text-align: center; gap: 8px; }
|
||||
|
||||
.dashboard-layout { display: flex; flex-direction: column; height: 100%; }
|
||||
.dashboard-tabs {
|
||||
display: flex; gap: 0; border-bottom: 1px solid var(--border);
|
||||
background: var(--bg-surface); flex-shrink: 0;
|
||||
}
|
||||
.dashboard-tab {
|
||||
padding: 10px 24px; font-size: 13px; font-weight: 600;
|
||||
color: var(--text-tertiary); cursor: pointer; transition: all 0.15s;
|
||||
display: flex; align-items: center; gap: 8px; border-bottom: 2px solid transparent;
|
||||
user-select: none;
|
||||
}
|
||||
.dashboard-tab:hover { color: var(--text-primary); background: var(--bg-card); }
|
||||
.dashboard-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
|
||||
.tab-count {
|
||||
font-size: 10px; padding: 1px 6px; border-radius: 99px;
|
||||
background: var(--bg-card); color: var(--text-tertiary); font-family: var(--font-mono);
|
||||
}
|
||||
.tab-count.warn { background: rgba(255,215,64,0.15); color: var(--warning); }
|
||||
|
||||
.dashboard-content { flex: 1; overflow-y: auto; }
|
||||
|
||||
.dashboard-tools { padding: 16px 24px; }
|
||||
.tools-compact { display: flex; flex-direction: column; gap: 2px; }
|
||||
.tool-compact-row {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 6px 12px; border-radius: var(--radius);
|
||||
font-size: 13px; transition: background 0.1s;
|
||||
}
|
||||
.tool-compact-row:hover { background: var(--bg-card); }
|
||||
.badge.sm { padding: 1px 5px; font-size: 10px; }
|
||||
.tool-compact-name { color: var(--text-primary); font-weight: 500; flex: 1; }
|
||||
.tool-compact-ver { color: var(--text-tertiary); font-size: 11px; font-family: var(--font-mono); }
|
||||
.tool-compact-installed { color: var(--success); font-size: 11px; font-family: var(--font-mono); opacity: 0.7; }
|
||||
|
||||
.dashboard-notifications { padding: 16px 24px; }
|
||||
.notif-row {
|
||||
display: flex; align-items: flex-start; gap: 12px;
|
||||
padding: 8px 12px; border-radius: var(--radius); margin-bottom: 4px;
|
||||
}
|
||||
.notif-row:hover { background: var(--bg-card); }
|
||||
.notif-time { color: var(--text-disabled); font-size: 11px; font-family: var(--font-mono); flex-shrink: 0; padding-top: 1px; }
|
||||
.notif-text { font-size: 13px; color: var(--text-secondary); }
|
||||
.notif-info .notif-text { color: var(--info); }
|
||||
.notif-ok .notif-text { color: var(--success); }
|
||||
.notif-warn .notif-text { color: var(--warning); }
|
||||
.notif-error .notif-text { color: var(--error); }
|
||||
|
||||
.dashboard-workflows { padding: 16px 24px; display: flex; flex-direction: column; gap: 24px; }
|
||||
.workflow-section { }
|
||||
.section-label {
|
||||
font-size: 11px; font-weight: 700; color: var(--accent); text-transform: uppercase;
|
||||
letter-spacing: 1px; margin-bottom: 12px; padding-bottom: 6px; border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.panel-header {
|
||||
display: flex; align-items: center; justify-content: space-between; padding: 10px 16px;
|
||||
border-bottom: 1px solid var(--border); background: var(--bg-surface);
|
||||
|
||||
Reference in New Issue
Block a user