diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d570d6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +################# +## Transifex +################# + +transifexAuth.json \ No newline at end of file diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..1fdf69a --- /dev/null +++ b/build.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/lang/cs.js b/javascript/lang/cs.js new file mode 100644 index 0000000..3a52c4b --- /dev/null +++ b/javascript/lang/cs.js @@ -0,0 +1,13 @@ +// DO NOT MODIFY. Generated by build task. +// Contribute here: https://www.transifex.com/projects/p/gridfieldbulkeditingtools/ +if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { + if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); +} else { + ss.i18n.addDictionary('cs', { + "GridFieldBulkTools.FINISH_CONFIRM": "Máte neuložené změny. Pokud budete pokračovat neuložená data budou nenávratně ztracena.\n\nOpravdu chcete pokračovat?", + "GridFieldBulkTools.EDIT_CHANGED": "Změněno", + "GridFieldBulkTools.EDIT_UPDATED": "Uloženo", + "GridFieldBulkManager.BULKACTION_EMPTY_SELECT": "Musíte vybrat alespoň jednu položku.", + "GridFieldBulkManager.CONFIRM_DESTRUCTIVE_ACTION": "Data budou nenávratně ztracena. Opravdu chcete pokračovat?" +}); +} \ No newline at end of file diff --git a/javascript/lang/cs_CZ.js b/javascript/lang/cs_CZ.js deleted file mode 100644 index ffc83a7..0000000 --- a/javascript/lang/cs_CZ.js +++ /dev/null @@ -1,11 +0,0 @@ -if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { - console.error('Class ss.i18n not defined'); -} else { - ss.i18n.addDictionary('cs_CZ', { - 'GridFieldBulkTools.FINISH_CONFIRM': "Máte neuložené změny. Pokud budete pokračovat neuložená data budou nenávratně ztracena.\n\nOpravdu chcete pokračovat?", - 'GridFieldBulkTools.EDIT_CHANGED': 'Změněno', - 'GridFieldBulkTools.EDIT_UPDATED': 'Uloženo', - 'GridFieldBulkManager.BULKACTION_EMPTY_SELECT': 'Musíte vybrat alespoň jednu položku.', - 'GridFieldBulkManager.CONFIRM_DESTRUCTIVE_ACTION': 'Data budou nenávratně ztracena. Opravdu chcete pokračovat?' - }); -} diff --git a/javascript/lang/de.js b/javascript/lang/de.js new file mode 100644 index 0000000..e0a5342 --- /dev/null +++ b/javascript/lang/de.js @@ -0,0 +1,13 @@ +// DO NOT MODIFY. Generated by build task. +// Contribute here: https://www.transifex.com/projects/p/gridfieldbulkeditingtools/ +if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { + if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); +} else { + ss.i18n.addDictionary('de', { + "GridFieldBulkTools.FINISH_CONFIRM": "Ihre Änderungen sind nicht gespeichert. Wenn sie fortfahren gehen diese Daten verloren.\n\nMöchten Sie fortfahren?", + "GridFieldBulkTools.EDIT_CHANGED": "Geändert", + "GridFieldBulkTools.EDIT_UPDATED": "Gespeichert", + "GridFieldBulkManager.BULKACTION_EMPTY_SELECT": "Sie müssen mindestens ein Element auswählen", + "GridFieldBulkManager.CONFIRM_DESTRUCTIVE_ACTION": "Wollen Sie dieses Element wirklich unwiderruflich löschen?" +}); +} \ No newline at end of file diff --git a/javascript/lang/de_DE.js b/javascript/lang/de_DE.js deleted file mode 100644 index af33277..0000000 --- a/javascript/lang/de_DE.js +++ /dev/null @@ -1,11 +0,0 @@ -if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { - console.error('Class ss.i18n not defined'); -} else { - ss.i18n.addDictionary('de_DE', { - 'GridFieldBulkTools.FINISH_CONFIRM': "Ihre Änderungen sind nicht gespeichert. Wenn sie fortfahren gehen diese Daten verloren.\n\nMöchten Sie fortfahren?", - 'GridFieldBulkTools.EDIT_CHANGED': 'Geändert', - 'GridFieldBulkTools.EDIT_UPDATED': 'Gespeichert', - 'GridFieldBulkManager.BULKACTION_EMPTY_SELECT': 'Sie müssen mindestens ein Element auswählen', - 'GridFieldBulkManager.CONFIRM_DESTRUCTIVE_ACTION': 'Wollen Sie dieses Element wirklich unwiderruflich löschen?' - }); -} diff --git a/javascript/lang/en.js b/javascript/lang/en.js new file mode 100644 index 0000000..2af5028 --- /dev/null +++ b/javascript/lang/en.js @@ -0,0 +1,13 @@ +// DO NOT MODIFY. Generated by build task. +// Contribute here: https://www.transifex.com/projects/p/gridfieldbulkeditingtools/ +if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { + if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); +} else { + ss.i18n.addDictionary('en', { + "GridFieldBulkTools.FINISH_CONFIRM": "You have unsaved changes. Continuing will loose all unsaved data.\n\nDo your really want to continue?", + "GridFieldBulkTools.EDIT_CHANGED": "Modified", + "GridFieldBulkTools.EDIT_UPDATED": "Saved", + "GridFieldBulkManager.BULKACTION_EMPTY_SELECT": "You must select at least one record.", + "GridFieldBulkManager.CONFIRM_DESTRUCTIVE_ACTION": "The data will be lost permanently. Do you want to continue?" +}); +} \ No newline at end of file diff --git a/javascript/lang/en_US.js b/javascript/lang/en_US.js deleted file mode 100644 index 99221bd..0000000 --- a/javascript/lang/en_US.js +++ /dev/null @@ -1,11 +0,0 @@ -if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { - console.error('Class ss.i18n not defined'); -} else { - ss.i18n.addDictionary('en_US', { - 'GridFieldBulkTools.FINISH_CONFIRM': "You have unsaved changes. Continuing will loose all unsaved data.\n\nDo your really want to continue?", - 'GridFieldBulkTools.EDIT_CHANGED': 'Modified', - 'GridFieldBulkTools.EDIT_UPDATED': 'Saved', - 'GridFieldBulkManager.BULKACTION_EMPTY_SELECT': 'You must select at least one record.', - 'GridFieldBulkManager.CONFIRM_DESTRUCTIVE_ACTION': 'The data will be lost permanently. Do you want to continue?' - }); -} diff --git a/javascript/lang/fr.js b/javascript/lang/fr.js new file mode 100644 index 0000000..6823505 --- /dev/null +++ b/javascript/lang/fr.js @@ -0,0 +1,13 @@ +// DO NOT MODIFY. Generated by build task. +// Contribute here: https://www.transifex.com/projects/p/gridfieldbulkeditingtools/ +if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { + if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); +} else { + ss.i18n.addDictionary('fr', { + "GridFieldBulkTools.FINISH_CONFIRM": "Vous avez des changements non enregistrés. En continuant vous allez perdre toutes vos données non enregistrées.\n\nVoulez-vous vraiment continuer?", + "GridFieldBulkTools.EDIT_CHANGED": "Changé", + "GridFieldBulkTools.EDIT_UPDATED": "Enregisté", + "GridFieldBulkManager.BULKACTION_EMPTY_SELECT": "Vous devez séléctionner au moins un élément.", + "GridFieldBulkManager.CONFIRM_DESTRUCTIVE_ACTION": "Vos données seront perdues définitivement. Voulez-vous continuer?" +}); +} \ No newline at end of file diff --git a/javascript/lang/fr_FR.js b/javascript/lang/fr_FR.js deleted file mode 100644 index 0e31c8c..0000000 --- a/javascript/lang/fr_FR.js +++ /dev/null @@ -1,11 +0,0 @@ -if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { - console.error('Class ss.i18n not defined'); -} else { - ss.i18n.addDictionary('fr_FR', { - 'GridFieldBulkTools.FINISH_CONFIRM': "Vous avez des changements non enregistrés. En continuant vous allez perdre toutes vos données non enregistrées.\n\nVoulez-vous vraiment continuer?", - 'GridFieldBulkTools.EDIT_CHANGED': 'Changé', - 'GridFieldBulkTools.EDIT_UPDATED': 'Enregisté', - 'GridFieldBulkManager.BULKACTION_EMPTY_SELECT': 'Vous devez séléctionner au moins un élément.', - 'GridFieldBulkManager.CONFIRM_DESTRUCTIVE_ACTION': 'Vos données seront perdues définitivement. Voulez-vous continuer?' - }); -} diff --git a/javascript/lang/nl.js b/javascript/lang/nl.js new file mode 100644 index 0000000..82b2b84 --- /dev/null +++ b/javascript/lang/nl.js @@ -0,0 +1,13 @@ +// DO NOT MODIFY. Generated by build task. +// Contribute here: https://www.transifex.com/projects/p/gridfieldbulkeditingtools/ +if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { + if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); +} else { + ss.i18n.addDictionary('nl', { + "GridFieldBulkTools.FINISH_CONFIRM": "Er zijn niet-opgeslagen wijzigingen.\n\nDoorgaan zal al deze niet-opgeslagen wijzigingen vergeten.\n\nWeet je zeker dat je de pagina wilt verlaten?", + "GridFieldBulkTools.EDIT_CHANGED": "Aangepast", + "GridFieldBulkTools.EDIT_UPDATED": "Opgeslagen", + "GridFieldBulkManager.BULKACTION_EMPTY_SELECT": "U moet minstens een item te selecteren.", + "GridFieldBulkManager.CONFIRM_DESTRUCTIVE_ACTION": "De gegevens zullen permanent verloren. Weet je zeker dat je de pagina wilt verlaten?" +}); +} \ No newline at end of file diff --git a/javascript/lang/nl_NL.js b/javascript/lang/nl_NL.js deleted file mode 100644 index 3926d08..0000000 --- a/javascript/lang/nl_NL.js +++ /dev/null @@ -1,11 +0,0 @@ -if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { - console.error('Class ss.i18n niet gevonden of niet gedefinieerd'); -} else { - ss.i18n.addDictionary('nl_NL', { - 'GridFieldBulkTools.FINISH_CONFIRM': "Er zijn niet-opgeslagen wijzigingen.\n\nDoorgaan zal al deze niet-opgeslagen wijzigingen vergeten.\n\nWeet je zeker dat je de pagina wilt verlaten?", - 'GridFieldBulkTools.EDIT_CHANGED': 'Aangepast', - 'GridFieldBulkTools.EDIT_UPDATED': 'Opgeslagen', - 'GridFieldBulkManager.BULKACTION_EMPTY_SELECT': 'U moet minstens een item te selecteren.', - 'GridFieldBulkManager.CONFIRM_DESTRUCTIVE_ACTION': 'De gegevens zullen permanent verloren. Weet je zeker dat je de pagina wilt verlaten?' - }); -} \ No newline at end of file diff --git a/lang/cs.yml b/lang/cs.yml index ef90a39..32268e3 100644 --- a/lang/cs.yml +++ b/lang/cs.yml @@ -1,3 +1,5 @@ +# DO NOT MODIFY. Generated by build task. +# Contribute here: https://www.transifex.com/projects/p/gridfieldbulkeditingtools/ cs: GridFieldBulkTools: BULK_UPLOAD_BTN_LABEL: Hromadně nahrát @@ -10,4 +12,4 @@ cs: ACTION_BTN_LABEL: Provést SELECT_ALL_LABEL: Vybrat vše GridFieldBulkManager: - CANCEL_BTN_LABEL: Storno + CANCEL_BTN_LABEL: Storno \ No newline at end of file diff --git a/lang/de.yml b/lang/de.yml index 85b9bf7..236f3fe 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -1,3 +1,5 @@ +# DO NOT MODIFY. Generated by build task. +# Contribute here: https://www.transifex.com/projects/p/gridfieldbulkeditingtools/ de: GridFieldBulkTools: BULK_UPLOAD_BTN_LABEL: Bulk Upload diff --git a/lang/en.yml b/lang/en.yml index f23981a..239e09d 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -1,3 +1,5 @@ +# DO NOT MODIFY. Generated by build task. +# Contribute here: https://www.transifex.com/projects/p/gridfieldbulkeditingtools/ en: GridFieldBulkTools: BULK_UPLOAD_BTN_LABEL: Bulk Upload diff --git a/lang/fr.yml b/lang/fr.yml index 55e6c60..36eda0e 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -1,3 +1,5 @@ +# DO NOT MODIFY. Generated by build task. +# Contribute here: https://www.transifex.com/projects/p/gridfieldbulkeditingtools/ fr: GridFieldBulkTools: BULK_UPLOAD_BTN_LABEL: Upload groupé diff --git a/lang/nl.yml b/lang/nl.yml index e3afdeb..fb431ae 100644 --- a/lang/nl.yml +++ b/lang/nl.yml @@ -1,3 +1,5 @@ +# DO NOT MODIFY. Generated by build task. +# Contribute here: https://www.transifex.com/projects/p/gridfieldbulkeditingtools/ nl: GridFieldBulkTools: BULK_UPLOAD_BTN_LABEL: Bulk Upload @@ -10,4 +12,4 @@ nl: ACTION_BTN_LABEL: Gaan SELECT_ALL_LABEL: Selecteer alles GridFieldBulkManager: - CANCEL_BTN_LABEL: Annuleren + CANCEL_BTN_LABEL: Annuleren \ No newline at end of file diff --git a/tasks/BuildTransifexTranslations.php b/tasks/BuildTransifexTranslations.php new file mode 100644 index 0000000..e5e6e56 --- /dev/null +++ b/tasks/BuildTransifexTranslations.php @@ -0,0 +1,292 @@ +txapi = $txapi; + } + + public function settxproject($txproject) + { + $this->txproject = $txproject; + } + + /** + * Task init + */ + public function init() + { + $root = realpath(__DIR__ . DIRECTORY_SEPARATOR . '..'); + $authFile = $root . DIRECTORY_SEPARATOR . $this->txAuthFile; + + 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."); + } + + $this->root = $root; + $this->jsDir = $root . $this->jsDir; + $this->ymlDir = $root . $this->ymlDir; + } + + /** + * Let's get to buisness... + */ + public function main() + { + $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); + + // get resources + $url = $this->txapi.'/project/'.$this->txproject.'/resources/'; + curl_setopt($ch, CURLOPT_URL, $url); + $resources = curl_exec($ch); + + if ( !$resources ) + { + throw new BuildException("Cannot fetch resources"); + } + else{ + $resources = json_decode($resources); + } + + // get langs + $url = $this->txapi.'/project/'.$this->txproject.'/languages/'; + curl_setopt($ch, CURLOPT_URL, $url); + $languages = curl_exec($ch); + + if ( !$languages ) + { + throw new BuildException("Cannot fetch languages"); + } + else{ + $languages = json_decode($languages); + } + + // clear existing translation files and/or setup folders + $this->resetTranslations(); + + // add source_language_code to languages list + $sourceLangs = array(); + 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); + + // get each resource translations + 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); + } + } + } + + curl_close($ch); + } + + /** + * Clear any existing translation files + * and create directory structure if needed + */ + private function resetTranslations() + { + 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()); + } + } + } + + 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()); + } + } + } + + if ( !file_exists($this->jsDir) ) + { + echo "Creating js folders...\n"; + mkdir($this->jsDir); + } + + if ( !file_exists($this->ymlDir) ) + { + echo "Creating yml folders...\n"; + mkdir($this->ymlDir); + } + } + + /** + * Hook that detect the translation type via resource slug + * and call corect saving function with data + * @param string $resource Transifex resrouce slug + * @param string $locale Transifex locale + * @param string $data Raw Transifex translation data + */ + private function saveTranslation($resource, $locale, $data) + { + if ( !$resource || !$locale || !$data ) + { + return; + } + + $data = json_decode($data); + $translation = rtrim($data->content); + + switch ($resource) + { + case 'js': + $this->saveJSTranslation($locale, $translation); + break; + + case 'yml': + $this->saveYMLTranslation($locale, $translation); + break; + } + } + + /** + * Save a JS translation file + * Uses JSTemplate to fit with SilverStripe requirements + * @param string $locale Locale code + * @param string $json JSON translation key:value + */ + private function saveJSTranslation($locale, $json) + { + echo "Saving $locale.js\n"; + file_put_contents( + $this->jsDir . DIRECTORY_SEPARATOR . $locale . '.js', + $this->getBanner('js') . + str_replace( + array( + '%TRANSLATIONS%', + '%LOCALE%' + ), + array( + $json, + $locale + ), + $this->getJSTemplate() + ) + ); + } + + /** + * Save a YML translation file + * @param string $locale Locale code + * @param string $yml YML translation + */ + public function saveYMLTranslation($locale, $yml) + { + echo "Saving $locale.yml\n"; + file_put_contents( + $this->ymlDir . DIRECTORY_SEPARATOR . $locale . '.yml', + $this->getBanner('yml') . $yml + ); + } + + /** + * Return the commented file banner + * @param string $type File type e.g js + * @return string The commented file banner + */ + private function getBanner($type) + { + switch ( strtolower($type) ) + { + case 'yml': + $comment = "#"; + break; + + default: + $comment = "//"; + break; + } + + $banner = <<