GridFieldBulkEditingTools/tasks/BuildTransifexTranslations.php

290 lines
7.8 KiB
PHP
Raw Normal View History

2014-03-15 14:43:04 +01:00
<?php
/**
* Phing build task used to generate SilverStripe translation files
2014-03-15 14:53:20 +01:00
* from Transifex data. This tasks assumes that:
2014-03-15 14:43:04 +01:00
* - Javascript translations are from the Transifex resource called 'js'
* - YML translations are from the Transifex resource called 'yml'
2015-12-15 13:08:57 +01:00
* - Transifex AUTH credentials to be saved in $txAuthFile with content {"username": "user", "password": "pwd"}.
2014-03-15 14:43:04 +01:00
*
* This is inspired by SilverStripe build tools. Thanks
2015-12-15 13:08:57 +01:00
*
2014-03-15 14:43:04 +01:00
* @see https://github.com/silverstripe/silverstripe-buildtools/blob/master/src/GenerateJavascriptI18nTask.php
*/
// Ignore this file if phing is not installed
2015-12-15 13:08:57 +01:00
if (!class_exists('Task')) {
return;
}
2014-03-15 14:43:04 +01:00
include_once 'phing/Task.php';
2014-03-15 14:43:04 +01:00
class BuildTransifexTranslations extends Task
{
2015-12-15 13:08:57 +01:00
private $txapi = 'https://www.transifex.com/api/2';
private $txproject = '';
private $txAuthFile = 'transifexAuth.json';
private $txAuth = null;
2014-03-15 14:43:04 +01:00
2015-12-15 13:08:57 +01:00
private $root = '';
private $jsDir = '/lang/js';
private $ymlDir = '/lang';
2014-03-15 14:43:04 +01:00
2015-12-15 13:08:57 +01:00
public function settxapi($txapi)
{
$this->txapi = $txapi;
}
2014-03-15 14:43:04 +01:00
2015-12-15 13:08:57 +01:00
public function settxproject($txproject)
{
$this->txproject = $txproject;
}
2014-03-15 14:43:04 +01:00
/**
2015-12-15 13:08:57 +01:00
* Task init.
2014-03-15 14:43:04 +01:00
*/
public function init()
2015-12-15 13:08:57 +01:00
{
$root = realpath(__DIR__.DIRECTORY_SEPARATOR.'..');
$authFile = $root.DIRECTORY_SEPARATOR.$this->txAuthFile;
2014-03-15 14:43:04 +01:00
2015-12-15 13:08:57 +01:00
if (file_exists($authFile)) {
$txAuthData = file_get_contents($authFile);
$txAuthData = json_decode($txAuthData);
if ($txAuthData->username && $txAuthData->password) {
$this->txAuth = $txAuthData;
} else {
throw new BuildException("Transifex credentials malformat. Check your $authFile for 'username' and 'password' keys.");
}
} else {
throw new BuildException("Transifex credentials not found. $authFile missing.");
2014-03-15 14:43:04 +01:00
}
2015-12-15 13:08:57 +01:00
$this->root = $root;
$this->jsDir = $root.$this->jsDir;
$this->ymlDir = $root.$this->ymlDir;
2014-03-15 14:43:04 +01:00
}
/**
* Let's get to buisness...
*/
public function main()
{
2015-12-15 13:08:57 +01:00
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $this->txAuth->username.':'.$this->txAuth->password);
2014-03-15 14:43:04 +01:00
// get resources
$url = $this->txapi.'/project/'.$this->txproject.'/resources/';
2015-12-15 13:08:57 +01:00
curl_setopt($ch, CURLOPT_URL, $url);
$resources = curl_exec($ch);
2014-03-15 14:43:04 +01:00
2015-12-15 13:08:57 +01:00
if (!$resources) {
throw new BuildException('Cannot fetch resources');
} else {
$resources = json_decode($resources);
}
2014-03-15 14:43:04 +01:00
// get langs
$url = $this->txapi.'/project/'.$this->txproject.'/languages/';
2015-12-15 13:08:57 +01:00
curl_setopt($ch, CURLOPT_URL, $url);
$languages = curl_exec($ch);
2014-03-15 14:43:04 +01:00
2015-12-15 13:08:57 +01:00
if (!$languages) {
throw new BuildException('Cannot fetch languages');
} else {
$languages = json_decode($languages);
}
2014-03-15 14:43:04 +01:00
// clear existing translation files and/or setup folders
$this->resetTranslations();
// add source_language_code to languages list
$sourceLangs = array();
2015-12-15 13:08:57 +01:00
foreach ($resources as $resource) {
$lang = new StdClass();
$locale = $resource->source_language_code;
$lang->language_code = $locale;
if (!array_key_exists($locale, $sourceLangs)) {
$sourceLangs[$locale] = $lang;
}
}
$sourceLangs = array_values($sourceLangs);
$languages = array_merge($languages, $sourceLangs);
2014-03-15 14:43:04 +01:00
// get each resource translations
2015-12-15 13:08:57 +01:00
foreach ($resources as $resource) {
foreach ($languages as $language) {
$url = $this->txapi.'/project/'.$this->txproject.'/resource/'.$resource->slug.'/translation/'.$language->language_code;
curl_setopt($ch, CURLOPT_URL, $url);
$data = curl_exec($ch);
if ($data) {
$this->saveTranslation($resource->slug, $language->language_code, $data);
}
2014-03-15 14:43:04 +01:00
}
}
2015-12-15 13:08:57 +01:00
curl_close($ch);
2014-03-15 14:43:04 +01:00
}
/**
* Clear any existing translation files
2015-12-15 13:08:57 +01:00
* and create directory structure if needed.
2014-03-15 14:43:04 +01:00
*/
private function resetTranslations()
{
2015-12-15 13:08:57 +01:00
if (file_exists($this->jsDir)) {
echo "Clearing js translations...\n";
$iterator = new GlobIterator($this->jsDir.DIRECTORY_SEPARATOR.'*.js');
foreach ($iterator as $fileInfo) {
if ($fileInfo->isFile()) {
$del = unlink($fileInfo->getRealPath());
}
}
2014-03-15 14:43:04 +01:00
}
2015-12-15 13:08:57 +01:00
if (file_exists($this->ymlDir)) {
echo "Clearing yml translations...\n";
$iterator = new GlobIterator($this->ymlDir.DIRECTORY_SEPARATOR.'*.yml');
foreach ($iterator as $fileInfo) {
if ($fileInfo->isFile()) {
$del = unlink($fileInfo->getRealPath());
}
}
2014-03-15 14:43:04 +01:00
}
2015-12-15 13:08:57 +01:00
if (!file_exists($this->jsDir)) {
echo "Creating js folders...\n";
mkdir($this->jsDir);
}
2014-03-15 14:43:04 +01:00
2015-12-15 13:08:57 +01:00
if (!file_exists($this->ymlDir)) {
echo "Creating yml folders...\n";
mkdir($this->ymlDir);
}
2014-03-15 14:43:04 +01:00
}
/**
* Hook that detect the translation type via resource slug
2015-12-15 13:08:57 +01:00
* and call corect saving function with data.
*
2014-03-15 14:43:04 +01:00
* @param string $resource Transifex resrouce slug
* @param string $locale Transifex locale
* @param string $data Raw Transifex translation data
*/
private function saveTranslation($resource, $locale, $data)
{
2015-12-15 13:08:57 +01:00
if (!$resource || !$locale || !$data) {
return;
}
2014-03-15 14:43:04 +01:00
2015-12-15 13:08:57 +01:00
$data = json_decode($data);
$translation = rtrim($data->content);
2014-03-15 14:43:04 +01:00
2015-12-15 13:08:57 +01:00
switch ($resource) {
2014-03-15 14:43:04 +01:00
case 'js':
$this->saveJSTranslation($locale, $translation);
break;
case 'yml':
$this->saveYMLTranslation($locale, $translation);
break;
}
}
/**
* Save a JS translation file
2015-12-15 13:08:57 +01:00
* Uses JSTemplate to fit with SilverStripe requirements.
*
2014-03-15 14:43:04 +01:00
* @param string $locale Locale code
* @param string $json JSON translation key:value
*/
private function saveJSTranslation($locale, $json)
2015-12-15 13:08:57 +01:00
{
echo "Saving $locale.js\n";
file_put_contents(
$this->jsDir.DIRECTORY_SEPARATOR.$locale.'.js',
$this->getBanner('js').
2014-03-15 14:43:04 +01:00
str_replace(
array(
'%TRANSLATIONS%',
2015-12-15 13:08:57 +01:00
'%LOCALE%',
2014-03-15 14:43:04 +01:00
),
array(
$json,
2015-12-15 13:08:57 +01:00
$locale,
2014-03-15 14:43:04 +01:00
),
$this->getJSTemplate()
)
);
}
/**
2015-12-15 13:08:57 +01:00
* Save a YML translation file.
*
2014-03-15 14:43:04 +01:00
* @param string $locale Locale code
* @param string $yml YML translation
*/
public function saveYMLTranslation($locale, $yml)
{
2015-12-15 13:08:57 +01:00
echo "Saving $locale.yml\n";
2014-09-15 09:38:24 +02:00
2015-12-15 13:08:57 +01:00
if ($locale !== 'en') {
$content = $this->getBanner('yml').$yml;
} else {
$content = $yml;
}
file_put_contents(
$this->ymlDir.DIRECTORY_SEPARATOR.$locale.'.yml',
2014-09-15 09:38:24 +02:00
$content
2014-03-15 14:43:04 +01:00
);
}
/**
2015-12-15 13:08:57 +01:00
* Return the commented file banner.
*
2014-03-15 14:43:04 +01:00
* @param string $type File type e.g js
2015-12-15 13:08:57 +01:00
*
2014-03-15 14:43:04 +01:00
* @return string The commented file banner
*/
private function getBanner($type)
{
2015-12-15 13:08:57 +01:00
switch (strtolower($type)) {
2014-03-15 14:43:04 +01:00
case 'yml':
2015-12-15 13:08:57 +01:00
$comment = '#';
2014-03-15 14:43:04 +01:00
break;
2015-12-15 13:08:57 +01:00
2014-03-15 14:43:04 +01:00
default:
2015-12-15 13:08:57 +01:00
$comment = '//';
2014-03-15 14:43:04 +01:00
break;
}
2015-12-15 13:08:57 +01:00
$banner = <<<TMPL
2014-03-15 14:43:04 +01:00
$comment DO NOT MODIFY. Generated by build task.
$comment Contribute here: https://www.transifex.com/projects/p/gridfieldbulkeditingtools/
TMPL;
2015-12-15 13:08:57 +01:00
return $banner;
2014-03-15 14:43:04 +01:00
}
/**
2015-12-15 13:08:57 +01:00
* Return the SilverStripe JS lang file template.
*
2014-03-15 14:43:04 +01:00
* @return string The JS file template
*/
private function getJSTemplate()
{
2015-12-15 13:08:57 +01:00
$tmpl = <<<TMPL
2014-03-15 14:43:04 +01:00
if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined');
} else {
ss.i18n.addDictionary('%LOCALE%', %TRANSLATIONS%);
}
TMPL;
2015-12-15 13:08:57 +01:00
return $tmpl;
2014-03-15 14:43:04 +01:00
}
2015-12-15 13:08:57 +01:00
}