feat(electrobun): i18n system — @formatjs/intl + Svelte 5 runes + 3 locales
- i18n.svelte.ts: store with $state locale + createIntl(), t() function, formatDate/Number/RelativeTime, getDir() for RTL, async setLocale() - i18n.types.ts: TranslationKey union (codegen from en.json) - locales/en.json: 200+ strings in ICU MessageFormat - locales/pl.json: full Polish translation - locales/ar.json: partial Arabic (validates 6-form plural + RTL) - scripts/i18n-types.ts: codegen script for type-safe keys - 6 components wired: StatusBar, AgentPane, CommandPalette, SettingsDrawer, SplashScreen, ChatInput - Language selector in AppearanceSettings - App.svelte: document.dir reactive for RTL - CONTRIBUTING_I18N.md: guide for adding languages Note: currently Electrobun-only. Will extract to @agor/i18n shared package for both Tauri and Electrobun.
This commit is contained in:
parent
eee65070a8
commit
aae86a4001
16 changed files with 947 additions and 64 deletions
|
|
@ -4,6 +4,7 @@
|
|||
getAttentionQueue,
|
||||
type ProjectHealth,
|
||||
} from './health-store.svelte.ts';
|
||||
import { t } from './i18n.svelte.ts';
|
||||
|
||||
interface Props {
|
||||
projectCount: number;
|
||||
|
|
@ -60,21 +61,21 @@
|
|||
<span class="status-segment">
|
||||
<span class="dot green pulse-dot" aria-hidden="true"></span>
|
||||
<span class="val">{health.running}</span>
|
||||
<span>running</span>
|
||||
<span>{t('statusbar.running')}</span>
|
||||
</span>
|
||||
{/if}
|
||||
{#if health.idle > 0}
|
||||
<span class="status-segment">
|
||||
<span class="dot gray" aria-hidden="true"></span>
|
||||
<span class="val">{health.idle}</span>
|
||||
<span>idle</span>
|
||||
<span>{t('statusbar.idle')}</span>
|
||||
</span>
|
||||
{/if}
|
||||
{#if health.stalled > 0}
|
||||
<span class="status-segment stalled">
|
||||
<span class="dot orange" aria-hidden="true"></span>
|
||||
<span class="val">{health.stalled}</span>
|
||||
<span>stalled</span>
|
||||
<span>{t('statusbar.stalled')}</span>
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
|
|
@ -84,11 +85,11 @@
|
|||
class="status-segment attn-btn"
|
||||
class:attn-open={showAttention}
|
||||
onclick={() => showAttention = !showAttention}
|
||||
title="Needs attention"
|
||||
title={t('statusbar.needsAttention')}
|
||||
>
|
||||
<span class="dot orange pulse-dot" aria-hidden="true"></span>
|
||||
<span class="val">{attentionQueue.length}</span>
|
||||
<span>attention</span>
|
||||
<span>{t('statusbar.attention')}</span>
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
|
|
@ -96,32 +97,32 @@
|
|||
|
||||
<!-- Right: aggregates -->
|
||||
{#if health.totalBurnRatePerHour > 0}
|
||||
<span class="status-segment burn" title="Burn rate">
|
||||
<span class="status-segment burn" title={t('statusbar.burnRate')}>
|
||||
<span class="val">{formatRate(health.totalBurnRatePerHour)}</span>
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
<span class="status-segment" title="Active group">
|
||||
<span class="status-segment" title={t('statusbar.activeGroup')}>
|
||||
<span class="val">{groupName}</span>
|
||||
</span>
|
||||
<span class="status-segment" title="Projects">
|
||||
<span class="status-segment" title={t('statusbar.projects')}>
|
||||
<span class="val">{projectCount}</span>
|
||||
<span>projects</span>
|
||||
<span>{t('statusbar.projects')}</span>
|
||||
</span>
|
||||
<span class="status-segment" title="Session duration">
|
||||
<span>session</span>
|
||||
<span class="status-segment" title={t('statusbar.session')}>
|
||||
<span>{t('statusbar.session')}</span>
|
||||
<span class="val">{sessionDuration}</span>
|
||||
</span>
|
||||
<span class="status-segment" title="Total tokens">
|
||||
<span>tokens</span>
|
||||
<span class="status-segment" title={t('statusbar.tokens')}>
|
||||
<span>{t('statusbar.tokens')}</span>
|
||||
<span class="val">{fmtTokens(totalTokens)}</span>
|
||||
</span>
|
||||
<span class="status-segment" title="Total cost">
|
||||
<span>cost</span>
|
||||
<span class="status-segment" title={t('statusbar.cost')}>
|
||||
<span>{t('statusbar.cost')}</span>
|
||||
<span class="val cost">{fmtCost(totalCost)}</span>
|
||||
</span>
|
||||
|
||||
<kbd class="palette-hint" title="Search (Ctrl+Shift+F)">Ctrl+Shift+F</kbd>
|
||||
<kbd class="palette-hint" title={t('statusbar.search')}>Ctrl+Shift+F</kbd>
|
||||
</footer>
|
||||
|
||||
<!-- Attention dropdown -->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue