diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 1277999..d314893 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -2330,8 +2330,8 @@ export default function App() { { type: 'item', label: ctyRefreshing ? 'Refreshing cty.dat…' : 'Refresh cty.dat', action: 'tools.refreshCty', disabled: ctyRefreshing }, { type: 'item', label: refsDownloading ? 'Downloading reference lists…' : 'Download reference lists (IOTA/POTA/WWFF/SOTA)', action: 'tools.downloadRefs', disabled: refsDownloading }, ]}, - { name: 'help', label: 'Help', items: [ - { type: 'item', label: 'About OpsLog', action: 'help.about' }, + { name: 'help', label: t('menu.help'), items: [ + { type: 'item', label: t('help.about'), action: 'help.about' }, ]}, ], [total, selectedId, selectedIds, ctyRefreshing, refsDownloading, exporting, wkEnabled, dvkEnabled, cwEnabled, netEnabled, t]); diff --git a/frontend/src/components/AdifExtrasEditor.tsx b/frontend/src/components/AdifExtrasEditor.tsx index fd9c03c..eeda9ed 100644 --- a/frontend/src/components/AdifExtrasEditor.tsx +++ b/frontend/src/components/AdifExtrasEditor.tsx @@ -4,6 +4,7 @@ import { ADIFFields } from '../../wailsjs/go/main/App'; import { Input } from '@/components/ui/input'; import { Combobox } from '@/components/ui/combobox'; import { Button } from '@/components/ui/button'; +import { useI18n } from '@/lib/i18n'; type FieldDef = { name: string; kind: string; category: string; @@ -21,6 +22,7 @@ interface Props { // ADIF 3.1.7 field (plus custom/vendor tags) can be viewed and edited. This is // what makes "100% of ADIF fields available" true without 160 DB columns. export function AdifExtrasEditor({ value, onChange }: Props) { + const { t } = useI18n(); const [dict, setDict] = useState([]); const [showDeprecated, setShowDeprecated] = useState(false); @@ -68,9 +70,7 @@ export function AdifExtrasEditor({ value, onChange }: Props) { return (

- Every ADIF 3.1.7 field not shown in the other tabs. Pick a field to add it, - or type a custom/vendor tag (e.g. APP_*). - Stored losslessly and exported in the full ADIF mode. + {t('adx.introPart1')}APP_*{t('adx.introPart2')}{t('adx.fullMode')}{t('adx.introPart3')}

{/* Add a field */} @@ -79,21 +79,21 @@ export function AdifExtrasEditor({ value, onChange }: Props) {
{/* Current entries */} {entries.length === 0 ? (
- No extra ADIF fields. Use the picker above to add one. + {t('adx.noExtra')}
) : (
@@ -105,11 +105,11 @@ export function AdifExtrasEditor({ value, onChange }: Props) { {k} {def && ( - {def.category}{def.deprecated ? ' · deprecated' : ''}{def.intl ? ' · intl' : ''} + {def.category}{def.deprecated ? ' · ' + t('adx.deprecated') : ''}{def.intl ? ' · ' + t('adx.intl') : ''} {!def && ''} )} - {!def && non-standard} + {!def && {t('adx.nonStandard')}}
diff --git a/frontend/src/components/AlertsModal.tsx b/frontend/src/components/AlertsModal.tsx index 4dcbebc..3ebac8c 100644 --- a/frontend/src/components/AlertsModal.tsx +++ b/frontend/src/components/AlertsModal.tsx @@ -9,6 +9,7 @@ import { Label } from '@/components/ui/label'; import { Checkbox } from '@/components/ui/checkbox'; import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'; import { cn } from '@/lib/utils'; +import { useI18n } from '@/lib/i18n'; import { ListAlertRules, SaveAlertRule, DeleteAlertRule, GetAlertEmailTo, SetAlertEmailTo, } from '@/../wailsjs/go/main/App'; @@ -32,6 +33,7 @@ function emptyRule(): Rule { function MultiCheck({ options, selected, onToggle, searchable, height = 'h-52' }: { options: string[]; selected: string[]; onToggle: (v: string) => void; searchable?: boolean; height?: string; }) { + const { t } = useI18n(); const [q, setQ] = useState(''); const shown = useMemo( () => (q ? options.filter((o) => o.toLowerCase().includes(q.toLowerCase())) : options), @@ -43,7 +45,7 @@ function MultiCheck({ options, selected, onToggle, searchable, height = 'h-52' } {searchable && (
- setQ(e.target.value)} /> + setQ(e.target.value)} />
)}
@@ -53,10 +55,10 @@ function MultiCheck({ options, selected, onToggle, searchable, height = 'h-52' } {o} ))} - {shown.length === 0 &&
no match
} + {shown.length === 0 &&
{t('altm.noMatch')}
}
- {(selected?.length ?? 0) === 0 ? 'none selected = ALL' : `${selected!.length} selected`} + {(selected?.length ?? 0) === 0 ? t('altm.noneAll') : t('altm.nSelected', { n: selected!.length })}
); @@ -65,6 +67,7 @@ function MultiCheck({ options, selected, onToggle, searchable, height = 'h-52' } export function AlertsModal({ onClose, bands, modes, countries }: { onClose: () => void; bands: string[]; modes: string[]; countries: string[]; }) { + const { t } = useI18n(); const [rules, setRules] = useState([]); const [draft, setDraft] = useState(null); const [tab, setTab] = useState('def'); // active editor tab (reset to Definition on new/select) @@ -88,14 +91,14 @@ export function AlertsModal({ onClose, bands, modes, countries }: { async function save() { if (!draft) return; - if (!draft.name.trim()) { setErr('Give the rule a name'); return; } + if (!draft.name.trim()) { setErr(t('altm.giveName')); return; } try { const saved = await SaveAlertRule(draft); await refresh(); setDraft(saved as Rule); setErr(''); } catch (e: any) { setErr(String(e?.message ?? e)); } } async function del() { if (!draft) return; if (!draft.id) { setDraft(null); return; } - if (!window.confirm(`Delete alert "${draft.name}"?`)) return; + if (!window.confirm(t('altm.deleteConfirm', { name: draft.name }))) return; try { await DeleteAlertRule(draft.id); setDraft(null); await refresh(); } catch (e: any) { setErr(String(e?.message ?? e)); } } @@ -104,19 +107,19 @@ export function AlertsModal({ onClose, bands, modes, countries }: { { if (!o) onClose(); }}> - Alert management - Alert when a spot matches a rule. Empty filters = ANY; the filters you set are ANDed (e.g. France + 20m = French stations on 20m). + {t('altm.title')} + {t('altm.desc')}
{/* Rule list */}
- Rules + {t('altm.rules')}
- {rules.length === 0 &&
No rules yet — click +
} + {rules.length === 0 &&
{t('altm.noRules')}
} {rules.map((r) => (
- + setEmailTo(e.target.value)} onBlur={() => SetAlertEmailTo(emailTo).catch(() => {})} /> @@ -139,60 +142,60 @@ export function AlertsModal({ onClose, bands, modes, countries }: { {/* Editor */}
{!draft ? ( -
Select or create a rule.
+
{t('altm.selectOrCreate')}
) : (
- Definition - Call / DXCC - Band / Mode - Origin + {t('altm.tabDef')} + {t('altm.tabCall')} + {t('altm.tabBandMode')} + {t('altm.tabOrigin')}
- + patch({ name: e.target.value })} />
- + patch({ again_after_min: parseInt(e.target.value) || 0 })} /> - 0 = once/session · -1 = always + {t('altm.againHint')}
- +
- - - + + +
- +