Skip to content
This repository was archived by the owner on Mar 4, 2019. It is now read-only.

Import translations and projects #17

Merged
merged 12 commits into from
Aug 27, 2015
70 changes: 70 additions & 0 deletions lib/fn/upload_file/to_server.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php
/**
* @file
* Function upload_file_to_server().
*/

namespace BTranslator\Client;
use \bcl;

/**
* Make an http request for uploading a file to the B-Translator server.
*
* This is done with curl because wsclient cannot handle it.
*
* TODO: Replace this function and wsclient by Guzzle.
*/
function upload_file_to_server($endpoint, $params = array()) {
$btr = wsclient_service_load('btr');

// Get an access_token.
module_load_include('inc', 'oauth2_client', 'oauth2_client');
$oauth2_settings = $btr->settings['authentication']['oauth2'];
$oauth2_client = new \OAuth2\Client($oauth2_settings);
try {
$access_token = $oauth2_client->getAccessToken();
}
catch (\Exception $e) {
return [[$e->getMessage(), 'error']];
}

// Get the details of the uploaded file.
$file_name = $_FILES['files']['name']['file'];
$file_tmp_name = $_FILES['files']['tmp_name']['file'];
$file_size = $_FILES['files']['size']['file'];

// Make an http request with curl.
$ch = curl_init($btr->url . $endpoint);
@curl_setopt_array($ch, array(
CURLOPT_POST => TRUE,
CURLOPT_POSTFIELDS => array(
'file' => "@$file_tmp_name;filename=$file_name",
) + $params,
CURLOPT_HTTPHEADER => array(
'Content-Type: multipart/form-data',
'Authorization: Bearer ' . $access_token,
'Accept: application/json',
),
CURLOPT_RETURNTRANSFER => TRUE,
) +
$btr->settings['curl options']
);
$result = curl_exec($ch);

// Check for any errors and get the result.
if (curl_errno($ch)) {
$messages = [[curl_error($ch), 'error']];
}
else {
$result = json_decode($result, TRUE);
if (isset($result['messages'])) {
$messages = $result['messages'];
}
else {
$messages = [[serialize($result), 'error']];
}
}
curl_close($ch);

return $messages;
}
63 changes: 63 additions & 0 deletions lib/fn/upload_file/validate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php
/**
* @file
* Validate the file uploaded from the import form.
*/

namespace BTranslator\Client;
use \bcl;


/**
* Validate the file uploaded from the import form.
*/
function upload_file_validate($extensions =NULL) {
// Check that a file is uploaded.
$file_tmp_name = $_FILES['files']['tmp_name']['file'];
if ($file_tmp_name == '') {
form_set_error('file', t("Please select a file."));
return;
}

// Check for any other upload errors.
$file_error = $_FILES['files']['error']['file'];
if ($file_error != 0) {
form_set_error('file',
t("Error %error happened during file upload.",
array('%error' => $file_error))
);
return;
}

// Check the extension of the uploaded file.
if ($extensions === NULL) $extensions = 'po tar gz tgz bz2 xz 7z zip';
$regex = '/\.(' . preg_replace('/ +/', '|', preg_quote($extensions)) . ')$/i';
$file_name = $_FILES['files']['name']['file'];
if (!preg_match($regex, $file_name)) {
form_set_error('file',
t('Only files with the following extensions are allowed: %files-allowed.',
array('%files-allowed' => $extensions))
);
return;
}

// Check the type of the uploaded file.
$file_type = $_FILES['files']['type']['file'];
$known_file_types = array(
'text/x-gettext-translation',
'application/x-tar',
'application/x-compressed-tar',
'application/x-bzip',
'application/x-gzip',
'application/x-7z-compressed',
'application/x-xz',
'application/zip',
);
if (!in_array($file_type, $known_file_types)) {
form_set_error('file',
t('File has unknown type: %file_type.',
array('%file_type' => $file_type))
);
return;
}
}
21 changes: 21 additions & 0 deletions project/blocks/blocks.inc
Original file line number Diff line number Diff line change
@@ -5,11 +5,14 @@
*/

require_once __DIR__ . '/select.inc';
require_once __DIR__ . '/subscribe.inc';
require_once __DIR__ . '/list.inc';
require_once __DIR__ . '/topcontrib.inc';
require_once __DIR__ . '/statistics.inc';
require_once __DIR__ . '/project_stats.inc';
require_once __DIR__ . '/export.inc';
require_once __DIR__ . '/import.inc';
require_once __DIR__ . '/import_translations.inc';
require_once __DIR__ . '/latest.inc';

/**
@@ -32,6 +35,12 @@ function btrProject_block_info() {
'cache' => DRUPAL_CACHE_CUSTOM,
);

// Subscribe to a project.
$blocks['subscribe'] = array(
'info' => t('B-Translator Project: Subscribe to a project'),
'cache' => DRUPAL_CACHE_CUSTOM,
);

// Displays top 5 (or 10) contributors, over the last week (or month).
$blocks['topcontrib'] = array(
'info' => t('B-Translator Project: Top contributors during the last period'),
@@ -56,6 +65,18 @@ function btrProject_block_info() {
'cache' => DRUPAL_CACHE_CUSTOM,
);

// Import.
$blocks['import'] = array(
'info' => t('B-Translator Project: Import'),
'cache' => DRUPAL_CACHE_CUSTOM,
);

// Import translations.
$blocks['import_translations'] = array(
'info' => t('B-Translator Project: Import translations'),
'cache' => DRUPAL_CACHE_CUSTOM,
);

// Suggestions and votes submited lately.
$blocks['latest'] = array(
'info' => t('B-Translator Project: Latest contributions'),
100 changes: 100 additions & 0 deletions project/blocks/import.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php
/**
* @file
* Import translations.
*/

