| 1 |
<?php
|
| 2 |
// $Id: i18n_auto.module,v 1.2 2007/06/06 20:17:56 aaron Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* Implement hook_menu
|
| 6 |
*/
|
| 7 |
function i18n_auto_menu($may_cache) {
|
| 8 |
$items = array();
|
| 9 |
if ($may_cache) {
|
| 10 |
$items[] = array(
|
| 11 |
'path' => 'admin/settings/i18n/auto',
|
| 12 |
'title' => t('Auto Translation'),
|
| 13 |
'type' => MENU_LOCAL_TASK,
|
| 14 |
'callback' => 'drupal_get_form',
|
| 15 |
'callback arguments' => array('i18n_auto_admin_settings'),
|
| 16 |
'weight' => 3,
|
| 17 |
'access' => user_access('administer i18n auto'),
|
| 18 |
);
|
| 19 |
$items[] = array(
|
| 20 |
'path' => 'i18n_auto/translate',
|
| 21 |
'callback' => '_i18n_auto_translate',
|
| 22 |
'type' => MENU_CALLBACK,
|
| 23 |
'access' => user_access('i18n auto translate'),
|
| 24 |
);
|
| 25 |
}
|
| 26 |
return $items;
|
| 27 |
}
|
| 28 |
|
| 29 |
/**
|
| 30 |
* Implement hook_perm
|
| 31 |
*/
|
| 32 |
function i18n_auto_perm() {
|
| 33 |
return array('i18n auto translate', 'administer i18n auto');
|
| 34 |
}
|
| 35 |
|
| 36 |
/**
|
| 37 |
* This displays the global settings for auto translate. It will create a field for each 3rd party translator included
|
| 38 |
* in the /translators directory of the i18n_auto module directory. When writing your own include file, you may include
|
| 39 |
* a fieldset for your translator by implementing the i18n_auto_TRANSLATOR_settings hook (replacing TRANSLATOR with the
|
| 40 |
* name of your .inc file).
|
| 41 |
*/
|
| 42 |
function i18n_auto_admin_settings() {
|
| 43 |
$form = array();
|
| 44 |
$translators = i18n_auto_system_list();
|
| 45 |
foreach ($translators as $translator) {
|
| 46 |
$info = i18n_auto_include_invoke($translator->name, 'info');
|
| 47 |
$form[$translator->name] = array(
|
| 48 |
'#type' => 'fieldset',
|
| 49 |
'#title' => t('@translator Configuration', array('@translator' => $info['name'])),
|
| 50 |
'#description' => $info['settings_description'],
|
| 51 |
'#collapsible' => true,
|
| 52 |
'#collapsed' => true,
|
| 53 |
);
|
| 54 |
$form[$translator->name][] = i18n_auto_include_invoke($translator->name, 'settings');
|
| 55 |
$form[$translator->name]['i18n_auto_allow_' . $translator->name] = array(
|
| 56 |
'#type' => 'checkbox',
|
| 57 |
'#title' => t('Allow translation from %translator', array('%translator' => $info['name'])),
|
| 58 |
'#description' => t('If checked, then automatic translation may be provided by %translator.', array('%translator' => $info['name'])),
|
| 59 |
'#weight' => -10,
|
| 60 |
'#default_value' => variable_get('i18n_auto_allow_' . $translator->name, true),
|
| 61 |
);
|
| 62 |
}
|
| 63 |
return system_settings_form($form);
|
| 64 |
}
|
| 65 |
|
| 66 |
/**
|
| 67 |
* TODO: have it intelligently check which forms & textareas it's allowed to add a button to, and use jsquery
|
| 68 |
*/
|
| 69 |
function i18n_auto_form_alter($form_id, &$form) {
|
| 70 |
// print "form: $form_id<br />\n";
|
| 71 |
// print_r($form);
|
| 72 |
|
| 73 |
if ($form['#id'] == 'node-form') {
|
| 74 |
$js = '';
|
| 75 |
foreach (_i18n_auto_form_iterate_for_textareas($form) as $element => $item) {
|
| 76 |
$field = 'i18n_auto_translate_' . $element;
|
| 77 |
$form[$field] = array(
|
| 78 |
'#type' => 'fieldset',
|
| 79 |
'#title' => t('Auto Translation'),
|
| 80 |
'#collapsible' => true,
|
| 81 |
'#collapsed' => false,
|
| 82 |
'#weight' => $item['#weight'],
|
| 83 |
'#attributes' => array(
|
| 84 |
'#class' => 'i18n-auto-fieldset',
|
| 85 |
),
|
| 86 |
'#description' => t('Selecting one of these translation services will replace the text in the %textarea textarea with a translated version.', array('%textarea' => $item['#title'])),
|
| 87 |
);
|
| 88 |
|
| 89 |
$edit_id = form_clean_id('edit-' . $element);
|
| 90 |
$revert_id = form_clean_id('edit-' . 'i18n_auto_revert_' . $element);
|
| 91 |
|
| 92 |
$js .= "
|
| 93 |
|
| 94 |
|
| 95 |
i18n_original_text['$element'] = $('#$edit_id').attr('value');
|
| 96 |
|
| 97 |
$('#$revert_id').click(
|
| 98 |
function() {
|
| 99 |
$('#$edit_id').attr('value', i18n_original_text['$element']);
|
| 100 |
return false;
|
| 101 |
}
|
| 102 |
);
|
| 103 |
";
|
| 104 |
|
| 105 |
$translators = i18n_auto_system_list();
|
| 106 |
foreach ($translators as $translator) {
|
| 107 |
$button = $field . '_' . $translator->name;
|
| 108 |
$form[$field][$button] = array(
|
| 109 |
'#type' => 'button',
|
| 110 |
'#value' => t('Translate with @translator', array('@translator' => $translator->name)),
|
| 111 |
);
|
| 112 |
$id = form_clean_id('edit-' . $button);
|
| 113 |
|
| 114 |
$link = url('i18n_auto/translate/' . $translator->name);
|
| 115 |
$js .= "
|
| 116 |
$('#$id').click(
|
| 117 |
function() {
|
| 118 |
return i18n_auto_click('#$id', '#$edit_id', '$element', '$link');
|
| 119 |
}
|
| 120 |
);
|
| 121 |
";
|
| 122 |
}
|
| 123 |
$form[$field]['i18n_auto_revert_' . $element] = array(
|
| 124 |
'#type' => 'button',
|
| 125 |
'#value' => t('Revert to original', array('@translator' => $translator->name)),
|
| 126 |
);
|
| 127 |
}
|
| 128 |
if ($js) {
|
| 129 |
$js = "
|
| 130 |
if (Drupal.jsEnabled) {
|
| 131 |
function i18n_auto_click(_id, _edit_id, _element, _link) {
|
| 132 |
var _new_value = function(data) {
|
| 133 |
var result = Drupal.parseJson(data);
|
| 134 |
if (result['text']) {
|
| 135 |
i18n_original_text[_element] = $(_edit_id).attr('value');
|
| 136 |
$(_edit_id).attr('value', result['text']);
|
| 137 |
}
|
| 138 |
}
|
| 139 |
if ($(_edit_id).attr('value')) {
|
| 140 |
$.post(_link, {text: $(_edit_id).attr('value'), from: $('#edit-language').attr('value') }, _new_value);
|
| 141 |
}
|
| 142 |
return false;
|
| 143 |
}
|
| 144 |
|
| 145 |
var i18n_original_text = new Array();
|
| 146 |
|
| 147 |
$(document).ready(function(){\n" . $js . "\n });\n }\n\n";
|
| 148 |
drupal_add_js($js, 'inline');
|
| 149 |
}
|
| 150 |
}
|
| 151 |
}
|
| 152 |
|
| 153 |
function _i18n_auto_translate($translator) {
|
| 154 |
$translators = i18n_auto_system_list($translator);
|
| 155 |
if (!$translators[$translator]) {
|
| 156 |
drupal_not_found();
|
| 157 |
}
|
| 158 |
$text = $_POST['text'];
|
| 159 |
$from = $_POST['from'];
|
| 160 |
// TODO: change default language to drupal's locale's default language...
|
| 161 |
$to = $_POST['to'] ? $_POST['to'] : variable_get('i18n_auto_translate_to_lang_default', 'es');
|
| 162 |
// $translation = check_plain(i18n_auto_include_invoke($translator, 'translate', drupal_urlencode($text)));
|
| 163 |
$translation = i18n_auto_include_invoke($translator, 'translate', $text, $from, $to);
|
| 164 |
// Google flattens the input markup. Put it back
|
| 165 |
$translation = htmlspecialchars_decode($translation);
|
| 166 |
// print drupal_urlencode($translation);
|
| 167 |
print drupal_to_js(array('text' => $translation));
|
| 168 |
exit();
|
| 169 |
}
|
| 170 |
|
| 171 |
/**
|
| 172 |
* This will return all the (nested) textarea elements in a form.
|
| 173 |
*/
|
| 174 |
function _i18n_auto_form_iterate_for_textareas($form) {
|
| 175 |
static $elements;
|
| 176 |
|
| 177 |
if (!isset($elements)) {
|
| 178 |
$elements = array();
|
| 179 |
}
|
| 180 |
foreach (element_children($form) as $element) {
|
| 181 |
$item = $form[$element];
|
| 182 |
if ($item['#type'] == 'textarea') {
|
| 183 |
$elements[$element] = $item;
|
| 184 |
}
|
| 185 |
else if (is_array($item)) {
|
| 186 |
_i18n_auto_form_iterate_for_textareas($item);
|
| 187 |
}
|
| 188 |
}
|
| 189 |
return $elements;
|
| 190 |
}
|
| 191 |
|
| 192 |
/**
|
| 193 |
* Return an array of installed .inc files and/or loads them upon request.
|
| 194 |
* This routine is modeled after drupal_system_listing() (and also depends on it).
|
| 195 |
* It's major difference, however, is that it loads .inc files by default.
|
| 196 |
*
|
| 197 |
* @param $translator
|
| 198 |
* Optional; name of the passed $translator to find (e.g. "youtube", "google", etc.).
|
| 199 |
* @param $load
|
| 200 |
* Defaults to true; whether to include matching files into memory.
|
| 201 |
* @return
|
| 202 |
* An array of file objects optionally matching $translator.
|
| 203 |
*/
|
| 204 |
function i18n_auto_system_list($translator = NULL, $load = true) {
|
| 205 |
$files = drupal_system_listing("$translator\.inc", drupal_get_path('module', 'i18n_auto')."/translators", 'name', 0);
|
| 206 |
|
| 207 |
ksort($files);
|
| 208 |
|
| 209 |
if ($load) {
|
| 210 |
foreach ($files as $file) {
|
| 211 |
i18n_auto_include_list($file);
|
| 212 |
}
|
| 213 |
}
|
| 214 |
|
| 215 |
return $files;
|
| 216 |
}
|
| 217 |
|
| 218 |
/**
|
| 219 |
* Maintains a list of all loaded include files.
|
| 220 |
*
|
| 221 |
* @param $file
|
| 222 |
* Optional; a file object (from i18n_auto_system_list()) to be included.
|
| 223 |
* @return
|
| 224 |
* An array of all loaded includes (without the .inc extension).
|
| 225 |
*/
|
| 226 |
function i18n_auto_include_list($file = NULL) {
|
| 227 |
static $list = array();
|
| 228 |
|
| 229 |
// if (!$list) { $list = array(); }
|
| 230 |
|
| 231 |
if ($file && !isset($list[$file->name])) {
|
| 232 |
include_once('./'.$file->filename);
|
| 233 |
$list[$file->name] = $file->name;
|
| 234 |
}
|
| 235 |
|
| 236 |
return $list;
|
| 237 |
}
|
| 238 |
|
| 239 |
/**
|
| 240 |
* Determine whether an include implements a hook, cf. module_hook.
|
| 241 |
*
|
| 242 |
* @param $translator
|
| 243 |
* The name of the translator file (without the .inc extension), such as 'youtube' or 'google'.
|
| 244 |
* @param $hook
|
| 245 |
* The name of the hook (e.g. "thumbnail", "settings", etc.).
|
| 246 |
* @return
|
| 247 |
* TRUE if the translator is loaded and the hook is implemented.
|
| 248 |
*/
|
| 249 |
function i18n_auto_include_hook($translator, $hook) {
|
| 250 |
return function_exists('i18n_auto_' . $translator .'_'. $hook);
|
| 251 |
}
|
| 252 |
|
| 253 |
/**
|
| 254 |
* Invoke hook in a particular include.
|
| 255 |
*
|
| 256 |
* @param $translator
|
| 257 |
* The name of the translator (without the .inc extension).
|
| 258 |
* @param $hook
|
| 259 |
* The name of the hook (e.g. "settings", "thumbnail", etc.).
|
| 260 |
* @param ...
|
| 261 |
* Arguments to pass to the hook implementation.
|
| 262 |
* @return
|
| 263 |
* The return value of the hook implementation.
|
| 264 |
*/
|
| 265 |
function i18n_auto_include_invoke() {
|
| 266 |
$args = func_get_args();
|
| 267 |
$translator = array_shift($args);
|
| 268 |
$hook = array_shift($args);
|
| 269 |
$function = 'i18n_auto_' . $translator . '_' . $hook;
|
| 270 |
i18n_auto_system_list($translator);
|
| 271 |
return i18n_auto_include_hook($translator, $hook) ? call_user_func_array($function, $args) : NULL;
|
| 272 |
}
|
| 273 |
|
| 274 |
// to support PHP 4 users...
|
| 275 |
if (!function_exists("htmlspecialchars_decode")) {
|
| 276 |
function htmlspecialchars_decode($string, $quote_style = ENT_COMPAT) {
|
| 277 |
return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
|
| 278 |
}
|
| 279 |
}
|
| 280 |
|