feat(frontend): i18n MITRE components (matrix modal, picker, field, tag)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { LoadingState } from './LoadingState';
|
||||
import { ErrorState } from './ErrorState';
|
||||
import { extractApiError } from '@/api/client';
|
||||
@@ -41,6 +42,7 @@ export function MitreMatrixModal({
|
||||
onApply,
|
||||
onCancel,
|
||||
}: MitreMatrixModalProps): JSX.Element | null {
|
||||
const { t } = useTranslation();
|
||||
const { data: matrix, isLoading, isError, error } = useMitreMatrix(isOpen);
|
||||
|
||||
const [selectedTechMap, setSelectedTechMap] = useState<Map<string, { id: string; name: string }>>(
|
||||
@@ -177,24 +179,24 @@ export function MitreMatrixModal({
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between px-xl py-md border-b border-hairline flex-shrink-0">
|
||||
<h2 id="matrix-modal-title" className="text-[18px] font-medium text-ink">
|
||||
MITRE ATT&CK Matrix
|
||||
{t('mitre.matrix.title')}
|
||||
</h2>
|
||||
<input
|
||||
ref={searchInputRef}
|
||||
type="text"
|
||||
placeholder="Filter techniques…"
|
||||
placeholder={t('mitre.matrix.filter')}
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
className="text-input w-56 h-9 text-[14px]"
|
||||
aria-label="Filter techniques"
|
||||
aria-label={t('mitre.matrix.filter')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Body — overflow-y-auto, NO overflow-x */}
|
||||
<div className="flex-1 overflow-y-auto overflow-x-hidden px-md py-md">
|
||||
{isLoading && <LoadingState label="Loading MITRE matrix…" />}
|
||||
{isLoading && <LoadingState label={t('mitre.matrix.loading')} />}
|
||||
{isError && (
|
||||
<ErrorState message={extractApiError(error, 'Could not load MITRE matrix')} />
|
||||
<ErrorState message={extractApiError(error, t('mitre.matrix.error'))} />
|
||||
)}
|
||||
{!isLoading && !isError && matrix && (
|
||||
<div
|
||||
@@ -340,7 +342,7 @@ export function MitreMatrixModal({
|
||||
{/* Footer */}
|
||||
<div className="flex items-center justify-end gap-md px-xl py-md border-t border-hairline flex-shrink-0">
|
||||
<button type="button" className="btn-outline-ink" onClick={onCancel}>
|
||||
Cancel
|
||||
{t('mitre.matrix.close')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -349,8 +351,8 @@ export function MitreMatrixModal({
|
||||
disabled={isLoading || isError || (totalSelected === 0 && !hasInitial)}
|
||||
>
|
||||
{totalSelected === 0
|
||||
? 'Clear all'
|
||||
: `Apply ${totalSelected} item${totalSelected !== 1 ? 's' : ''}`}
|
||||
? t('mitre.matrix.clearAll')
|
||||
: t(totalSelected === 1 ? 'mitre.matrix.applyItem_one' : 'mitre.matrix.applyItem_other', { count: totalSelected })}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user