/**
* Called from hook_block_view for import.
*/
function btrProject_import_view() {
// Get the arguments from the path.
list($origin, $project, $lng) = bcl::get_project_from_path();

$block['subject'] = t('Import Project');
$block['content'] = drupal_get_form('btrProject_import_form', $origin, $project, $lng);
return $block;
}

/**
* Form callback for: btrProject_import_form
*/
function btrProject_import_form($form, &$form_state, $origin, $project, $lng) {
$description = t('
<p>This form is for creating/updating custom translation projects. The PO/POT files
that are uploaded will be used for importing strings and translations. If
there are no POT files, then the PO files will be used both for importing
strings and for importing translations. If there are POT files and PO files,
their names have to match (except for the extension).</p>

<p>If you want to create a vocabulary, use <strong>vocabulary</strong> as the
origin of the project, and add the suffix \'<strong>_!lng</strong>\' to the
project name. Use <strong>msgctxt "project_name"</strong> as the context of each
string in the PO/POT file. Also the uploaded PO file must have the same name
as the project, for example <strong>ICT_sq.po</strong>. These restrictions are
needed because vocabularies are pseudo-projects (for example you can add
strings to them) and certain assumptions are made about them.</p> ',
['!lng' => bcl::get_translation_lng()]
);

$form = [
'import' => [
'#type' => 'fieldset',
'#title' => t('Create a project or update an existing one by importing POT/PO files'),
'#description' => $description,
'#collapsible' => FALSE,
'#collapsed' => FALSE,

'origin' => [
'#type' => 'textfield',
'#title' => t('Origin'),
'#default_value' => 'custom',
'#required' => TRUE,
//'#attributes' => array('readonly' => 'readonly'),
],

'project' => [
'#type' => 'textfield',
'#title' => t('Project'),
'#required' => TRUE,
],

'file' => [
'#type' => 'file',
'#title' => t('PO File(s)'),
'#description' => t('Upload a PO file. If you have many files, upload them as an archive (tar, tgz, bz2, 7z, zip).'),
],

'submit' => [
'#value' => t('Import'),
'#type' => 'submit',
],
],
];
return $form;
}

/**
* Implements hook form_validate() for btrProject_import_form.
*/
function btrProject_import_form_validate($form, &$form_state) {
$extensions = 'pot po tar gz tgz bz2 xz 7z zip';
bcl::upload_file_validate($extensions);
}


/**
* Implement hook form_submit() for the form btrProject_import_form
*/
function btrProject_import_form_submit($form, &$form_state) {
if (!bcl::user_is_authenticated()) {
bcl::user_authenticate($form_state, $redirection = ($form===NULL));
return;
}

$messages = bcl::upload_file_to_server('project/import', [
'origin' => $form_state['values']['origin'],
'project' => $form_state['values']['project'],
]);
bcl::display_messages($messages);
}
81 changes: 81 additions & 0 deletions project/blocks/import_translations.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php
/**
* @file
* Import translations.
*/

/**
* Called from hook_block_view for import_translations.
*/
function btrProject_import_translations_view() {
// Get the arguments from the path.
list($origin, $project, $lng) = bcl::get_project_from_path();

$block['subject'] = t('Import Translations');
$block['content'] = drupal_get_form('btrProject_import_translations_form', $origin, $project, $lng);
return $block;
}

/**
* Form callback for: btrProject_import_translations_form
*/
function btrProject_import_translations_form($form, &$form_state, $origin, $project, $lng) {
$description = t('
<p>Importing PO files is for bulk translation and voting. For any translation in
the PO files, it will be added as a suggestion if such a translation does not
exist, or it will just be voted if such a translation already exists. In case
that the translation already exists but its author is not known, then you (the
user who makes the import) will be recorded as the author of the
translation.</p>

<p>This functionality can be useful if you prefer to work off-line with PO
files. You can export the PO files of a project, work on them with desktop
tools (like Lokalize) to translate or correct exported translations, and then
import back to B-Translator the translated/corrected PO files.</p>
');

$form = [
'import_translations' => [
'#type' => 'fieldset',
'#title' => t('Import translations from PO files'),
'#description' => $description,
'#collapsible' => FALSE,
'#collapsed' => FALSE,

'file' => [
'#type' => 'file',
'#title' => t('PO File(s)'),
'#description' => t('Upload a PO file. If you have many files, upload them as an archive (tar, tgz, bz2, 7z, zip).'),
],

'submit' => [
'#value' => t('Import'),
'#type' => 'submit',
],
],
];
return $form;
}

/**
* Implements hook form_validate() for btrProject_import_translations_form.
*/
function btrProject_import_translations_form_validate($form, &$form_state) {
bcl::upload_file_validate();
}


/**
* Implement hook form_submit() for the form btrProject_import_translations_form
*/
function btrProject_import_translations_form_submit($form, &$form_state) {
if (!bcl::user_is_authenticated()) {
bcl::user_authenticate($form_state, $redirection = ($form===NULL));
return;
}

$messages = bcl::upload_file_to_server('translations/import', [
'lng' => bcl::get_translation_lng(),
]);
bcl::display_messages($messages);
}
Loading