PHPackages                             mathieumaingret/drup\_csv2po - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. mathieumaingret/drup\_csv2po

ActiveDrupal-module[Utility &amp; Helpers](/categories/utility)

mathieumaingret/drup\_csv2po
============================

Generates the PO files of a module or a theme from a CSV translation file.

1.7(3w ago)08.3k↓17%GPL-2.0-or-laterPHPPHP ^8.1

Since Jun 19Pushed 1y ago1 watchersCompare

[ Source](https://github.com/mathieumaingret/drup_csv2po)[ Packagist](https://packagist.org/packages/mathieumaingret/drup_csv2po)[ Docs](https://github.com/mathieumaingret/drup_csv2po)[ RSS](/packages/mathieumaingret-drup-csv2po/feed)WikiDiscussions main Synced 2w ago

READMEChangelogDependencies (4)Versions (10)Used By (0)

Drup Csv2Po
===========

[](#drup-csv2po)

Generates the PO files of a module or a theme from a CSV translation file, typically a Google Sheet exported as CSV. One PO file is written per language column found in the CSV.

Requirements
------------

[](#requirements)

- Drush
- The `language` and `locale` core modules, both declared as dependencies.

Setup
-----

[](#setup)

1. Tell Drupal where the translation files of the module or theme live, in its own `.info.yml`:

    ```
    'interface translation project': my_module
    'interface translation server pattern': modules/custom/my_module/translations/%project.%language.po
    ```
2. At `/admin/config/regional/translate/settings`, set **Translation source** overwrite to *All*.
3. Declare the CSV URL in `settings.php`:

    ```
    $settings['drup_csv2po']['csv_remote_url'] = 'https://docs.google.com/spreadsheets/d/[ID]/gviz/tq?tqx=out:csv';
    $settings['drup_csv2po']['extension_name'] = 'my_module';
    ```

Usage
-----

[](#usage)

```
drush csv2po
```

The command downloads the CSV, writes one PO file per language next to it, and points you to `/admin/reports/translations` to import them.

### Which extension is translated

[](#which-extension-is-translated)

`extension_name` is looked up in the modules first, then in the themes. Without a value, the site's default theme is used. A name matching neither is rejected.

```
# A theme.
drush csv2po --extension_name=backend

# A module.
drush csv2po --extension_name=my_module

# Overriding the CSV URL for one run.
drush csv2po --csv_remote_url='https://docs.google.com/spreadsheets/d/XXX/gviz/tq?tqx=out:csv'
```

### Options

[](#options)

Every option can be set in `settings.php` under `$settings['drup_csv2po']`, or passed to the command. The command line wins over `settings.php`, which wins over the defaults.

OptionDefaultDescription`extension_name`the default themeMachine name of the module or theme to translate.`extension_translations_directory``translations`Directory, inside the extension, the files are written to.`csv_remote_url`*none*URL the CSV is downloaded from. Required.`csv_output_filename``translations.csv`Name the downloaded CSV is saved under.`plural_value_separator``PHP_EOL`Separator between the singular and the plural value of a cell.`check_enabled_languages``TRUE`Only generate files for languages enabled on the site.`translations_source_langcode``en`Langcode of the column strings are translated from.The canonical list is `ConverterOptions::DEFAULTS`.

CSV format
----------

[](#csv-format)

Column names are matched case insensitively.

ColumnRequiredDescription`PAGE`yesGrouping label. A comment banner is written whenever it changes. May be left empty on a row.`CONTEXT`yesTranslation context. May be left empty on a row.`PLURAL`yesWhen filled, the source and translation cells hold a singular and a plural value, separated by `plural_value_separator`.source langcodeyesThe strings to translate. `EN` unless `translations_source_langcode` says otherwise.`[LANGCODE]`—One column per translation, named after the langcode.A row is skipped when its source or its translation is empty, so a language column can be filled progressively.

### Example

[](#example)

```
"PAGE","CONTEXT","PLURAL","EN","FR","DE"
"FAQ","","","Frequently asked questions","Questions fréquentes","Häufig gestellte Fragen"
"FAQ","","","Search by keywords","Rechercher par mots-clés","Nach Stichwörtern suchen"
"SEARCH","","1","@count result
@count results","@count résultat
@count résultats","@count Ergebnis
@count Ergebnisse"
```

Safeguards
----------

[](#safeguards)

- A CSV missing a required column aborts the run, naming the columns.
- A language whose column holds no translation at all leaves its PO file untouched, so an emptied column cannot wipe the translations of a site.
- Two rows sharing a context and a source string are reported: the last one wins.
- A malformed plural value is imported as a singular translation, with a warning.

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance69

Regular maintenance activity

Popularity23

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~226 days

Recently: every ~234 days

Total

6

Last Release

21d ago

PHP version history (3 changes)1.1PHP ^7.0 || ^8.0

1.2PHP ^8.0

1.7PHP ^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/cbf1d184864bfccd773caaa812c82f2307771830e2eab4b8001e6debac8a095d?d=identicon)[mathieumaingret](/maintainers/mathieumaingret)

---

Top Contributors

[![mathieumaingret](https://avatars.githubusercontent.com/u/22579623?v=4)](https://github.com/mathieumaingret "mathieumaingret (11 commits)")

### Embed Badge

![Health badge](/badges/mathieumaingret-drup-csv2po/health.svg)

```
[![Health](https://phpackages.com/badges/mathieumaingret-drup-csv2po/health.svg)](https://phpackages.com/packages/mathieumaingret-drup-csv2po)
```

###  Alternatives

[azuracast/azuracast

The AzuraCast self-hosted web radio station management suite.

4.0k27.9k](/packages/azuracast-azuracast)[grumpydictator/firefly-iii

Firefly III: a personal finances manager.

24.3k69.5k](/packages/grumpydictator-firefly-iii)[statamic/cms

The Statamic CMS Core Package

4.9k3.8M1.2k](/packages/statamic-cms)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

762297.9k53](/packages/civicrm-civicrm-core)[craftcms/feed-me

Import content from XML, RSS, CSV or JSON feeds into entries, categories, Craft Commerce products, and more.

292960.7k38](/packages/craftcms-feed-me)[oat-sa/tao-core

TAO core extension

64147.9k151](/packages/oat-sa-tao-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
