Skip to content

feat(l10n): localize clipboard import errors by type - #163

Merged
mrcsin merged 1 commit into
masterfrom
clipboard-import-errors-typed
Jul 31, 2026
Merged

mrcsin merged 1 commit into
masterfrom
clipboard-import-errors-typed

Conversation

@mrcsin

@mrcsin mrcsin commented Jul 30, 2026

Copy link
Copy Markdown
Member

Problem

The clipboard paste path (ClipboardSerializer.DeserializeSteps) raised free-text Result.Fail(string) / new Error(string) for every parse failure, so a paste error rendered raw English regardless of culture. It reaches the panel via ClipboardViewModel.PasteStepsAsync → ReportFailure, which localizes by type.

What changed

Type the clipboard path, reusing the shared tabular-parse errors 5b introduced (AtRowError, AtColumnError, ActionColumnEmptyError, ActionValueNotIntegerError, ActionByIdNotFoundError, ActionColumnNotFoundError) and adding three clipboard-specific classes:

  • ClipboardParseFailedError — Rule-B exception-envelope for the top-level parse catch. Injects ILogger<ClipboardSerializer> and LogWarnings the exception detail (mirrors CsvService), since the localized headline drops ex.Message; the catch is real (CsvHelper throws BadDataException on malformed pastes).
  • ColumnCountMismatchError and NoValidStepsError — leaves, byte-identical English.

The value chain composes AtRowError → AtColumnError → PropertyValueParseError: pasting a non-numeric cell into a float column renders, under ru, Строка 1: Столбец «task»: Не удалось разобрать «abc» как float — Russian end to end (was just "Row 1"). This completes the CSV+clipboard ingress: after it, only the config-load-culture boundary is English by design.

Behavior-preserving for English except three flagged changes (same shape as 5b): AtRowError gains : {inner}, the ActionByIdNotFoundError reuse rewords unknown-action, and ClipboardParseFailedError drops : {ex.Message} (kept in the log via logger.LogWarning).

Verification

  • dotnet build SemiStep.slnx — 0 warnings.
  • dotnet test SemiStep/SemiStep.Tests/SemiStep.Tests.csproj — 1638 passed, 0 failed.
  • The composition payoff: CsvDeserializationTests deserializes 20\t5.0\tabc\tc through the real ClipboardSerializer.DeserializeSteps and asserts the full Russian chain under ru. The three new types are each pinned end-to-end: ClipboardParseFailedError (unescaped-quote → BadDataException catch), NoValidStepsError (empty input), ColumnCountMismatchError (too-many-columns). ReasonLocalizerTests pins the 3 ru renders + the en Localize == .Message.
  • Review chain: comprehensive (5 agents, all OUTCOME ACHIEVED) → smells → comment audit → critical, all clean after low fixes (end-to-end type pins, a doc logger ref, a comment trim).
  • Manual test (operator): pasted TSV with a bad cell / too many columns / malformed quoting under the Russian UI — the error shows in Russian with row/column context.
Per-task commits before collapse
701b397 test: trim redundant tail from clipboard payoff comment
1cb96b3 docs: correct clipboard logger reference in error-reporting
27249bb test(l10n): pin clipboard parse-failed and no-valid-steps error types
44554f1 test(l10n): cover clipboard import error localization end-to-end
b82a87e feat(l10n): type clipboard import errors

🤖 Generated with Claude Code

The clipboard paste path (ClipboardSerializer.DeserializeSteps) raised
free-text Result.Fail/new Error for every parse failure, so a paste error
rendered raw English regardless of culture. It reaches the panel via
ClipboardViewModel.PasteStepsAsync -> ReportFailure, which localizes by type.

Type the clipboard path, reusing the shared tabular-parse errors 5b
introduced (AtRowError, AtColumnError, ActionColumnEmptyError,
ActionValueNotIntegerError, ActionByIdNotFoundError, ActionColumnNotFoundError)
and adding three clipboard-specific classes:

- ClipboardParseFailedError -- Rule-B exception-envelope for the top-level
  parse catch. Inject ILogger<ClipboardSerializer> and LogWarning the
  exception detail (mirrors CsvService), since the localized headline drops
  ex.Message; the catch is real (CsvHelper throws on malformed pastes).
- ColumnCountMismatchError and NoValidStepsError -- leaves, byte-identical
  English.

The value chain composes AtRowError -> AtColumnError -> PropertyValueParseError:
pasting a non-numeric cell into a float column renders, under ru,
"Строка 1: Столбец «task»: Не удалось разобрать «abc» как float" -- Russian
end to end (was just "Row 1"). This completes the CSV+clipboard ingress:
after it, only the config-load-culture boundary is English by design.

English is behavior-preserving except three flagged changes (same as 5b):
AtRowError gains ": {inner}", the ActionByIdNotFoundError reuse rewords
unknown-action, and ClipboardParseFailedError drops ": {ex.Message}" (kept
in the log).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mrcsin
mrcsin marked this pull request as ready for review July 31, 2026 08:10
@mrcsin
mrcsin merged commit cdb9014 into master Jul 31, 2026
1 check passed
@mrcsin
mrcsin deleted the clipboard-import-errors-typed branch July 31, 2026 08:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant