| 1 |
<?php
|
| 2 |
// $Id: autolocale.module,v 1.9 2007/05/09 09:14:43 goba Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* Implementation of hook_help()
|
| 6 |
*
|
| 7 |
* @param section
|
| 8 |
* Drupal path to provide help for
|
| 9 |
*/
|
| 10 |
function autolocale_help($section) {
|
| 11 |
if ($section == 'admin/settings/locale/language/autoimport') {
|
| 12 |
return t('Automatic import scans all enabled modules and themes for interface translation files under their directories and imports all files found for the selected language. This operation could be resource intensive, and is irreversible.');
|
| 13 |
}
|
| 14 |
return '';
|
| 15 |
}
|
| 16 |
|
| 17 |
/**
|
| 18 |
* Implementation of hook_menu()
|
| 19 |
*/
|
| 20 |
function autolocale_menu() {
|
| 21 |
$items = array();
|
| 22 |
$items['admin/build/autolocale'] = array(
|
| 23 |
'title' => t('Import interface translations'),
|
| 24 |
'description' => t('Automatically import interface translations'),
|
| 25 |
'page callback' => 'drupal_get_form',
|
| 26 |
'page arguments' => array('autolocale_autoimport_form'),
|
| 27 |
'access arguments' => array('administer locales'),
|
| 28 |
);
|
| 29 |
return $items;
|
| 30 |
}
|
| 31 |
|
| 32 |
/**
|
| 33 |
* Menu callback to wipe one language and automatically import PO files
|
| 34 |
*/
|
| 35 |
function autolocale_autoimport_form() {
|
| 36 |
$languages = _autolocale_languages();
|
| 37 |
|
| 38 |
// No foreign language enabled
|
| 39 |
if (count($languages) == 0) {
|
| 40 |
drupal_set_message(t('No foreign language enabled on your site. You need to <a href="@urladd">add</a> and <a href="@urlenable">enable</a> at least one foreign language to import strings for.', array('@urladd' => url('admin/settings/language/add'), '@urlenable' => url('admin/settings/language/overview'))), 'error');
|
| 41 |
return array();
|
| 42 |
}
|
| 43 |
|
| 44 |
// Build language selection form
|
| 45 |
$form = array();
|
| 46 |
$form['language'] = array(
|
| 47 |
'#type' => 'radios',
|
| 48 |
'#title' => t('Language'),
|
| 49 |
'#default_value' => array_shift(array_keys($languages)),
|
| 50 |
'#options' => array_map('check_plain', $languages),
|
| 51 |
'#description' => t('Select the language to autoimport translation files into.'),
|
| 52 |
);
|
| 53 |
|
| 54 |
$form['cleanup'] = array(
|
| 55 |
'#type' => 'checkbox',
|
| 56 |
'#title' => t('Remove existing translations first'),
|
| 57 |
'#default_value' => TRUE,
|
| 58 |
'#description' => t('It is advised to remove the existing translations in the given language for performance reasons, if you have no custom strings added, which are not available in the PO files to import. This removes strings left from upgrades or previously tried and removed modules.')
|
| 59 |
);
|
| 60 |
|
| 61 |
$form['submit'] = array(
|
| 62 |
'#type' => 'submit',
|
| 63 |
'#value' => t('Perform automatic import'),
|
| 64 |
);
|
| 65 |
$form['#skip_duplicate_check'] = TRUE;
|
| 66 |
|
| 67 |
return $form;
|
| 68 |
}
|
| 69 |
|
| 70 |
/**
|
| 71 |
* Implementation of hook_form_validate()
|
| 72 |
*/
|
| 73 |
function autolocale_autoimport_form_validate($form_id, $form_values) {
|
| 74 |
$languages = _autolocale_languages();
|
| 75 |
if (!in_array($form_values['language'], array_keys($languages))) {
|
| 76 |
form_set_error('language', t('Invalid language code (@langcode) choosen for automatic import.', array('@langcode' => $form_values['language'])));
|
| 77 |
}
|
| 78 |
}
|
| 79 |
|
| 80 |
/**
|
| 81 |
* Implementation of hook_form_submit()
|
| 82 |
*/
|
| 83 |
function autolocale_autoimport_form_submit($form_id, $form_values) {
|
| 84 |
$languages = _autolocale_languages();
|
| 85 |
$language = $languages[$form_values['language']];
|
| 86 |
|
| 87 |
if ($form_values['cleanup']) {
|
| 88 |
db_query("DELETE FROM {locales_target} WHERE language = '%s'", $form_values['language']);
|
| 89 |
drupal_set_message(t('Existing translations removed from @language.', array('@language' => $language)));
|
| 90 |
}
|
| 91 |
|
| 92 |
// Initiate batch processing of import if files are available
|
| 93 |
if ($batch = autolocale_batch_import($form_values['language'])) {
|
| 94 |
return batch_set($batch);
|
| 95 |
}
|
| 96 |
// Return to language page otherwise
|
| 97 |
else {
|
| 98 |
drupal_set_message(t('No interface translation files found to import.'));
|
| 99 |
return 'admin/build/autolocale';
|
| 100 |
}
|
| 101 |
}
|
| 102 |
|
| 103 |
/**
|
| 104 |
* Prepare a batch to use to import translations.
|
| 105 |
*
|
| 106 |
* @param $language
|
| 107 |
* Language code to import translations for.
|
| 108 |
* @return
|
| 109 |
* A batch structure or FALSE if no files found.
|
| 110 |
*/
|
| 111 |
function autolocale_batch_import($language) {
|
| 112 |
|
| 113 |
// We have part of the logic in our .install file.
|
| 114 |
include_once drupal_get_path('module', 'autolocale').'/autolocale.install';
|
| 115 |
|
| 116 |
// Collect all files to import for all enabled modules
|
| 117 |
// (and autolocale, even if just in the process of enabling it)
|
| 118 |
$files = array();
|
| 119 |
$result = db_query("SELECT name, filename FROM {system} WHERE status = 1 OR name = 'autolocale'");
|
| 120 |
while ($component = db_fetch_object($result)) {
|
| 121 |
$files = array_merge($files, _autolocale_po_files_for_component($language, $component));
|
| 122 |
}
|
| 123 |
if (count($files)) {
|
| 124 |
$ops = array();
|
| 125 |
foreach($files as $filename) {
|
| 126 |
// We call _autolocale_do_import for every batch operation.
|
| 127 |
// Arguments to this function are: $filename, $language
|
| 128 |
$ops[] = array('_autolocale_do_import', array($filename, $language));
|
| 129 |
}
|
| 130 |
}
|
| 131 |
if (!empty($ops)) {
|
| 132 |
return autolocale_build_batch($ops);
|
| 133 |
} else {
|
| 134 |
return FALSE;
|
| 135 |
}
|
| 136 |
}
|
| 137 |
/**
|
| 138 |
* Build a batch from array of files.
|
| 139 |
*
|
| 140 |
* @param $operations
|
| 141 |
* Array of operations to perform
|
| 142 |
* @return
|
| 143 |
* A batch structure
|
| 144 |
*/
|
| 145 |
function autolocale_build_batch($operations) {
|
| 146 |
if (count($operations)) {
|
| 147 |
$batch = array(
|
| 148 |
'operations' => $operations,
|
| 149 |
'title' => t('Importing interface translations'),
|
| 150 |
'init_message' => t('Starting import'),
|
| 151 |
'error_message' => t('Error importing interface translations'),
|
| 152 |
'finished' => 'autolocale_batch_finished',
|
| 153 |
);
|
| 154 |
return $batch;
|
| 155 |
}
|
| 156 |
return FALSE;
|
| 157 |
}
|
| 158 |
|
| 159 |
/**
|
| 160 |
* Perform interface translation import as a batch step.
|
| 161 |
*
|
| 162 |
* @param $filepath
|
| 163 |
* Path to a file to import.
|
| 164 |
* @param $langcode
|
| 165 |
* Language to import file into.
|
| 166 |
* @param $results
|
| 167 |
* Contains a list of files imported.
|
| 168 |
*/
|
| 169 |
function _autolocale_do_import($filepath, $langcode, &$context) {
|
| 170 |
include_once "includes/locale.inc";
|
| 171 |
$file = (object) array('filename' => basename($filepath), 'filepath' => $filepath);
|
| 172 |
_locale_import_read_po('db-store', $file, 'keep', $langcode);
|
| 173 |
$context['results'][] = $filepath;
|
| 174 |
}
|
| 175 |
|
| 176 |
/**
|
| 177 |
* Batch hook called when processing finishes.
|
| 178 |
*/
|
| 179 |
function autolocale_batch_finished($success, $results) {
|
| 180 |
global $install_locale;
|
| 181 |
if ($success) {
|
| 182 |
drupal_set_message(format_plural(count($results), '1 interface translation file succesfully imported.', '@count interface translation files succesfully imported.'));
|
| 183 |
}
|
| 184 |
else {
|
| 185 |
drupal_set_message(t('Importing translations finished with an error.'));
|
| 186 |
}
|
| 187 |
// Advance install state if in installer.
|
| 188 |
if (isset($install_locale)) {
|
| 189 |
variable_set('install_task', 'finished');
|
| 190 |
}
|
| 191 |
return t('Automatic import finished.');
|
| 192 |
}
|
| 193 |
|
| 194 |
/**
|
| 195 |
* Implementation of hook_form_alter()
|
| 196 |
*
|
| 197 |
* The module management form uses a two step process. Once modules are enabled/installed,
|
| 198 |
* Drupal redirects to the confirm page (even if that is not required), so we
|
| 199 |
* cannot stick submit functions before and after the form handler in the same
|
| 200 |
* HTTP request. This is why we need to first store the previous state in the
|
| 201 |
* session, then compare that with the new state of modules when we get to
|
| 202 |
* the final stage.
|
| 203 |
*
|
| 204 |
* WARNING: since we need to bridge two HTTP requests, if multiple admins
|
| 205 |
* fiddle with modules at the same time, things might get interesting. This
|
| 206 |
* is not a real problem until we deal with modules getting disabled.
|
| 207 |
*/
|
| 208 |
function autolocale_form_alter(&$form, $form_id) {
|
| 209 |
// Skip confirm page alltogether (we cannot identify it by the form id
|
| 210 |
// or form base,/ because the confirm page might not show any form at all)
|
| 211 |
if (($form_id == "system_modules") && ($_GET['q'] != 'admin/build/modules/list/confirm')) {
|
| 212 |
|
| 213 |
// Determine what does the form say about modules enabled at the moment
|
| 214 |
if (is_array($form['status']['#default_value'])) {
|
| 215 |
$enabled_now = $form['status']['#default_value'];
|
| 216 |
|
| 217 |
// We have a previous list to compare to
|
| 218 |
if (isset($_SESSION['autolocale_modules']) && is_array($_SESSION['autolocale_modules'])) {
|
| 219 |
// Does the list of enabled modules changed since we have last been here?
|
| 220 |
$new = array_diff($enabled_now, $_SESSION['autolocale_modules']);
|
| 221 |
if (count($new)) {
|
| 222 |
include_once 'autolocale.install';
|
| 223 |
// Import all PO files for all enabled foreign languages
|
| 224 |
$languages = array_keys(_autolocale_languages());
|
| 225 |
$ops = array();
|
| 226 |
foreach($new as $module) {
|
| 227 |
$component = db_fetch_object(db_query("SELECT name, filename FROM {system} WHERE name = '%s'", $module));
|
| 228 |
foreach($languages as $langcode) {
|
| 229 |
// Get all files needed for batch operation
|
| 230 |
$files = _autolocale_po_files_for_component($langcode, $component);
|
| 231 |
if (count($files)) {
|
| 232 |
foreach($files as $filename) {
|
| 233 |
// Schedule an operation for each one
|
| 234 |
$ops[] = array('_autolocale_do_import', array($filename, $langcode));
|
| 235 |
}
|
| 236 |
}
|
| 237 |
}
|
| 238 |
}
|
| 239 |
if (count($ops)) {
|
| 240 |
$batch = autolocale_build_batch($ops);
|
| 241 |
// @todo: This doesn't work yet.
|
| 242 |
batch_set($batch);
|
| 243 |
}
|
| 244 |
_autolocale_clear();
|
| 245 |
}
|
| 246 |
}
|
| 247 |
|
| 248 |
// Store modules for next reload
|
| 249 |
$_SESSION['autolocale_modules'] = $enabled_now;
|
| 250 |
}
|
| 251 |
}
|
| 252 |
}
|
| 253 |
|
| 254 |
/**
|
| 255 |
* Helper function to get the languages we can work with.
|
| 256 |
*/
|
| 257 |
function _autolocale_languages() {
|
| 258 |
static $languages = NULL;
|
| 259 |
if (!isset($languages)) {
|
| 260 |
$languages = locale_language_list();
|
| 261 |
unset($languages['en']);
|
| 262 |
}
|
| 263 |
return $languages;
|
| 264 |
}
|
| 265 |
|
| 266 |
/**
|
| 267 |
* Clear every affected cache. To be called after an import.
|
| 268 |
*/
|
| 269 |
function _autolocale_clear() {
|
| 270 |
cache_clear_all('*', 'cache', TRUE);
|
| 271 |
cache_clear_all('*', 'cache_page', TRUE);
|
| 272 |
cache_clear_all('*', 'cache_filter', TRUE);
|
| 273 |
}
|