Skip to content

Python API

The complete Python reference. csv_trans exposes two entry points, a typed TranslationConfig, a content-free TranslationResult, and a small exception hierarchy. Everything below is importable from the top-level csv_trans package unless noted.

Use translate_csv when you hold a typed TranslationConfig; use translate for the ergonomic string-language form. Both return a TranslationResult — check succeeded or inspect status.

def translate_csv(
input_path: str | Path,
config: TranslationConfig,
*,
output_path: str | Path | None = None,
) -> TranslationResult

The single typed engine entry point. Samples the input for column selection, processes it in bounded row groups, and publishes the output atomically after the final row is written. Failed cells retain their complete original value and appear in failures.

ParameterTypeDefaultDescription
input_pathstr | PathPath to the input CSV.
configTranslationConfigFully-typed configuration. A non-TranslationConfig raises TypeError.
output_pathstr | Path | NoneNoneOutput CSV path. When None, defaults to translated_<target>_<name> beside the input (<target> is sanitized to filesystem-safe characters).

Raises on fatal input, configuration, privacy-preflight, and write errors — e.g. CsvInputError, OutputExistsError, PrivacyViolation.

from csv_trans import TranslationConfig, translate_csv
from csv_trans.providers import EchoProvider
config = TranslationConfig(
source_language="en",
target_language="fr",
provider=EchoProvider(),
)
result = translate_csv("catalog.csv", config, output_path="catalog.fr.csv")
print(result.status.value, result.output_path)
def translate(
input_path: str | Path,
source_language: str,
target_language: str,
sep: str | None = None,
*,
output_path: str | Path | None = None,
**options: Any,
) -> TranslationResult

An ergonomic wrapper. It builds a TranslationConfig from source_language, target_language, and any keyword optionsevery TranslationConfig field is accepted — then delegates to translate_csv.

ParameterTypeDefaultDescription
input_pathstr | PathPath to the input CSV. 1.x alias: file=.
source_languagestrSource language code/name, or "auto". 1.x alias: source_lang=.
target_languagestrTarget language code/name. 1.x alias: target_lang=.
sepstr | NoneNone1.x delimiter alias, forwarded to delimiter=. When omitted, the dialect detector runs.
output_pathstr | Path | NoneNoneOutput CSV path (same default as above).
**optionsAny TranslationConfig field, e.g. provider=, columns=, privacy=, overwrite=.
from csv_trans import translate
from csv_trans.providers import EchoProvider
result = translate(
"catalog.csv", "en", "fr",
provider=EchoProvider(),
columns=("title", "description"),
privacy="public",
)

The typed configuration passed to translate_csv. It is a dataclass; source_language and target_language are required and everything else has a default. Values are validated in __post_init__, so an invalid configuration raises ValueError (or TypeError) at construction.

from csv_trans import TranslationConfig
from csv_trans.providers import EchoProvider
config = TranslationConfig(
source_language="en",
target_language="fr",
provider=EchoProvider(),
columns=("title", "description"),
privacy="restricted",
allowed_providers=("echo",),
)
FieldTypeDefaultDescription
source_languagestrrequiredSource language code/name. "auto", "detect", or "automatic" request auto-detection (sent as no source). Stripped; must be non-empty.
target_languagestrrequiredTarget language code/name. Stripped; must be non-empty.
providerprovider object | NoneNonePrimary provider. None uses the experimental GoogleFreeProvider.
fallback_providerssequence of provider objects()Providers tried, in order, only after bounded recovery on the primary fails and privacy permits. A bare str/bytes is rejected.
FieldTypeDefaultDescription
columnsSequence[str | int] | NoneNoneExplicit column names or zero-based indexes; None = automatic selection. Booleans and empty names are rejected.
translate_headersboolFalseTranslate the selected columns’ header cells too.
encodingstr | NoneNoneInput encoding. None/"auto"/"detect"/empty = detect BOM or strict UTF-8. Unknown codecs rejected.
output_encodingstr"utf-8"Output codec (normalized via codecs.lookup). Unknown codecs rejected.
delimiterstr | NoneNoneOne-character field delimiter; None auto-detects. Must be a single non-newline, non-NUL character.
overwriteboolFalseAllow replacing an existing output/report.
FieldTypeDefaultDescription
privacyPrivacyMode | str"public"Network boundary: "public", "restricted", or "local-only". A string is coerced to PrivacyMode.
allowed_providersSequence[str]()Provider names permitted under restricted. Non-empty strings. Under privacy="restricted" an empty allowlist fails the run-time preflight with PrivacyViolation.
approved_local_hostsSequence[str]()Exact non-loopback hosts approved under local-only. Non-empty strings.

See Privacy and security for behavior.

All fields in this section must be positive integers (≥ 1).

FieldTypeDefaultDescription
sample_rowsint100Rows sampled for automatic column selection.
batch_sizeint20Max items per provider request; also bounds row groups by selected-cell count.
max_charsint3500Max characters per translatable segment before lossless chunking.
min_adaptive_charsint32Floor for adaptive splitting of a context-limited singleton.
max_field_charsint67108864 (64 MiB)Reject any single CSV field larger than this.
max_row_charsint134217728 (128 MiB)Reject any row whose fields sum beyond this.
max_columnsint10000Reject any row with more columns than this.
max_sample_charsint16777216 (16 MiB)Cap on characters buffered during selection sampling.
max_pending_charsint67108864 (64 MiB)Character budget that flushes a pending row group.
FieldTypeDefaultRuleDescription
max_failure_detailsint10000≥ 0Max stored failure records; the rest count in omitted_failure_count.
max_retriesint2≥ 0Transient-error retries per provider.
malformed_retriesint1≥ 0Separate corrective-retry budget for invalid model output.
backoff_basefloat0.5≥ 0, finiteBase seconds for exponential backoff.
max_backofffloat8.0≥ 0, finiteCap on backoff delay.
jitterfloat0.1≥ 0, finiteRandom jitter added to each backoff delay.
cache_sizeint2048≥ 0LRU capacity for (source, target, segment) translations. 0 disables caching.
FieldTypeDefaultDescription
preserve_placeholdersboolTrueProtect URLs, tokens, formats, tags, and boundary whitespace as local segments.
allow_empty_translationsboolFalseAccept an empty provider result for non-empty source text instead of rejecting it.
report_pathstr | Path | NoneNoneWrite the structured JSON result here. Must differ from input and output paths, must not be a symlink, and must not exist unless overwrite=True.
snapshot_directorystr | Path | NoneNoneDirectory for the transient plaintext source snapshot. None = beside the input.
dry_runboolFalseInspect selection and counts without contacting a provider or writing a CSV.
progress_callbackCallable[[ProgressEvent], None] | NoneNoneCalled with content-free ProgressEvents during translation. A raising callback is caught and recorded as a warning.
cancellation_checkCallable[[], bool] | NoneNonePolled at safe points; returning True cancels the run without publishing output.

The object passed to progress_callback (frozen dataclass):

FieldTypeDescription
phasestr"translating" or "complete".
rows_processedintData rows processed so far.
cells_translatedintCells fully translated so far.
cells_failedintCells preserved after failure so far.
from csv_trans import TranslationConfig, ProgressEvent
def on_progress(event: ProgressEvent) -> None:
print(event.phase, event.rows_processed, event.cells_translated)
config = TranslationConfig("en", "fr", progress_callback=on_progress)

Every run returns a TranslationResult — a durable, content-free record.

result = translate_csv("catalog.csv", config)
if result.succeeded:
print("done:", result.output_path)
else:
print(result.status.value, "failures:", result.failed_cells)
result.write_json("catalog.translation.json")
FieldTypeDescription
input_pathPathResolved source path.
output_pathPath | NoneOutput CSV path; None for a dry run or a cancelled run.
source_languagestrAs configured.
target_languagestrAs configured.
privacyPrivacyModeEffective privacy mode.
statusRunStatusFinal state (see RunStatus).
input_encodingstrDetected/selected input encoding.
output_encodingstrOutput codec used.
dialectdictDetected CSV dialect (delimiter, quotechar, quoting, line terminator, …).
FieldTypeDescription
row_countintData rows processed (excludes the header).
total_cellsintFields processed; header fields count only when translate_headers=True.
selected_cellsintFields in selected columns, including blank ones.
translated_cellsintFields whose translation fully succeeded.
cached_cellsintSubset of translated cells completed entirely via dedup/cache.
skipped_cellsintUnselected or safely bypassed fields (blank, machine-like, identical languages, no translatable segment).
failed_cellsintFields preserved with their original value after failing.
omitted_failure_countintFailures beyond max_failure_details that were counted but not stored.
retriesintTotal provider retries across the run.
fallbacksintNumber of times work moved to a fallback provider.
FieldTypeDescription
selected_columnslist[ColumnSelection]One entry per column with its selection decision and reason.
failureslist[TranslationFailure]One entry per preserved cell failure (capped by max_failure_details).
provider_attemptslist[ProviderAttempt]Per-provider telemetry (batches, items, retries, failures, sanitized endpoints).
warningslist[str]Non-fatal advisories (e.g. identical languages, no columns selected, durability notes).
report_pathPath | NoneWhere a report was published, if any.
@property
def succeeded(self) -> bool

True when status is success or dry-run — i.e. the run completed without a final cell failure.

def to_dict(self, *, include_column_names: bool = False) -> dict

Returns a JSON-ready dict. Content-free by default: header names and per-failure column_name are set to null unless include_column_names=True. Paths, status, and privacy are stringified; provider endpoints are lists.

def write_json(
self,
path: str | Path,
*,
overwrite: bool = False,
include_column_names: bool = False,
) -> Path

Writes the result atomically as UTF-8 JSON and returns the destination path. It refuses to overwrite an existing file (or a symlink) unless overwrite=True, and updates self.report_path on success. See How it works.

A string enum. succeeded is True for SUCCESS and DRY_RUN.

ValueMeaning
successEvery selected cell translated.
partialOne or more cells preserved after failure; output still written.
failedReserved for forward compatibility; not produced by v2 (fatal errors raise instead).
cancelledcancellation_check stopped the run; no output published.
dry-runSelection/counts only; no provider contacted, no CSV written.

String enum: public, restricted, local-only. See Privacy and security.

FieldTypeDescription
indexintZero-based column index.
namestrHeader name (nulled in serialized reports by default).
selectedboolWhether the column was translated.
reasonstrWhy (e.g. text-like values, numeric-like values, explicitly selected).
FieldTypeDescription
rowintData-row number of the failed cell.
column_indexintZero-based column index.
column_namestrHeader name (nulled in serialized reports by default).
item_idstrInternal stable cell ID (e.g. r3c1).
categorystrError category (e.g. timeout, invalid_response, output_encoding).
providerstrProvider that produced the final failure.
endpointstr | NoneSanitized recipient endpoint.
attemptsintTotal attempts across recovery.
messagestrEngine-derived safe message (never provider raw text).
original_preservedboolAlways True — the source value is kept.
FieldTypeDescription
providerstrProvider name.
chain_indexintPosition in the provider chain (0 = primary).
endpointstr | NoneFirst sanitized endpoint.
endpointstuple[str, ...]All sanitized endpoints observed.
batchesintProvider requests made.
itemsintItems submitted across those requests.
retriesintRetries within this provider.
failuresintFailed requests within this provider.

csv-trans raises fatal input, configuration, privacy, and write errors to the caller; returned results are only success, partial, cancelled, or dry-run. Provider adapters normalize transport-, HTTP-, and response-level failures into a small provider-independent hierarchy so recovery can make retry/split/fallback decisions without depending on a provider SDK.

from csv_trans import PrivacyViolation # subclass of ValueError

Raised during preflight (and re-validation before each provider call) when a configured provider would cross the selected network boundary — for example a remote endpoint under local-only, a restricted run without an allowlist, or a provider not on the allowlist. See Privacy and security.

These come from the CSV and config layers and inherit from standard base classes, so existing except ValueError / except FileExistsError handlers keep working:

ExceptionBaseRaised when
csv_trans.csvio.CsvInputErrorValueErrorInput cannot be decoded/interpreted as CSV, or it changed during the run.
csv_trans.csvio.OutputExistsErrorFileExistsErrorOutput/report collision rejected by policy (no overwrite).
ValueError / TypeErrorInvalid TranslationConfig fields, or a non-TranslationConfig passed to translate_csv.

All provider exceptions live in csv_trans.exceptions (and are re-exported from csv_trans.providers). The base carries safe, log-friendly metadata — never a response body, which could echo source text or credentials.

class ProviderError(RuntimeError):
provider: str # provider id/name
category: ErrorCategory # stable category
retryable: bool # engine retry hint
status_code: int | None # HTTP status when applicable
ExceptionCategoryRetryableDefault statusMeaning
ProviderConfigurationErrorconfigurationnoInvalid/missing provider configuration.
ProviderAuthenticationErrorauthenticationnoAuth/authorization failed (HTTP 401/403).
ProviderRateLimitErrorrate_limityes429Quota exceeded.
ProviderContextLimitErrorcontext_limitnoRequest exceeded a context/payload limit → drives adaptive split.
ProviderTimeoutErrortimeoutyesRequest timed out.
ProviderConnectionErrorconnectionyesCould not connect to the endpoint.
ProviderRequestErrorinvalid_requestnoSemantically invalid request rejected.
ProviderResponseErrorinvalid_responsenoMalformed/contract-breaking output → corrective retry then split.
ProviderServerErrorserveryesProvider internal server failure (HTTP 5xx).
ProviderUnavailableErrorunavailableyesEndpoint temporarily unavailable (HTTP 502/503/504).

A StrEnum of stable categories used across providers and reports: configuration, authentication, rate_limit, context_limit, timeout, connection, invalid_request, invalid_response, server, unavailable, unknown.

Raise the subclass that matches the failure so recovery classifies it correctly (see Providers):

from csv_trans.exceptions import ProviderRateLimitError, ProviderResponseError
# 429 from the upstream service:
raise ProviderRateLimitError("rate limited", provider="my-provider")
# Model returned something that isn't the required JSON contract:
raise ProviderResponseError("not translation JSON", provider="my-provider")

Reports record only the engine’s category-derived wording, not your message. Do not put source text or credentials in messages anyway — logs and error reporters may capture them.