Skip to content

Instantly share code, notes, and snippets.

@TomasKostadinov
Created March 30, 2020 13:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TomasKostadinov/f1d8da2a36ce671eb6143dd84b1bfc93 to your computer and use it in GitHub Desktop.
Save TomasKostadinov/f1d8da2a36ce671eb6143dd84b1bfc93 to your computer and use it in GitHub Desktop.
Export/Import a translatable csv in ProcessWire
<?php
include_once "path/to/import.php";
include_once "path/to/export.php";
// call the functions like this
if (isset($_GET["export"])) {
$forceDownload = isset($_GET["force"]);
$debug = isset($_GET["debug"]);
renderExport($pages, $forceDownload, $debug);
} else if (isset($_GET["import"])) {
import();
}
<?php
function renderExport($pages, $force, $debug) {
// allowed fields
$allowedFields = array('title', 'headline', 'summary', 'body', 'body_secondary', 'text', 'image', 'images');
// get current user
$user = wire('user');
// get all installed languages
$languages = wire('languages');
// first line of generated csv
// add url so translator has some context
$headLine = array("fieldID");
// a single page = one line in csv
$page = array();
// field data export
$export = array();
// find all pages
// exclude configuration pages
$selector = array("has_parent=1", "include=all", "include=hidden", "has_parent!=3|22|21|28|304|23|1035|1142|1447|/trash", "id!=3|22|21|28|304|23");
// pass some variables per reference so that they can be used later for output
$pages->findMany(implode(",", $selector))->explode(function ($resultPage) use (&$export, $page, &$headLine, $languages, $allowedFields, &$user, $debug) {
$resultPage->setOutputFormatting(false);
// loop through allowed fields
foreach ($allowedFields as $field) {
// check if field exists on page
if ($resultPage->hasField($field)) {
$getField = $resultPage->get($field);
// special snowflake: RepeaterMatrix is just an array of pages
if ($field === "image" | $field === "images") {
$fieldIdentifier = $resultPage->id . "#" . $field;
// remember user's language
$lang = $user->language;
$i = 0;
foreach ($getField as $image) {
$imageIdentifier = $fieldIdentifier . "#" . $i;
$i++;
$translatedValues = array();
// loop through languages
foreach ($languages as $language) {
if (!in_array($language->name, $headLine)) {
array_push($headLine, $language->name);
}
$user->language = $language;
if ($image != null) array_push($translatedValues, $image->description);
}
// restore saved language
$user->language = $lang;
$page = array($imageIdentifier, preg_replace("/\r|\n/", "", implode(";", $translatedValues)));
array_push($export, $page);
}
} else {
$fieldIdentifier = $resultPage->id . "#" . $field;
$translatedValues = array();
// loop through languages
foreach ($languages as $language) {
if (!in_array($language->name, $headLine)) {
array_push($headLine, $language->name);
}
if ($resultPage[$field] !== "") {
array_push($translatedValues, str_replace('"', '&quot;', $resultPage->get($field)->getLanguageValue($language->id)));
}
}
$page = array($fieldIdentifier, preg_replace("/\r|\n/", "", implode(";", $translatedValues)));
array_push($export, $page);
}
}
}
});
array_unshift($export, $headLine);
renderExportCSV($export, $force);
}
function renderExportCSV($export, $force) {
// force download as file and set correct headers
if ($force) {
header("Content-type: text/csv; charset=utf-8");
header("Content-Disposition: attachment; filename=" . $_SERVER['HTTP_HOST'] . "-" . date("Ymd") . ".csv");
header("Pragma: no-cache");
header("Expires: 0");
}
$output = "";
// generate CSV syntax
foreach ($export as $exportItem) {
$output .= '"' . implode('";"', $exportItem) . "\";\n";
}
echo $output;
exit();
}
<?php
function import() {
$pages = wirePages();
$csv = csv_to_array(wire('config')->paths->templates . 'lib/csv.csv', ';');
$languages = $csv[0];
// remove id and url from languages
#unset($languages[1]);
unset($languages[0]);
unset($csv[0]);
var_dump($languages);
// loop through rows of csv
foreach ($csv as $item) {
#var_dump($item);
// { 23, title }
$fieldIdentifier = explode("#", $item[0]);
$p = $pages->findOne("id=$fieldIdentifier[0], include=all");
// if page exists
if (!$p instanceof NullPage) {
#var_dump($p->title);
// turn off output formatting
$p->of(false);
$i = 0;
$user = wire('user');
foreach ($languages as $lang) {
$user->language = wire('languages')->get($lang);
$i++;
var_dump($item[$i]);
if (!empty($item[$i])) {
if ($lang === "") continue;
if ($fieldIdentifier[1] === "image" | $fieldIdentifier[1] === "images") {
if ($fieldIdentifier[1] === "images") {
$images = $p->get($fieldIdentifier[1]);
$image = $images->eq($fieldIdentifier[2]);
} else {
$image = $p->get($fieldIdentifier[1]);
}
$image->description = $item[$i];
//var_dump($image);
var_dump("Set " . $item[0] . " to " . $p->get($fieldIdentifier[1] . "_" . $lang) . " for Lang " . $lang);
continue;
}
$string = str_replace('&quot;', '"', $item[$i]);
var_dump($string);
$p->set($fieldIdentifier[1], $string);
}
}
$p->save();
}
}
exit();
}
function csv_to_array($filename = '', $delimiter = ',') {
if (!file_exists($filename) || !is_readable($filename)) return FALSE;
$data = array();
if (($handle = fopen($filename, 'r')) !== FALSE) {
while (($row = fgetcsv($handle, 10000, $delimiter)) !== FALSE) {
array_push($data, $row);
}
fclose($handle);
}
return $data;
}
@TomasKostadinov
Copy link
Author

TomasKostadinov commented Mar 30, 2020

The output will look like this:

"fieldID";"default";"english";"russian";"chinese";
"1#title";"Default Title";"English Title";"Russian Title"; "Chinese Title"

and can be given to a company offering translation services.
The import file should look the same, the fieldID field has to stay the same all the time.

Backup the database BEFORE doing any imports

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment