Getting started
Install csv-trans, prove the pipeline end-to-end with the offline echo
provider, then point the same code and commands at a real endpoint.
Install
Section titled “Install”python -m pip install csv-transOr with uv:
uv pip install csv-transcsv-trans 2.0.1 runs on CPython 3.11, 3.12, 3.13, and 3.14 with no
third-party runtime dependencies — the engine uses the standard library alone.
Installation provides two identical console scripts, and the package is also runnable as a module:
csv-trans --helpcsv_trans --helppython -m csv_trans --helpVerify the install, then confirm an end-to-end run with the offline echo
provider, which needs no credentials or network:
python -c "import csv_trans; print(csv_trans.__version__)" # 2.0.1
printf 'id,text\n1,hello\n' > smoke.csvcsv-trans -f smoke.csv -sl en -tl fr --provider echo --columns text \ --output smoke.out.csv --privacy local-only --quietFor local development, an editable install works the same way:
git clone https://github.com/ML-Dev-Hub/csv_transcd csv_transpython -m pip install -e .Quickstart: translate offline
Section titled “Quickstart: translate offline”The examples use this catalog:
id,title,description,price1,Wireless mouse,Ergonomic 2.4GHz mouse,19.992,USB-C cable,Braided 1m cable,7.50The echo provider returns text unchanged, so this runs anywhere and exercises
the full pipeline — column selection, structure preservation, atomic write, and
the structured result:
from csv_trans import translatefrom csv_trans.providers import EchoProvider
result = translate("catalog.csv", "en", "fr", provider=EchoProvider())
print(result.status.value) # "success"print(result.output_path) # translated_fr_catalog.csvprint(result.translated_cells) # cells whose translation fully succeededprint(result.skipped_cells) # id/price columns skipped automaticallyfor column in result.selected_columns: print(column.index, column.name, column.selected, column.reason)translate(input_path, source_language, target_language, sep=None, *, output_path=None, **options)
is the ergonomic wrapper: it builds a
TranslationConfig from your keyword options and calls
the engine. Automatic selection keeps id and price out of the request;
title and description are translated. Headers are preserved unless you pass
translate_headers=True. When you already hold a config object, call
translate_csv directly:
from csv_trans import TranslationConfig, translate_csvfrom csv_trans.providers import EchoProvider
config = TranslationConfig( source_language="en", target_language="fr", provider=EchoProvider(), columns=("title", "description"), # names or zero-based indexes)result = translate_csv("catalog.csv", config, output_path="catalog.fr.csv")From the CLI
Section titled “From the CLI”The equivalent command, with an explicit output path:
csv-trans -f catalog.csv -sl en -tl fr \ --provider echo \ --output catalog.fr.csv \ --privacy local-only--dry-run inspects column selection without contacting any provider — it never
needs a key and never writes a CSV:
csv-trans -f catalog.csv -sl en -tl fr --dry-run# dry-run: translated=0, failed=0, skipped=...; selected-columns=#1='title' (text-like values), ...Point at a real provider
Section titled “Point at a real provider”Credentials come from the environment, not a flag. Point at any OpenAI-compatible endpoint:
export CSV_TRANS_OPENAI_API_KEY="sk-..."export CSV_TRANS_OPENAI_MODEL="gpt-4o-mini"
csv-trans -f catalog.csv -sl en -tl fr --provider openai --privacy restrictedThe same run in Python constructs the provider explicitly:
import osfrom csv_trans import TranslationConfig, translate_csvfrom csv_trans.providers import OpenAICompatibleProvider
provider = OpenAICompatibleProvider( model=os.environ["CSV_TRANS_OPENAI_MODEL"], base_url="https://api.openai.com/v1", api_key=os.environ["CSV_TRANS_OPENAI_API_KEY"],)config = TranslationConfig( source_language="en", target_language="fr", provider=provider, privacy="restricted", allowed_providers=(provider.provider_id,),)result = translate_csv("catalog.csv", config)To keep data on a machine you control, point base_url at a local
OpenAI-compatible server (Ollama, vLLM, LM Studio, llama.cpp) under local-only
privacy. See Providers for every adapter and
Privacy and security for the loopback rule
and its threat-model limits.
If a cell cannot be translated after all recovery, its original value is
preserved and the run is reported as partial; from the CLI a partial run exits
with code 2. See How it works for selection,
recovery, and reports.