Skip to content

Import

This area covers 38 features. Watch the walkthrough, then use the reference below — each feature links to the exact moment it appears (▶).

Who this is for: Project lead (source steward). Each feature below lists the role/permission it requires.

Features

Upload files from disk ▶ 00:00

As a translator, I want to upload USFM, DOCX, PPTX, TXT, CSV, XLSX, or subtitle files from my computer, so that I can import source text content and begin translation work.

How it works. User clicks 'Upload Files' in ImportDialog landing. Dialog navigates to upload screen with file drop zone. User drags/drops or clicks 'Choose file' to pick a file. Accepted types: USFM (.usfm/.sfm/.usf), DOCX, PPTX, TXT, CSV, TSV, XLSX, XLS, VTT, SRT, SSA/ASS, audio/video files (MP3, WAV, M4A, WebM, MP4). File is parsed; if it's USFM, the dialog shows a preview of all parsed cells before importing. If unsupported type, error message shown.

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

src/components/ImportDialog.tsx:600+
src/lib/import.ts:428-450
src/lib/parsers/types.ts:detectFileType

Preview parsed cells before import ▶ 00:00

As a translator, I want to review a preview of what will be imported, including cell count, references, and snippet text, so that I can confirm the parse was correct before committing.

How it works. After file is parsed, PreviewPanel is shown. It displays: total cell count across all files; file name(s) with per-file cell counts; snippet list (first 20 cells per file) with canonical reference and text. Confirm button triggers upload; Cancel returns to upload screen without saving. Preview limit: 20 cells shown per result, with '…and N more' note if truncated.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/components/import/PreviewPanel.tsx

USFM book grouping on import ▶ 00:00

As a translator importing a multi-book USFM file, I want each book to be imported as a separate Aquilla file, so that my workspace can organize books separately.

How it works. When importing a USFM file with multiple book sections (e.g. Genesis, Exodus), ImportDialog parses it and creates one ImportResult per book. Preview shows each book with cell count. Each book is uploaded as a distinct FileReference with its book code (from \id marker) and OT/NT corpus classification preserved.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/import.ts:337-385
src/lib/parsers/usfm-lossless.ts

Detect import collisions (duplicate files) ▶ 00:00

As a translator re-importing a file that's already in the project, I want to choose to skip it, replace it, or import it as a duplicate, so that I don't accidentally overwrite work.

How it works. When ImportDialog detects a file with the same name already in the project (FRO-287), it shows a collision screen with list of detected duplicates. Each shows: file name, reason (already exists), three choices: 'Skip', 'Replace', or 'Import as duplicate'. User selects choices per file, clicks Continue, and import proceeds with selected strategy applied.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/import-collision.ts
src/components/ImportDialog.tsx:153-158

Import eBible corpus translations ▶ 00:00

As a translator, I want to download and import openly-licensed Bible translations directly from the eBible corpus, without manually downloading files, so that I can quickly set up reference translations.

How it works. User clicks 'eBible Corpus' on landing. Dialog shows searchable list of 1000+ translations (filtered by language, title, ID). User searches (e.g. 'English', 'KJV') and results update in real-time. Click a translation → progress bar shows download (received/total MB), parse, and save phases. After import, cells are created with target column populated from the eBible text matched by canonical reference.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/parsers/ebible.ts
src/lib/import.ts:191-222
src/components/EBibleTargetReviewPanel.tsx

Match eBible verses to existing cells by reference ▶ 00:00

As a translator with an existing project, I want to populate my target column with eBible translations matched by canonical reference (e.g. GEN 1:1), so that I can add translations without re-creating the source structure.

How it works. After selecting eBible translation, the download/parse completes. Each verse ref in the eBible is matched to a source cell with the same canonicalRef. Unmatched verses are listed as orphans. Matched cells show: incoming text, current text (conflict if non-empty), hasConflict flag. User can review and check/uncheck cells before import. Only checked cells are committed. Returns: committedCount, skippedCount.

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

src/lib/import.ts:138-184
src/components/EBibleTargetReviewPanel.tsx

Direction prompt (source/target language inference) ▶ 00:00

As a translator importing content where the language direction is ambiguous, I want to confirm or override the source and target languages, so that the system correctly interprets which column is source vs translation.

How it works. After file parse completes, if the inferred languages differ from project languages, ImportDialog shows a 'Set language' screen with source/target language dropdowns pre-filled with inferred values. User can override or confirm. Clicking 'Confirm' commits the import with those language tags. If user closes dialog without confirming, a flush path ensures the import isn't silently dropped (FRO-249 Fix 3).

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/components/ImportDialog.tsx:187-200
src/lib/import.ts:391-410

Import result report (partial imports with skipped items) ▶ 00:00

As a translator importing a project with some file collisions that were skipped, I want to see a report of what was imported and what was skipped, with reasons, so that I can decide whether to retry or accept the partial result.

How it works. After import, ImportDialog shows a 'result' screen with: total files imported, count of cells per file, list of skipped files with reason (e.g. 'skipped by user', 'duplicate detected'). Each skipped item shows: book/file name, reason. User can read/copy the report. Close or Click 'Done' dismisses and fires onImported callback with refs + skipped data.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/components/ImportDialog.tsx:142-146,380-430

Spreadsheet import (CSV/XLSX) with column mapping ▶ 00:00

As a translator with content in a spreadsheet, I want to map columns (source, target, reference, cast, timestamps) and import the data, so that I can reuse content organized in Excel/CSV without manual data entry.

How it works. User selects CSV or XLSX file via ImportDialog 'Spreadsheet' option. If XLSX has multiple sheets, sheet selector appears. ColumnMappingPanel shows: header toggle, column selectors for source (required), target, label/ref, cast, start/end timestamp. Auto-detect tries common header names. Preview table shows 5 data rows. After mapping confirm, rows are converted to translatable strings and imported via the standard bulkUploadSource pipeline. Source column is required, others optional.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/components/import/SpreadsheetImportPanel.tsx
src/components/import/ColumnMappingPanel.tsx
src/lib/parsers/spreadsheet.ts

File-scoped target import from USFM or spreadsheet ▶ 00:00

As a translator with an open file, I want to fill its target column from a USFM file or spreadsheet, without modifying the source column, so that I can add translations to existing cells while preserving source structure.

How it works. User opens file in editor, clicks 'Import translations into this file' from menu. FileTargetImportDialog opens. User drops/picks USFM or spreadsheet. For USFM: rows extracted with refs; straight to review. For spreadsheet: sheet selector (if multi-sheet), column mapping with ref optional. Review shows: matched cells with source text beside incoming translation, conflicts highlighted, orphans listed. User checks/unchecks cells, clicks Import. Only checked cells' target columns updated via applyEBibleTargetImport (uses same pipeline as eBible→target).

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

src/components/import/FileTargetImportPanel.tsx
src/components/FileTargetImportDialog.tsx
src/lib/import-file-target.ts

Target import by reference or by row order ▶ 00:00

As a translator importing a spreadsheet without reference column, I want to match rows to cells by order (row N → cell N), so that I can fill translations even when row order aligns with file order.

How it works. When FileTargetImportPanel maps columns with labelCol=null, matching switches to order-based mode. Each data row matches to the corresponding cell position in file. Review screen shows: source text for each cell, incoming translation beside it, warning banner: 'No ref column mapped — rows matched in order. Check source text alignment before importing.' Orphans = empty rows (skipped). User can eyeball alignment before committing.

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

src/lib/import-file-target.ts:100+
src/components/import/FileTargetImportPanel.tsx:259-264

Paired translation import (source + target from spreadsheet) ▶ 00:00

As a translator with a spreadsheet of source+target pairs, I want to import them to populate both source and target columns, so that I can quickly load finished translations in one step.

How it works. User selects 'Paired translation' from ImportDialog landing. Drops/picks CSV or XLSX. Sheet selector if multi-sheet. ColumnMappingPanel requires sourceCol and targetCol; ref optional for matching (if absent, rows matched by order). Review shows: source text, incoming translation, conflicts highlighted. User checks cells, clicks Import. Commits via bulkUploadTargetCommits (target column only; source already exists).

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

src/components/import/PairedImportPanel.tsx
src/lib/parsers/spreadsheet.ts:matchPairedRowsToSourceCells

Cell labels / cast import template download and re-upload ▶ 00:00

As a production manager, I want to download a spreadsheet with cell references, fill in cast names, and re-upload to label cells, so that I can assign actors to cells via a simple spreadsheet workflow.

How it works. User selects 'Cell labels / cast' from ImportDialog. LabelImportPanel shown. Step 1: 'Download template' button generates CSV with ref column (one row per cell with canonicalRef). User downloads, fills in cast_name column. Step 2: User uploads filled CSV. Preview shows: ref + cast_name pairs parsed from file (up to 20 shown). Validation detects header or auto-detects columns. Apply button would commit cast labels (currently held: FRO-314-cast-events requires dedicated server event type).

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/components/import/LabelImportPanel.tsx
src/lib/parsers/spreadsheet.ts:generateLabelTemplate

Extract and import rules from document ▶ 00:00

As a translation lead, I want to upload or paste a style guide document and have the LLM extract structured rules, so that I can quickly set up project-specific validation rules.

How it works. User clicks 'Import from doc' on Rules surface. RuleImportDialog opens. User drops/pastes TXT/MD (max 200 KB) or PDF/DOCX (max 2 MB). For text: runs LLM extraction immediately. For PDF/DOCX: uploads to Frontier, receives parsed text, then extracts. Extraction phase shows progress: extracting candidates, then structuring rules. Review stage shows: list of extracted RuleSuggestion entries. User selects which to accept and clicks Import. Each accepted rule is added to project with source='llm'.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/components/RuleImportDialog.tsx
src/lib/rules/rule-extractor.ts

Macula Hebrew + Greek import (morphology) ▶ 00:00

As a biblical scholar, I want to import Macula original-language data with per-word lemma, morphology, and Strong's codes, so that I can use morphological analysis in my translation workflow.

How it works. User selects 'Macula Hebrew + Greek' from ImportDialog landing (Beta badge shown, enabled). Chooses testament (OT/NT) or both. Source cells created with lemma/morphology metadata per word. Additional morph rows uploaded via separate pipeline (bulkUploadMorphRows). Progress shown: parse phase, save phase, morph phase with counts (morphEnqueued/morphTotal).

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

src/lib/import.ts:282-291
src/lib/parsers/macula.ts

Translation Notes (TSV) import ▶ 00:00

As a translator, I want to import unfoldingWord translation notes (TSV format) mapped by canonical reference, so that I can see contextual notes beside matching verses as I translate.

How it works. User selects 'Translation Notes (TSV)' from ImportDialog landing (Beta badge shown, enabled). Uploads TSV file with canonical_ref column. Rows with missing canonical_ref are skipped (counter shown). Matched notes are stored and displayed in UI beside matching cells. Progress shows: parse phase, save phase with skipped count.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/import.ts:293-300
src/lib/parsers/translation-notes.ts

Bible API (helloao.org) import ▶ 00:00

As a translator needing multiple Bible translations, I want to browse and import from the helloao.org corpus (1000+ translations), choosing full Bible, testament, or specific books, so that I can quickly access reference translations.

How it works. User selects 'Bible API' from ImportDialog landing. Dialog shows searchable translation list fetched from helloao.org. User selects a translation, then book selector appears (pick books or full Bible). Download/parse/save phases shown with progress. Cells created with selected books' content. Supports language filtering in search.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/parsers/helloao.ts
src/lib/import.ts:importHelloao

Paratext project import (multi-file zip) ▶ 00:00

As a translator with a Paratext project, I want to import the entire project (zip with all books), so that I can migrate my Paratext work into Aquilla.

How it works. User selects file upload, drops a .zip containing Paratext project files (.usfm, .ssf metadata). DetectParatextProject analyzes structure and extracts books. PrepareParatextProject builds a plan (one file per book, with language/license metadata). User can skip individual books on collision. CommitParatextProject uploads all books as source cells, preserving book order and section structure.

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

src/lib/parsers/paratext-project.ts
src/lib/import.ts:ParatextPlan,prepareParatextProject,commitParatextProject

Paratext project as target import ▶ 00:00

As a translator with existing source cells, I want to import a Paratext project to populate the target column, so that I can add Paratext translations to my Aquilla project.

How it works. User selects 'Import translations into this file' from file menu. Drops Paratext .zip. Files matched to existing cells by canonical reference (same mechanism as eBible→target). Review shows: matched refs with existing vs incoming text. User confirms, target commits applied. Orphan files (unmatched) listed with reason.

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

src/lib/import.ts:importParatextAsTarget

Audio/video file import (media timeline segments) ▶ 00:00

As a translator working with audio/video content, I want to import MP3, WAV, WebM, or MP4 files, so that I can work with media-based translation segments.

How it works. User uploads audio (MP3/WAV/M4A/WebM) or video (MP4) file. File is detected as media type (isMediaFileType check). Rather than parsing text, the file becomes a single media segment with time-ordered timeline model. Media blob stored; metadata (duration) computed via probeMediaDurationMs. No text content — subtitle features or speaker detection optional.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/import.ts:MediaSegmentSpec,emitMediaFile,computeMediaSegmentSpecs
src/lib/parsers/types.ts:isMediaFileType

Subtitle parsing (SRT/VTT) with speaker tags ▶ 00:00

As a translator working with subtitled content, I want to import SRT or VTT files with speaker tags (e.g. <v Name>), so that I can assign dialogue to characters automatically.

How it works. User uploads .srt or .vtt file. Parser extracts subtitle cues as translatable strings with timecodes. If file contains <v Name> speaker tags, TTS settings can be updated in batch (buildCastAdditions) to create cast members + cell assignments. Speaker pairs (cellId, speaker name) returned for UI to apply cast.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/parsers/subtitle.ts
src/lib/import/cast-from-speakers.ts
src/components/import/SpreadsheetImportPanel.tsx:128-138

Plaintext import ▶ 00:00

As a translator with plain text content, I want to import .txt files where each line or paragraph is a translatable segment, so that I can work with simple text-based content.

How it works. User uploads .txt file. Parsed via extractPlaintextStrings (one string per line or per paragraph, depending on text splitter). Each string gets an ID and becomes a translatable cell. No reference/structure preserved. Simple linear ordering.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/parsers/plaintext.ts
src/lib/import.ts:424-449

Markdown import ▶ 00:00

As a translator with Markdown documentation, I want to import .md files preserving structure, so that I can translate headings, paragraphs, and lists separately.

How it works. User uploads .md file. Parsed via extractMarkdownStrings (headings as type='heading', body as type='verse'). Structure and order preserved. Canonical refs optional (can be injected via heading IDs). Cell group shows section hierarchy.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/parsers/markdown.ts
src/lib/import.ts:424-449

USFM format with lossless round-trip fidelity ▶ 00:00

As a translator working with USFM text, I want to export back to USFM with original markup preserved, so that I can return translations to Paratext without markup loss.

How it works. User imports .usfm file. ParseUsfmLossless preserves all markers, attributes, and formatting in a side-car rawSource field (base64-encoded). On export, the original USFM skeleton is reconstructed with current translations substituted. Verse bodies + heading/title/intro paratext parsed as separate translatable strings.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/parsers/usfm-lossless.ts
src/lib/import.ts:318-335

DOCX import with format preservation ▶ 00:00

As a translator with Word documents, I want to import .docx files with paragraph structure preserved, so that I can translate formatted documents.

How it works. User uploads .docx file. Parsed via extractDocxStrings (paragraphs extracted as translatable strings). Raw DOCX bytes captured as side-car for round-trip export with translations substituted into original formatting.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/parsers/docx.ts
src/lib/import.ts:424-449

PPTX import (slides to translatable units) ▶ 00:00

As a translator with PowerPoint presentations, I want to import .pptx files so that I can translate slide content while preserving layout.

How it works. User uploads .pptx file. Parsed via extractPptxStrings (text from each slide → translatable string). Raw PPTX bytes captured as side-car for round-trip export.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/parsers/pptx.ts
src/lib/import.ts:424-449

XLIFF (XML Localisation Interchange Format) import ▶ 00:00

As a translator with XLIFF translation packages, I want to import .xliff files mapped by unit ID, so that I can work with industry-standard localization format.

How it works. User uploads .xliff file. Parsed via parseXliff (source units extracted as translatable strings with IDs preserved). Each unit becomes one translatable cell.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/parsers/xliff.ts

TMX (Translation Memory eXchange) import ▶ 00:00

As a translator with translation memory files, I want to import TMX format reusing prior translations, so that I can leverage translation history.

How it works. User selects 'Translation Memory (TMX)' from ImportDialog. Currently shown as 'Coming soon' (disabled, badge='soon'). Clicking shows: 'Coming soon — Translation Memory import is tracked for a later release'. Implementation pending.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/parsers/tmx.ts
src/components/ImportDialog.tsx:660-661

CSV bilingual (source + target) import ▶ 00:00

As a translator, I want to import CSV files with both source and target columns already mapped, so that I can quickly load aligned bilingual data.

How it works. User imports CSV with source and target columns. Parser (parseCsvBilingual) extracts aligned pairs. Each pair becomes: source in original column, target populated. Similar to paired import but simpler format detection.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/parsers/csv-bilingual.ts

Speaker/cast assignment from subtitle files ▶ 00:00

As a video translator, I want to import VTT/SRT files with character tags so that dialogue is automatically assigned to speakers, reducing manual casting work.

How it works. User imports VTT/SRT with <v Speaker Name> tags. TTS settings (voices, castAssignments) are updated in batch. SpreadsheetImportPanel receives onCastUpdated callback; buildCastAdditions creates new voice entries and cell-to-speaker assignments. Result: cells tagged with speaker metadata for audio generation.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/import/cast-from-speakers.ts
src/components/import/SpreadsheetImportPanel.tsx:128-138

Paragraph-start signal preservation (USFM) ▶ 00:00

As a Bible translator, I want paragraph structure markers in USFM to be preserved during import, so that paragraph boundaries are respected in the translation interface.

How it works. When importing USFM, ParseUsfmLossless detects paragraph-start markers (e.g. \p). Verses that begin a paragraph get paragraphStart=true flag. UI uses this for grouping context display (D1, D2 signals per design spec 2026-06-18).

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/import.ts:359-362
src/lib/parsers/usfm-lossless.ts

Frontier authentication (login/signup/forgot password) ▶ 00:00

As a user, I want to sign up for, log in to, and reset my password on the Frontier LLM platform, so that I can access AI-powered features like rule extraction and completions.

How it works. User accesses Frontier login/signup forms (FrontierLoginForm, FrontierSignupForm, FrontierForgotPasswordForm). Login requires username/email + password. Signup requires username (3-50 chars), email, password (8+ chars, not containing email local part). Forms show online/offline state. Eye icon toggles password visibility. Signup includes password strength meter. On success, session persists in useFrontierSession hook.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/components/git-import/FrontierLoginForm.tsx
src/components/git-import/FrontierSignupForm.tsx
src/components/git-import/FrontierForgotPasswordForm.tsx

Dialog navigation back button ▶ 00:00

As a user in the ImportDialog, I want a back button that returns me to the previous screen without losing data, so that I can explore options without committing.

How it works. From any ImportDialog sub-screen (upload, ebible, macula, etc.), Back button (aria-label='Back to import types') appears in DialogTitle. Clicking returns to landing screen with all options. No data loss — state preserved if user re-enters sub-screen.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/components/ImportDialog.tsx:440-480

Import type selector landing screen ▶ 00:00

As a user, I want to see all available import options organized by category (Popular vs Specialized), so that I can quickly find the format I need.

How it works. ImportDialog opens to landing screen with title 'Import'. Two sections: POPULAR_OPTIONS (Upload files, eBible Corpus, Bible API, Spreadsheet) and SPECIALIZED_OPTIONS (Macula, Paired, Labels, Translation Notes, Translation Memory 'coming soon'). Each option card shows icon, title, hint, description. Beta or 'Soon' badge displayed. Coming-soon items are disabled (cursor-not-allowed, opacity-55). Clicking enabled card routes to that import type's screen.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/components/ImportDialog.tsx:640-712

Bulk upload source cells (AD-2 event chain) ▶ 00:00

As a developer, I want the import system to emit file.create + source.cell.create events in an AD-2 event chain to the server, so that imported cells are properly versioned and auditable.

How it works. After parsing, emitParsedFile calls bulkUploadSource with BulkImportCell array. Each cell becomes a source.cell.create event chained via anchor_cell_id. First cell has anchor_cell_id=null. Cells uploaded in large chunks to /import endpoint (lib/sync/bulk-import.ts) rather than dripped through outbox (for performance). Server applies chunks and cells projection lands as events are processed.

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

src/lib/sync/bulk-import.ts
src/lib/import.ts:412-450

Conflict resolution (keep vs replace) on target import ▶ 00:00

As a translator importing target text, I want to decide per-cell whether to keep the existing translation or replace it with the incoming one, so that I have control over overwrites.

How it works. During target import review (FileTargetImportPanel, EBibleTargetReviewPanel, PairedImportPanel), matched cells with hasConflict=true are marked with 'Replaces: [current text]' note. User must explicitly check the checkbox to approve the replacement. Pre-selection: non-conflicting cells auto-checked; conflicting cells unchecked by default. Only checked cells are committed.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/components/import/FileTargetImportPanel.tsx:73-76
src/components/PairedImportPanel.tsx:99-103

Duplicate reference handling during import ▶ 00:00

As a translator, I want the system to handle duplicate references in USFM or incoming data gracefully, so that import doesn't fail and I can see what was matched.

How it works. When multiple source cells or rows share the same canonical ref, matcher uses 'first cell wins' strategy (first encountered cell is matched; later rows targeting same ref become orphans). UsfmToTargetRows and matchTargetRowsByRef explicitly track this behavior. User sees orphans listed in review with note '(duplicate ref — later row skipped)'.

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

src/lib/import-file-target.ts:61-98
src/lib/import.ts:144-150

Blank cell handling (never clear existing translations with empty rows) ▶ 00:00

As a translator, I want empty rows in an import file to be skipped rather than clearing existing translations, so that accidental blank cells don't delete work.

How it works. During target import matching (byRef or byOrder), TargetRow with empty/whitespace-only text is ignored — not matched, not committed. Row is discarded silently (no orphan listing for empty rows). This prevents blank spreadsheet cells from clearing existing translations.

WhoProject lead PermissionsImport & file.create: project_lead(500)
Key files

src/lib/import-file-target.ts:76-77