manonkindt / craft-csv-export
A simple translation workflow for Craft CMS: export translatable content to Excel, import the translations safely. Plus a flat, one-column-per-field CSV export.
Package info
github.com/Manonkindt/craft-csv-export
Type:craft-plugin
pkg:composer/manonkindt/craft-csv-export
Requires
- php: ^8.2
- craftcms/cms: ^5.9.0
- moneyphp/money: ^4.0
- phpoffice/phpspreadsheet: ^5.3
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A simple translation workflow for Craft CMS. Export your content to a clean, Excel-friendly file, send it to your translator or edit it yourself, and safely import the completed translations back into Craft. On the side, it also gives you a flat, one-column-per-field CSV export of any entries, handy for pulling form submissions into Excel.
The plugin is built for translating existing content. It only exports what can actually be translated and leaves your site's structure, relations, assets and other non-translatable data untouched.
Requirements
- Craft CMS 5.9 or later
- PHP 8.2 or later
- For the translation workflow: a multi-site installation (one site per language)
Installation
From the Plugin Store, search for Translation CSV Export and click Install. Or with Composer:
composer require manonkindt/craft-csv-export php craft plugin/install csv-export
The translation workflow
1. Export
Go to Entries, filter the entries you want translated and click Export… at the bottom of the list. Two translation export types are available:
- Translations (Word, source | translation) — a
.docxdocument with, per page, a heading and a table: the source texts on the left and an empty column on the right for the translator. Grey rows mark the blocks, a small caption above each text names the field. Links, bold and italic appear as real Word formatting and hyperlinks, not as HTML tags; on import they are turned back into HTML and links get their original attributes back. Fields that are already translated are prefilled. Most translation agencies prefer this format. - Translations (Excel, one sheet per language) — an
.xlsxworkbook, handy when you want all languages side by side or want to filter and sort.
Both can be imported again. The Excel workbook contains:
- a READ ME sheet with instructions for the translator, in English followed by Dutch, French and German;
- one sheet per site, named after the site handle (
nl,fr,en, …). The first sheet is the source language. Every sheet has the same rows (one per entry) and the same columns.
The visible header shows readable labels built from block type and field names, such as Tekstblok Titel or Hero Tekst 2. A hidden first row holds the technical column keys the import needs; translators never have to look at it.
Only translatable content is included:
| Content | What the translator sees |
|---|---|
| Entry title (when the entry type's title is translatable) | One column |
| Plain Text fields set to a translatable translation method | One column |
| Rich text (CKEditor, Redactor, Vizy) | One column per text segment, without HTML tags. Each heading, paragraph or styled <span> becomes its own cell; lines of the same style separated by <br> stay together in one cell. Inline formatting such as <strong> or links stays visible inside the text so it can be kept in place. |
| Entries embedded in CKEditor (buttons, columns, …) | Their fields, like any block |
| Matrix, Neo and Content Block blocks | Their translatable fields, nested as deep as needed |
| Hyper link fields | The link text |
| SEO Fields, SEOmatic, Ether SEO | Meta title, meta description, social title and description |
Relations, assets, dates, numbers, options, lightswitches, images and non-translatable fields are left out on purpose. The id column identifies the entries and must stay untouched.
2. Translate
The translator opens the sheet of the target language and replaces the texts with the translation. No Craft account, no field-setup knowledge, no control panel. HTML tags in rich text stay in place; only the text between them is translated. Empty cells are fine, they are ignored on import.
3. Import
Go to Utilities → CSV Import, or click Import translations… next to Export… on the entries index. Upload the workbook, choose the source language, check the preview and confirm.
The preview lists, per language, every text that will be written with its current and new value, plus what is skipped and why. Nothing is saved until you confirm.
The Word document works the same way: hidden markers in the left column tell the import which entry and field each row belongs to, so the translator only types in the right column. A single-language .csv (for example from the flat export below) can be imported too; pick its language in the form.
Safe by default
- The source language is never modified.
- Only existing entries and blocks in the corresponding site are written. The plugin never creates or deletes entries or blocks. Blocks are matched on their position and block type; text segments on their position in the HTML, so the HTML structure of the target language is kept and only the texts change.
- Only translatable, textual fields and titles are written. Non-translatable and unsupported fields are skipped and reported.
- Empty cells are ignored, so nothing is ever cleared.
- Existing translations are preserved: a cell is only written when the target field is still empty or still identical to the source text. Enable Overwrite existing translations to write every non-empty cell.
- Every element is saved through Craft's normal validation. Elements that fail validation remain unchanged and their errors are shown.
- Every successful save creates a Craft revision, so changes can be reverted through the entry's revision history.
Users need the Utilities → CSV Import permission to import.
Flat CSV export
Besides the translation workbook, the plugin exports any entries as a flat CSV: one row per entry, one column per field, nested content flattened into columns. Useful for form submissions, reports or a quick look at your content in Excel.
- Entries index → Export… → Flat (one column per field): respects the filters, search and selection of the index. Craft writes the file (CSV, JSON or XML).
- Utilities → CSV Export: pick a section, site, status and fields, and download a CSV that honours the delimiter and UTF‑8 BOM settings so Excel opens it correctly.
How values are flattened:
| Field type | Output |
|---|---|
| Plain text, number, email, URL, dropdown, radio, lightswitch | The value (1/0 for lightswitches) |
| Rich text (CKEditor, Redactor, Vizy) | The HTML, or plain text when Strip HTML is on |
| Date/Time | Formatted with the configured date format |
| Checkboxes, multi-select | Option values joined with the multi-value separator |
| Entries, categories, tags, users | Titles (users: e‑mail) joined with the separator |
| Assets | URLs joined with the separator |
| Link, color, money | URL, hex code, decimal amount |
| Table, JSON | JSON |
| Matrix, Neo, Content Block | One column per nested field (data[1].type, data[1].answer, …), readable text or JSON, depending on the Matrix fields setting |
| SEO Fields, SEOmatic, Ether SEO | Split into seo.metaTitle, seo.metaDescription, seo.socialTitle, seo.socialDescription, seo.socialImage (and Twitter/meta image columns where the plugin has them) |
Command line
# Flat CSV php craft csv-export/export --section=requests --site=default --status=all --output=requests.csv # Translation workbook (Excel) or document (Word) php craft csv-export/export --section=news --translations --output=news-translations.xlsx php craft csv-export/export --section=news --translations --format=docx --output=news-translations.docx # Import: preview, then save php craft csv-export/import --file=news-translations.xlsx --source=nl php craft csv-export/import --file=news-translations.xlsx --source=nl --apply
Export options: --section (required), --site, --status (live, pending, expired, disabled, all), --fields=firstName,lastName,email, --limit, --output, --translations.
Import options: --file (required), --source (source site handle), --site (language for .csv files), --overwrite, --apply.
Settings
Under Settings → Plugins → CSV Export:
- Delimiter: semicolon (default, opens correctly in Excel in most European locales), comma or tab. Applies to the utility download and the console command; the entries index export is written by Craft itself (comma).
- Include UTF‑8 BOM: recommended for Excel.
- Column labels: field handle (stable, best for re‑importing) or field name.
- Entry attributes: which element attributes (id, title, slug, status, dates, …) come first in the flat export.
- Matrix fields: how nested content is flattened in the flat export.
- Date format, multi-value separator, strip HTML.
The translation workbook always uses field handles, ids and one column per nested field, so it can be imported again.
Languages
The control panel texts are available in English, Dutch, French and German. Add another language by copying src/translations/nl/csv-export.php.
License
This plugin is licensed for sale in the Craft Plugin Store under the Craft License. Copyright © 2026 Manon Kindt.