| Commit | Line | Data |
|---|---|---|
| e46f1746 | 1 | <?php\r |
| e46f1746 JR |
2 | \r |
| 3 | /**\r | |
| 4 | * Internationalization (i18n) package.\r | |
| 5 | * \r | |
| 6 | * Translation module: translation\r | |
| 7 | *\r | |
| 8 | * @author Jose A. Reyero, 2004, http://www.reyero.net\r | |
| 9 | *\r | |
| 10 | */\r | |
| 11 | \r | |
| 94399f15 JR |
12 | // Status for translations\r |
| 13 | define('TRANSLATION_STATUS_NONE', 0);\r | |
| 14 | define('TRANSLATION_STATUS_SOURCE', 1);\r | |
| 15 | define('TRANSLATION_STATUS_WORKING', 2);\r | |
| 16 | define('TRANSLATION_STATUS_TRANSLATED', 3);\r | |
| 17 | define('TRANSLATION_STATUS_UPDATED', 4);\r | |
| 18 | \r | |
| e46f1746 JR |
19 | /**\r |
| 20 | * Implementation of hook_help().\r | |
| 21 | */\r | |
| 22 | function translation_help($section = 'admin/help#translation' ) {\r | |
| 23 | switch ($section) {\r | |
| 24 | case 'admin/help#translation' :\r | |
| 25 | $output = t('\r | |
| 26 | <p>This module is part of i18n package and provides support for translation relationships.</p>\r | |
| 27 | <p>The objects you can define translation relationships for are:</p>\r | |
| 28 | <ul>\r | |
| 29 | <li>Nodes</li>\r | |
| 30 | <li>Taxonomy Terms</li>\r | |
| 31 | </ul>\r | |
| 32 | <p><small>Module developed by Jose A. Reyero, <a href="http://www.reyero.net">www.reyero.net</a></small></p>' );\r | |
| 33 | break;\r | |
| 34 | case 'admin/modules#description' :\r | |
| 35 | $output = t('Manages translations between nodes and taxonomy terms. <b>Requires i18n module</b>' );\r | |
| 36 | break;\r | |
| 37 | case 'admin/access#translation':\r | |
| 38 | $output = t('<h2>Translations</h2>');\r | |
| 39 | $output = t('<strong>translate nodes</strong> <p>This one, combined with create content permissions, will allow to create node translation</p>');\r | |
| 40 | }\r | |
| 41 | return $output;\r | |
| 42 | }\r | |
| 43 | \r | |
| 44 | /**\r | |
| 45 | * Implementation of hook_menu().\r | |
| 46 | */\r | |
| 47 | function translation_menu($may_cache) {\r | |
| 48 | $items = array();\r | |
| 49 | \r | |
| 50 | if ($may_cache) {\r | |
| e46f1746 JR |
51 | $items[] = array(\r |
| 52 | 'path' => 'admin/node/translation',\r | |
| 53 | 'title' => t('translation'),\r | |
| 54 | 'callback' => 'translation_node_admin',\r | |
| 94399f15 | 55 | 'access' => user_access('translate nodes'),\r |
| e46f1746 | 56 | 'type' => MENU_LOCAL_TASK);\r |
| e46f1746 JR |
57 | }\r |
| 58 | else {\r | |
| 59 | if (arg(0) == 'node' && is_numeric(arg(1)) && variable_get('i18n_node_'.translation_get_node_type(arg(1)), 0)) {\r | |
| 60 | $access = user_access('translate nodes');\r | |
| 61 | $type = MENU_LOCAL_TASK; \r | |
| 62 | $items[] = array(\r | |
| 63 | 'path' => 'node/'. arg(1) .'/translation', \r | |
| 64 | 'title' => t('translation'),\r | |
| 65 | 'callback' => 'translation_node_page',\r | |
| 66 | 'access' => $access,\r | |
| 67 | 'type' => $type,\r | |
| 68 | 'weight' => 3);\r | |
| 69 | }\r | |
| 70 | if(arg(0) == 'admin' && arg(1) == 'taxonomy' && is_numeric(arg(2)) ) {\r | |
| 71 | $items[] = array(\r | |
| 72 | 'path' => 'admin/taxonomy/'.arg(2).'/translation', \r | |
| 73 | 'title' => t('translation'),\r | |
| 74 | 'callback' => 'translation_taxonomy_admin',\r | |
| 75 | 'access' => user_access('administer taxonomy'),\r | |
| 76 | 'type' => MENU_LOCAL_TASK);\r | |
| 77 | \r | |
| 78 | }\r | |
| b69d3aa1 JR |
79 | // Special redirections and rewrite conditions\r |
| 80 | if( arg(0) == 'node' && arg(1) == 'add' && isset($_GET['translation']) && ($source_nid = $_GET['translation']) && isset($_GET['language']) && ($lang = $_GET['language']) && array_key_exists($lang, i18n_supported_languages()) ) {\r | |
| 81 | // Special redirection for product types\r | |
| 82 | if (arg(2) == 'product' && !arg(3) && is_numeric($source_nid) && $ptype = db_result(db_query("SELECT ptype FROM {ec_product} WHERE nid = %d", $source_nid))) {\r | |
| 83 | drupal_goto(url("node/add/product/$ptype", "translation=$source_nid&language=$lang", NULL, TRUE));\r | |
| 84 | }\r | |
| 85 | // Change rewrite conditions when translating node\r | |
| e46f1746 JR |
86 | i18n_selection_mode('translation', db_escape_string($lang));\r |
| 87 | }\r | |
| 88 | }\r | |
| 89 | \r | |
| 90 | return $items;\r | |
| 91 | }\r | |
| 92 | \r | |
| 93 | /**\r | |
| 94 | * Implementation of hook_perm\r | |
| 95 | */\r | |
| 96 | function translation_perm(){\r | |
| 97 | return array('translate nodes');\r | |
| 98 | }\r | |
| 99 | \r | |
| 100 | /**\r | |
| 101 | * Implementation of hook_settings\r | |
| 102 | */\r | |
| 103 | function translation_settings(){\r | |
| 104 | $form['i18n_translation_links'] = array(\r | |
| 105 | '#type' => 'radios',\r | |
| 106 | '#title' => t('Language Management'),\r | |
| 107 | '#default_value' => variable_get('i18n_translation_links', 0),\r | |
| 108 | '#options' => array(t('Interface language depends on content.'), t('Interface language is independent')),\r | |
| 109 | '#description' => t("How interface language and content language are managed."),\r | |
| 110 | );\r | |
| 111 | $form['i18n_translation_node_links'] = array(\r | |
| 112 | '#type' => 'radios',\r | |
| 113 | '#title' => t('Links to node translations'),\r | |
| 114 | '#default_value' => variable_get('i18n_translation_node_links', 0),\r | |
| 115 | '#options' => array(t('None.'), t('Main page only'), t('Teaser and Main page')),\r | |
| 116 | '#description' => t("How interface language and content language are managed."),\r | |
| 117 | );\r | |
| 94399f15 JR |
118 | $form['i18n_translation_workflow'] = array(\r |
| 119 | '#type' => 'radios',\r | |
| 120 | '#title' => t('Translation workflow'),\r | |
| 121 | '#default_value' => variable_get('i18n_translation_workflow', 1),\r | |
| 122 | '#options' => array(t('Disabled'), t('Enabled')),\r | |
| 123 | '#description' => t("If enabled some worklow will be provided for content translation."),\r | |
| 124 | ); \r | |
| e46f1746 JR |
125 | return $form; \r |
| 126 | }\r | |
| 127 | /**\r | |
| 94399f15 | 128 | * Implementation of hook_blok().\r |
| e46f1746 JR |
129 | * \r |
| 130 | * This is a simple language switcher which knows nothing about translations\r | |
| 131 | */\r | |
| 132 | function translation_block($op = 'list', $delta = 0) {\r | |
| 133 | if ($op == 'list') {\r | |
| 134 | $blocks[0]['info'] = t('Translations');\r | |
| 135 | }\r | |
| 136 | elseif($op == 'view') {\r | |
| 137 | $blocks['subject'] = t('Languages');\r | |
| 138 | $blocks['content'] = theme('item_list', translation_get_links($_GET['q']));\r | |
| 139 | }\r | |
| 140 | \r | |
| 141 | return $blocks;\r | |
| 142 | }\r | |
| 143 | \r | |
| 144 | /**\r | |
| 94399f15 | 145 | * Implementation of hook_form_alter().\r |
| e46f1746 JR |
146 | */\r |
| 147 | function translation_form_alter($form_id, &$form) {\r | |
| e46f1746 JR |
148 | // Node edit form\r |
| 149 | if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id && variable_get('i18n_node_'.$form['type']['#value'], 0)){\r | |
| 150 | $node = $form['#node'];\r | |
| 151 | $languages = i18n_supported_languages();\r | |
| 94399f15 | 152 | // Translation workflow, default\r |
| e46f1746 JR |
153 | if ($node->nid && $node->translation) {\r |
| 154 | $translations = $node->translation;\r | |
| 155 | }\r | |
| 94399f15 | 156 | elseif (isset($_GET['translation']) && user_access('translate nodes')) {\r |
| e46f1746 | 157 | // We are translating a node: node/add/type/translation/nid/lang\r |
| 94399f15 JR |
158 | $translation_nid = $_GET['translation'];\r |
| 159 | $language = $_GET['language'];\r | |
| e46f1746 JR |
160 | // Load the node to be translated and populate fields\r |
| 161 | $trans = node_load($translation_nid);\r | |
| 162 | $form['i18n']['translation_nid'] = array('#type' => 'hidden', '#value' => $translation_nid);\r | |
| 163 | $form['i18n']['language']['#default_value'] = $language;\r | |
| 164 | translation_node_populate_fields($trans, $form, $node); \r | |
| 165 | if($trans->trid){\r | |
| 166 | $form['i18n']['trid'] = array('#type' => 'hidden', '#value' => $trans->trid);\r | |
| 167 | }\r | |
| 94399f15 | 168 | // Translations are taken from source node \r |
| e46f1746 JR |
169 | $translations = $trans->translation;\r |
| 170 | $translations[$trans->language] = $trans;\r | |
| 171 | }\r | |
| e46f1746 JR |
172 | if ($translations) {\r |
| 173 | // Unset invalid languages\r | |
| 174 | foreach(array_keys($translations) as $lang) {\r | |
| 175 | unset($form['i18n']['language']['#options'][$lang]);\r | |
| 176 | }\r | |
| 177 | // Add translation list\r | |
| 178 | $form['i18n']['#title'] = t('Language and translations');\r | |
| 179 | $form['i18n']['translations'] = array(\r | |
| 180 | '#type' => 'markup',\r | |
| 181 | '#value' => theme('translation_node_list', $translations, FALSE)\r | |
| 182 | );\r | |
| 183 | }\r | |
| 94399f15 JR |
184 | // Translation workflow\r |
| 185 | if (variable_get('i18n_translation_workflow', 1) && (user_access('translate nodes') || user_access('administer nodes'))) {\r | |
| 186 | $form['i18n']['i18n_status'] = array(\r | |
| 187 | '#type' => 'select', \r | |
| 188 | '#title' => t('Translation workflow'), \r | |
| 189 | '#options' => _translation_status(),\r | |
| 190 | '#description' => t('Use the translation workflow to keep track of content that needs translation.'));\r | |
| 191 | if($node->nid) {\r | |
| 192 | $form['i18n']['i18n_status']['#default_value'] = isset($node->i18n_status) ? $node->i18n_status : TRANSLATION_STATUS_NONE;\r | |
| 193 | } elseif(isset($trans)) {\r | |
| 194 | $form['i18n']['i18n_status']['#default_value'] = TRANSLATION_STATUS_WORKING; \r | |
| 195 | }\r | |
| 196 | } else {\r | |
| 197 | $form['i18n']['i18n_status'] = array('#type' => 'value', '#value' => isset($node->i18n_status) ? $node->i18n_status : TRANSLATION_STATUS_NONE);\r | |
| 198 | }\r | |
| 199 | // Clone files for original node ?\r | |
| 200 | if (isset($trans) && is_array($trans->files) && count($trans->files)) {\r | |
| 201 | $form['i18n']['translation_files'] = array(\r | |
| 202 | '#type' => 'fieldset', \r | |
| 203 | '#title' => t('Files from translated content'), \r | |
| 204 | '#tree' => TRUE,\r | |
| 205 | '#prefix' => '<div class="attachments">',\r | |
| 206 | '#suffix' => '</div>',\r | |
| 207 | '#theme' => 'upload_form_current',\r | |
| 208 | '#description' => t('You can remove the files for this translation or keep the original files and translate the description.')\r | |
| 209 | );\r | |
| 210 | foreach($trans->files as $key => $file) {\r | |
| 211 | $description = file_create_url((strpos($file->fid, 'upload') === false ? $file->filepath : file_create_filename($file->filename, file_create_path())));\r | |
| 212 | $description = "<small>". check_plain($description) ."</small>";\r | |
| 213 | $form['i18n']['translation_files'][$key]['description'] = array('#type' => 'textfield', '#default_value' => (strlen($file->description)) ? $file->description : $file->filename, '#maxlength' => 256, '#description' => $description );\r | |
| 214 | $form['i18n']['translation_files'][$key]['size'] = array('#type' => 'markup', '#value' => format_size($file->filesize));\r | |
| 215 | $form['i18n']['translation_files'][$key]['remove'] = array('#type' => 'checkbox', '#default_value' => 0);\r | |
| 216 | $form['i18n']['translation_files'][$key]['list'] = array('#type' => 'checkbox', '#default_value' => $file->list);\r | |
| 217 | $form['i18n']['translation_files'][$key]['fid'] = array('#type' => 'value', '#value' => $file->fid);\r | |
| 218 | }\r | |
| 219 | }\r | |
| e46f1746 JR |
220 | } \r |
| 221 | }\r | |
| 222 | \r | |
| 94399f15 JR |
223 | /**\r |
| 224 | * Implementation of hook_nodeapi().\r | |
| 225 | * \r | |
| 226 | * Delete case is now handled in i18n_nodeapi\r | |
| 227 | */\r | |
| 228 | function translation_nodeapi(&$node, $op, $arg = 0) {\r | |
| 229 | if (variable_get("i18n_node_$node->type", 0)) {\r | |
| 230 | switch ($op) {\r | |
| 231 | case 'load':\r | |
| 232 | $node->translation = translation_node_get_translations(array('nid' =>$node->nid), FALSE);\r | |
| 233 | break;\r | |
| 234 | case 'insert':\r | |
| 235 | if($node->translation_nid) {\r | |
| 236 | // If not existing translation set, update both nodes. Otherwise trid is saved by i18n module\r | |
| 237 | if(!$node->trid){\r | |
| 238 | $node->trid = db_next_id('{i18n_node}_trid');\r | |
| 239 | db_query("UPDATE {i18n_node} SET trid = %d WHERE nid=%d OR nid=%d", $node->trid, $node->nid, $node->translation_nid);\r | |
| 240 | }\r | |
| 241 | // Clone files for node attachments\r | |
| 242 | if(isset($node->translation_files)) {\r | |
| 243 | foreach($node->translation_files as $fid => $file) {\r | |
| 244 | if(!$file['remove']) {\r | |
| 245 | // We are using revisions to have a file linked to different nodes, different descriptions\r | |
| 246 | db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $file['fid'], $node->vid, $file['list'], $file['description']);\r | |
| 247 | }\r | |
| 248 | }\r | |
| 249 | }\r | |
| 250 | }\r | |
| 251 | break;\r | |
| 252 | }\r | |
| 253 | }\r | |
| 254 | }\r | |
| 255 | \r | |
| 256 | /**\r | |
| 257 | * Fills up some fields from source node\r | |
| 258 | */\r | |
| e46f1746 JR |
259 | function translation_node_populate_fields($source, &$form, &$node, $level = 0){\r |
| 260 | $fields = array();\r | |
| 261 | foreach(element_children($form) as $key) {\r | |
| 262 | if($key == 'nid' || $key == 'vid' || $key == 'i18n'){\r | |
| 263 | continue;\r | |
| 264 | } elseif(isset($source->$key) && !isset($node->$key)) {\r | |
| 94399f15 JR |
265 | if($level == 0 && $key == 'parent' && is_numeric($source->parent)) {\r |
| 266 | // Translate book outline\r | |
| e46f1746 JR |
267 | $lang = $form['i18n']['language']['#default_value'];\r |
| 268 | $trans = translation_node_get_translations(array('nid' => $source->parent));\r | |
| 269 | if(isset($trans[$lang])) {\r | |
| 270 | $form['parent']['#default_value'] = $trans[$lang]->nid;\r | |
| 271 | }\r | |
| 272 | } else {\r | |
| 273 | $node->$key = $form[$key]['#default_value'] = $source->$key;\r | |
| 274 | $fields[] = $key;\r | |
| 275 | }\r | |
| 276 | } elseif(!isset($form[$key]['#tree'])) {\r | |
| 277 | translation_node_populate_fields($source, $form[$key], $node, $level +1);\r | |
| 278 | }\r | |
| 279 | }\r | |
| e46f1746 JR |
280 | // For debugging\r |
| 281 | // if($fields) drupal_set_message("Populated fields ($level): ". implode(', ', $fields));\r | |
| 282 | }\r | |
| 94399f15 | 283 | \r |
| e46f1746 JR |
284 | /**\r |
| 285 | * Multilingual Nodes support\r | |
| 286 | */\r | |
| 287 | \r | |
| 288 | /**\r | |
| 289 | * This is the callback for the tab 'translation' for nodes\r | |
| 290 | */\r | |
| 291 | function translation_node_page() {\r | |
| 292 | $args = func_get_args();\r | |
| 293 | $op = isset($_POST['op']) ? $_POST['op'] : $args[0];\r | |
| 294 | $edit = $_POST['edit'];\r | |
| 295 | $nid = arg(1);\r | |
| 296 | $node = node_load($nid);\r | |
| 7991576b JR |
297 | // If node has no language, just warning message. Function returns here\r |
| 298 | if(!$node->language) {\r | |
| 299 | form_set_error('language', t("You need to set a language before creating a translation."));\r | |
| 300 | drupal_goto("node/$nid/edit");\r | |
| 301 | }\r | |
| 63d8e564 | 302 | drupal_set_title(check_plain($node->title));\r |
| e46f1746 | 303 | $output = '';\r |
| e46f1746 JR |
304 | switch($op){\r |
| 305 | case 'select':\r | |
| 306 | $output .= translation_node_overview($node);\r | |
| 307 | $output .= translation_node_form($node, $args[1]);\r | |
| 308 | break;\r | |
| 309 | case t('Save'):\r | |
| 310 | $output .= translation_node_form($node, $args[1]);\r | |
| 311 | break;\r | |
| e46f1746 JR |
312 | default:\r |
| 313 | $output .= translation_node_overview($node);\r | |
| 314 | }\r | |
| 7991576b | 315 | return $output; \r |
| e46f1746 JR |
316 | }\r |
| 317 | \r | |
| 94399f15 JR |
318 | /**\r |
| 319 | * Menu callback: administration page for node translations\r | |
| 320 | */\r | |
| 321 | function translation_node_admin() {\r | |
| 322 | $output = '';\r | |
| 323 | $defaults = array('translation_language' => i18n_get_lang(), 'source_status' => TRANSLATION_STATUS_SOURCE);\r | |
| 324 | $output .= translation_node_admin_form($defaults);\r | |
| 325 | return $output;\r | |
| 326 | } \r | |
| 327 | \r | |
| 328 | /**\r | |
| 329 | * Administrative form for node translations\r | |
| 330 | */\r | |
| 331 | function translation_node_admin_form($defaults = array()) {\r | |
| 332 | $output = '';\r | |
| 333 | // Filters\r | |
| 334 | $output .= node_filter_form();\r | |
| 335 | $output .= translation_filter_form($defaults);\r | |
| 336 | \r | |
| 337 | // First, translation filter because it may need parameters for join conditions\r | |
| 338 | $filter = translation_build_filter_query();\r | |
| 339 | $where = $filter['where'];\r | |
| 340 | $params = $filter['args'];\r | |
| 341 | $join = $filter['join'];\r | |
| 342 | \r | |
| 343 | $filter = node_build_filter_query();\r | |
| 344 | // Remove WHERE \r | |
| 345 | if($filter['where']) {\r | |
| 346 | $where += array(str_replace('WHERE', '', $filter['where']));\r | |
| 347 | }\r | |
| 348 | \r | |
| 349 | $params = array_merge($params, $filter['args']);\r | |
| 350 | \r | |
| 351 | $join .= $filter['join'];\r | |
| 352 | \r | |
| 353 | // Select only source nodes\r | |
| 354 | /*\r | |
| 355 | $params[] = TRANSLATION_STATUS_SOURCE;\r | |
| 356 | $where[] = "i.status = %d";\r | |
| 357 | */\r | |
| 358 | $sql = "SELECT n.nid, n.type, n.title, n.status, u.name, u.uid, i.language, i2.nid AS translation_nid, i2.status AS translation_status ".\r | |
| 359 | "FROM {node} n INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {i18n_node} i ON n.nid = i.nid ".\r | |
| 360 | "LEFT JOIN {i18n_node} i2 ON i.trid = i2.trid AND 0 != i2.trid AND i.language != i2.language $join".\r | |
| 361 | (count($where) ? ' WHERE '.implode(' AND ', $where) : '');\r | |
| 362 | \r | |
| 363 | // Fetch data\r | |
| 364 | //drupal_set_message("DEBUG:query: $sql");\r | |
| 365 | //drupal_set_message("DEBUG:params: ".implode(', ', $params));\r | |
| 366 | i18n_selection_mode('off');\r | |
| 367 | $result = pager_query(db_rewrite_sql($sql), 50, 0, NULL, $params);\r | |
| 368 | i18n_selection_mode('reset');\r | |
| 369 | \r | |
| 370 | $languages = i18n_supported_languages();\r | |
| 371 | $translation_status = _translation_status();\r | |
| 372 | \r | |
| 373 | // Fetch language for translations\r | |
| 374 | $language = isset($_SESSION['translation_filter']['translation_language']) ? $_SESSION['translation_filter']['translation_language'] : i18n_get_lang();\r | |
| 375 | $destination = drupal_get_destination();\r | |
| 376 | while ($node = db_fetch_object($result)) {\r | |
| 377 | $nodes[$node->nid] = '';\r | |
| 378 | $form['language'][$node->nid] = array('#value' => $languages[$node->language]);\r | |
| 379 | $form['title'][$node->nid] = array('#value' => l($node->title, 'node/'. $node->nid) .' '. theme('mark', node_mark($node->nid, $node->changed)));\r | |
| 380 | $form['name'][$node->nid] = array('#value' => node_get_name($node));\r | |
| 381 | $form['username'][$node->nid] = array('#value' => theme('username', $node));\r | |
| 382 | $form['status'][$node->nid] = array('#value' => ($node->status ? t('published') : t('not published')));\r | |
| 383 | if ($node->translation_nid) {\r | |
| 384 | $form['translation_status'][$node->nid] = array('#value' => $translation_status[$node->translation_status]);\r | |
| 385 | $form['operations'][$node->nid] = array('#value' => l(t('edit translation'), 'node/'. $node->translation_nid .'/edit', array(), $destination));\r | |
| 386 | } else {\r | |
| 387 | $form['translation_status'][$node->nid] = array('#value' => '--');\r | |
| 388 | if($language == $node->language) {\r | |
| 389 | $form['operations'][$node->nid] = array('#value' => '--');\r | |
| 390 | } else {\r | |
| 391 | $form['operations'][$node->nid] = array('#value' => l(t('create translation'), 'node/add/'.$node->type, array(), "translation=$node->nid&language=$language").\r | |
| 392 | ' | '.l(t('select node'), "node/$node->nid/translation/select/$language", array(), $destination)); \r | |
| 393 | }\r | |
| 394 | }\r | |
| 395 | }\r | |
| 396 | /*\r | |
| 397 | $form['nodes'] = array('#type' => 'checkboxes', '#options' => $nodes);\r | |
| 398 | */\r | |
| 399 | $form['pager'] = array('#value' => theme('pager', NULL, 50, 0));\r | |
| 400 | $output .= drupal_get_form('translation_admin_nodes', $form);\r | |
| 401 | return $output; \r | |
| 402 | }\r | |
| 403 | \r | |
| 404 | \r | |
| 405 | /**\r | |
| 406 | * Build query for node administration filters based on session.\r | |
| 407 | */\r | |
| 408 | function translation_build_filter_query() {\r | |
| 409 | \r | |
| 410 | // Build query\r | |
| 411 | $where = $args = array();\r | |
| 412 | $join = '';\r | |
| 413 | // This will produce an empty join\r | |
| 414 | if (!is_array($_SESSION['translation_filter'])) {\r | |
| 415 | $_SESSION['translation_filter'] = array();\r | |
| 416 | }\r | |
| 417 | foreach ($_SESSION['translation_filter'] as $type => $value) {\r | |
| 418 | switch($type) {\r | |
| 419 | case 'source_language':\r | |
| 420 | $where[] = "i.language = '%s'";\r | |
| 421 | $args[] = $value;\r | |
| 422 | break;\r | |
| 423 | case 'translation_language':\r | |
| 424 | $join .= " AND i2.language ='".db_escape_string($value)."' ";\r | |
| 425 | break;\r | |
| 426 | case 'source_status':\r | |
| 427 | $where[] = "i.status = %d";\r | |
| 428 | $args[] = $value;\r | |
| 429 | break;\r | |
| 430 | case 'translation_status':\r | |
| 431 | $join .= " AND i2.status = ".db_escape_string($value);\r | |
| 432 | break;\r | |
| 433 | }\r | |
| 434 | }\r | |
| 435 | \r | |
| 436 | return array('where' => $where, 'join' => $join, 'args' => $args);\r | |
| 437 | }\r | |
| 438 | \r | |
| 439 | /**\r | |
| 440 | * Returns form for translation administration filters.\r | |
| 441 | */\r | |
| 442 | function translation_filter_form($defaults = array()) {\r | |
| 443 | $session = &$_SESSION['translation_filter'];\r | |
| 444 | $session = is_array($session) ? $session : $defaults;\r | |
| 445 | \r | |
| 446 | // Save defaults for form reset\r | |
| 447 | $form['_defaults'] = array('#type' => 'value', '#value' => $defaults);\r | |
| 448 | $form['filters'] = array('#type' => 'fieldset',\r | |
| 449 | '#title' => t('And translation conditions are'),\r | |
| 450 | );\r | |
| 451 | $languages = i18n_supported_languages();\r | |
| 452 | // Translation and language conditions\r | |
| 453 | \r | |
| 454 | $form['filters']['source_language'] = array('#type' => 'select', '#title' => t('source language'),\r | |
| 455 | '#options' => array('' => '') + $languages, '#default_value' => $session['source_language']);\r | |
| 456 | $form['filters']['source_status'] = array('#type' => 'select', '#title' => t('source status'),\r | |
| 457 | '#options' => array('' => '') + _translation_status(), '#default_value' => $session['source_status']);\r | |
| 458 | $form['filters']['translation_language'] = array('#type' => 'select', '#title' => t('translation language'),\r | |
| 459 | '#options' => array('' => '') + $languages, '#default_value' => $session['translation_language']); \r | |
| 460 | $form['filters']['translation_status'] = array('#type' => 'select', '#title' => t('translation status'),\r | |
| 461 | '#options' => array('' => '') + _translation_status(), '#default_value' => $session['translation_status']);\r | |
| 462 | $form['filters']['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Filter'));\r | |
| 463 | if (count($session)) {\r | |
| 464 | $form['filters']['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset'));\r | |
| 465 | }\r | |
| 466 | return drupal_get_form('translation_filter_form', $form);\r | |
| 467 | }\r | |
| 468 | \r | |
| 469 | function theme_translation_filter_form($form) {\r | |
| 470 | $form['filters']['source_language']['#prefix'] = '<table><tr><td>';\r | |
| 471 | $form['filters']['source_status']['#suffix'] = '</td><td>';\r | |
| 472 | $form['filters']['buttons']['#prefix'] = '</td><td>';\r | |
| 473 | $form['filters']['buttons']['#suffix'] = '</td></tr></table>';\r | |
| 474 | return form_render($form);\r | |
| 475 | }\r | |
| 476 | /**\r | |
| 477 | * Builds translation admin filters\r | |
| 478 | */\r | |
| 479 | function translation_filter_form_submit($form_id, $form_values) {\r | |
| 480 | $op = $_POST['op'];\r | |
| 481 | $session = &$_SESSION['translation_filter'];\r | |
| 482 | \r | |
| 483 | switch ($op) {\r | |
| 484 | case t('Filter'):\r | |
| 485 | $session = array();\r | |
| 486 | foreach($form_values as $name => $value) {\r | |
| 487 | if($value) $session[$name] = $value;\r | |
| 488 | }\r | |
| 489 | break;\r | |
| 490 | case t('Reset'):\r | |
| 491 | $session = $form_values['_defaults'];\r | |
| 492 | break;\r | |
| 493 | }\r | |
| 494 | \r | |
| 495 | }\r | |
| 496 | /**\r | |
| 497 | * Theme node administration overview.\r | |
| 498 | */\r | |
| 499 | function theme_translation_admin_nodes($form) {\r | |
| 500 | // Overview table:\r | |
| 501 | $header = array(t('Language'), t('Title'), t('Type'), t('Author'), t('Status'), t('Translation status'), t('Operations'));\r | |
| 502 | \r | |
| 503 | $output .= form_render($form['options']);\r | |
| 504 | if (isset($form['title']) && is_array($form['title'])) {\r | |
| 505 | foreach (element_children($form['title']) as $key) {\r | |
| 506 | $row = array();\r | |
| 507 | $row[] = form_render($form['language'][$key]);\r | |
| 508 | $row[] = form_render($form['title'][$key]);\r | |
| 509 | $row[] = form_render($form['name'][$key]);\r | |
| 510 | $row[] = form_render($form['username'][$key]);\r | |
| 511 | $row[] = form_render($form['status'][$key]);\r | |
| 512 | $row[] = form_render($form['translation_status'][$key]);\r | |
| 513 | $row[] = form_render($form['operations'][$key]);\r | |
| 514 | $rows[] = $row;\r | |
| 515 | }\r | |
| 516 | \r | |
| 517 | }\r | |
| 518 | else {\r | |
| 519 | $rows[] = array(array('data' => t('No posts available.'), 'colspan' => '6'));\r | |
| 520 | }\r | |
| 521 | \r | |
| 522 | $output .= theme('table', $header, $rows);\r | |
| 523 | if ($form['pager']['#value']) {\r | |
| 524 | $output .= form_render($form['pager']);\r | |
| 525 | }\r | |
| 526 | \r | |
| 527 | $output .= form_render($form);\r | |
| 528 | \r | |
| 529 | return $output;\r | |
| 530 | }\r | |
| 531 | \r | |
| e46f1746 JR |
532 | function translation_node_overview($node) {\r |
| 533 | $languages = i18n_supported_languages();\r | |
| 534 | unset($languages[$node->language]);\r | |
| 535 | $output = t('<h2>Current translations</h2>');\r | |
| 94399f15 | 536 | $header = array(t('Language'), t('Title'), t('Status'), t('Options'));\r |
| b69d3aa1 JR |
537 | // Special links for product nodes\r |
| 538 | $createlink = $node->type == 'product' ? "node/add/$node->type/$node->ptype" : "node/add/$node->type";\r | |
| e46f1746 JR |
539 | foreach($languages as $lang => $langname){\r |
| 540 | $options = array();\r | |
| 541 | if(isset($node->translation[$lang])){\r | |
| 542 | $trnode = $node->translation[$lang];\r | |
| 543 | $title = l($trnode->title, 'node/'.$trnode->nid);\r | |
| 94399f15 | 544 | $status = $trnode->status ? t('Published') : t('Not published');\r |
| e46f1746 JR |
545 | } else {\r |
| 546 | $title = t('Not translated');\r | |
| b69d3aa1 | 547 | $options[] = l(t('create translation'), $createlink , array(), "translation=$node->nid&language=$lang");\r |
| 94399f15 JR |
548 | $status = '--';\r |
| 549 | }\r | |
| e46f1746 | 550 | $options[] = l(t('select node'), "node/$node->nid/translation/select/$lang");\r |
| 94399f15 | 551 | $rows[] = array($langname, $title, $status, implode(" | ", $options));\r |
| e46f1746 JR |
552 | }\r |
| 553 | $output .= theme('table', $header, $rows);\r | |
| 63d8e564 JR |
554 | if ($node->trid){\r |
| 555 | $form['node'] = array('#type' => 'value', '#value' => $node);\r | |
| e46f1746 | 556 | $form['submit'] = array('#type' => 'submit', '#value' => t('Remove'), '#suffix' => t('Remove node from this translation set'));\r |
| 63d8e564 | 557 | $output .= drupal_get_form('translation_node_remove', $form);\r |
| e46f1746 JR |
558 | }\r |
| 559 | return $output;\r | |
| 560 | }\r | |
| 561 | \r | |
| 94399f15 | 562 | /**\r |
| 63d8e564 JR |
563 | * Form submit. Remove node from translation\r |
| 564 | */\r | |
| 565 | function translation_node_remove_submit($form_id, $form_values) {\r | |
| 566 | $node = $form_values['node'];\r | |
| 567 | db_query("UPDATE {i18n_node} SET trid = 0 WHERE nid=%d", $node->nid);\r | |
| 568 | drupal_set_message(t("The node has been removed from the translation set"));\r | |
| 569 | drupal_goto("node/$node->nid/translation"); \r | |
| 570 | }\r | |
| 571 | \r | |
| 572 | /**\r | |
| 94399f15 JR |
573 | * Form to select a translation from existing nodes\r |
| 574 | */\r | |
| e46f1746 | 575 | function translation_node_form($node, $lang){\r |
| 63d8e564 | 576 | $form['node'] = array('#type' => 'value', '#value' =>$node);\r |
| e46f1746 JR |
577 | $form['language'] = array('#type' => 'hidden', '#value' => $lang);\r |
| 578 | $form['source_nid'] = array('#type' => 'hidden', '#value' => $node->nid);\r | |
| 579 | $form['trid'] = array('#type' => 'hidden', '#value' => $node->trid);\r | |
| 580 | $languages = i18n_supported_languages();\r | |
| 581 | \r | |
| 582 | // Disable i18n rewrite. Order by trid to show first nodes with no translation\r | |
| 583 | i18n_selection_mode('off');\r | |
| 584 | $result = pager_query(db_rewrite_sql("SELECT n.nid, n.title FROM {node} n INNER JOIN {i18n_node} i ON n.nid = i.nid WHERE i.language = '%s' ORDER BY i.trid"), 40, 0, NULL, $lang);\r | |
| 585 | i18n_selection_mode('reset');\r | |
| 586 | while($trnode = db_fetch_object($result)){\r | |
| 587 | $list[$trnode->nid] = l($trnode->title, "node/$trnode->nid") ;\r | |
| 588 | }\r | |
| 589 | if($list){\r | |
| 590 | $form['nodes']['nid'] = array(\r | |
| 591 | '#type' => 'radios', '#title' => t('Select translation for %language', array('%language' => $languages[$lang])), \r | |
| 592 | '#default_value' => isset($node->translation[$lang]) ? $node->translation[$lang]->nid : '',\r | |
| 593 | '#options' => $list);\r | |
| 594 | $form['pager'] = array('#value' => theme('pager'));\r | |
| 595 | $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));\r | |
| 596 | return drupal_get_form('translation_node_form', $form);\r | |
| 597 | } else {\r | |
| 598 | return t("<p>No nodes available in %language</p>", array('%language' => $languages[$lang]) );\r | |
| 94399f15 | 599 | } \r |
| e46f1746 JR |
600 | }\r |
| 601 | \r | |
| 94399f15 JR |
602 | /**\r |
| 603 | * Process translation node form\r | |
| 604 | */\r | |
| e46f1746 JR |
605 | function translation_node_form_submit($form_id, $form_values){\r |
| 606 | $op = $_POST['op'];\r | |
| 607 | $source_nid = $form_values['source_nid'];\r | |
| 608 | $language = $form_values['language'];\r | |
| 609 | $nid = $form_values['nid'];\r | |
| 610 | if( $source_nid && $language && $nid ) {\r | |
| 611 | if($trid = $form_values['trid']){\r | |
| 612 | // Delete old translations\r | |
| 613 | db_query("UPDATE {i18n_node} SET trid = 0 WHERE trid = %d AND language = '%s'", $trid, $language);\r | |
| 614 | } else {\r | |
| 615 | $trid = db_next_id('{i18n_node}_trid');\r | |
| 616 | }\r | |
| 617 | db_query("UPDATE {i18n_node} SET trid = %d WHERE nid=%d OR nid=%d", $trid, $source_nid, $nid); \r | |
| 618 | drupal_set_message(t('The translation has been saved'));\r | |
| 619 | \r | |
| 620 | } \r | |
| 621 | }\r | |
| 622 | \r | |
| 623 | /**\r | |
| e46f1746 JR |
624 | * Taxonomy hook\r |
| 625 | * $edit parameter is an array, not an object !!\r | |
| 626 | */\r | |
| 627 | // $op = insert, update, delete\r | |
| 628 | function translation_taxonomy($op, $type, $edit = NULL) {\r | |
| 629 | switch ("$type/$op") {\r | |
| 630 | case 'term/insert':\r | |
| 631 | case 'term/update':\r | |
| 632 | if (!$edit['language'] && $edit['trid']) {\r | |
| 633 | // Removed language, remove trid\r | |
| 634 | db_query('UPDATE {term_data} SET trid=0 WHERE tid=%d', $edit['tid']);\r | |
| 635 | if(db_affected_rows()) drupal_set_message(t('Removed translation information from term'));\r | |
| 636 | }\r | |
| 637 | break;\r | |
| 638 | }\r | |
| 639 | } \r | |
| 640 | /**\r | |
| 641 | * Implementation of hook_link().\r | |
| 642 | */\r | |
| 643 | function translation_link($type, $node = NULL, $teaser = FALSE) {\r | |
| 644 | $languages = i18n_supported_languages();\r | |
| 645 | $links = array();\r | |
| 646 | if ($type == 'node' && variable_get('i18n_translation_node_links', 0) > ($teaser ? 1 : 0) && $node->translation) {\r | |
| 647 | foreach ($node->translation as $lang => $trnode) {\r | |
| 94399f15 JR |
648 | // Add node link if published\r |
| 649 | if($trnode->status) {\r | |
| e46f1746 JR |
650 | $baselang = variable_get('i18n_translation_links', 0) ? i18n_get_lang() : $lang;\r |
| 651 | $links[]= theme('translation_node_link', $trnode , $lang, $baselang);\r | |
| 94399f15 JR |
652 | }\r |
| 653 | }\r | |
| e46f1746 JR |
654 | }\r |
| 655 | return $links;\r | |
| 656 | }\r | |
| 657 | \r | |
| 658 | /**\r | |
| 659 | * Returns a list for terms for vocabulary, language\r | |
| 660 | */\r | |
| 661 | function translation_vocabulary_get_terms($vid, $lang, $status = 'all') {\r | |
| 662 | switch($status){\r | |
| 663 | case 'translated':\r | |
| 664 | $andsql = ' AND trid > 0';\r | |
| 665 | break;\r | |
| 666 | case 'untranslated':\r | |
| 667 | $andsql = ' AND trid = 0';\r | |
| 668 | break;\r | |
| 669 | default:\r | |
| 670 | $andsql = '';\r | |
| 671 | }\r | |
| 672 | $result = db_query("SELECT * FROM {term_data} WHERE vid=%d AND language='%s' $andsql", $vid, $lang);\r | |
| 673 | $list = array();\r | |
| 674 | while ($term = db_fetch_object($result)) {\r | |
| 675 | $list[$term->tid] = $term->name;\r | |
| 676 | }\r | |
| 677 | return $list; \r | |
| 678 | }\r | |
| 679 | \r | |
| 680 | /**\r | |
| 681 | * Get translations\r | |
| 94399f15 JR |
682 | *\r |
| 683 | * @param $params\r | |
| 684 | * array of parameters\r | |
| 685 | * @param $getall\r | |
| 686 | * TRUE to get the also node itself\r | |
| e46f1746 | 687 | */\r |
| e46f1746 JR |
688 | function translation_node_get_translations($params, $getall = TRUE) {\r |
| 689 | foreach($params as $field => $value) {\r | |
| 690 | $conds[] = "b.$field = '%s'";\r | |
| 691 | $values[] = $value;\r | |
| 692 | }\r | |
| 693 | if(!$getall){ // If not all, a parameter must be nid\r | |
| 694 | $conds[] = "n.nid != %d";\r | |
| 695 | $values[] = $params['nid'];\r | |
| 696 | }\r | |
| 697 | $conds[] = "b.trid != 0";\r | |
| 698 | $sql = 'SELECT n.nid, n.title, n.status, a.language FROM {node} n INNER JOIN {i18n_node} a ON n.nid = a.nid INNER JOIN {i18n_node} b ON a.trid = b.trid WHERE '. implode(' AND ', $conds);\r | |
| 699 | \r | |
| 700 | i18n_selection_mode('off');\r | |
| 701 | $result = db_query(db_rewrite_sql($sql), $values);\r | |
| 702 | i18n_selection_mode('reset');\r | |
| 703 | \r | |
| 704 | $items = array();\r | |
| 705 | while ($node = db_fetch_object($result)) {\r | |
| 706 | $items[$node->language] = $node;\r | |
| 707 | }\r | |
| 708 | return $items;\r | |
| 709 | }\r | |
| 710 | \r | |
| 94399f15 JR |
711 | /**\r |
| 712 | * Returns node type for nid\r | |
| 713 | */\r | |
| e46f1746 JR |
714 | function translation_get_node_type($nid) {\r |
| 715 | return db_result(db_query('SELECT type FROM {node} WHERE nid=%d', $nid));\r | |
| 716 | }\r | |
| 94399f15 | 717 | \r |
| e46f1746 JR |
718 | /**\r |
| 719 | * Multilingual Taxonomy\r | |
| 720 | *\r | |
| 721 | */\r | |
| 722 | \r | |
| 723 | /**\r | |
| 724 | * This is the callback for taxonomy translations\r | |
| 725 | * \r | |
| 726 | * Gets the urls:\r | |
| 727 | * admin/taxonomy/i18n/term/xx\r | |
| 728 | * admin/taxonomy/i18n/term/new/xx\r | |
| 729 | * admin/taxonomy/vid/translation/op/trid\r | |
| 730 | */\r | |
| 731 | \r | |
| 732 | function translation_taxonomy_admin() {\r | |
| 733 | $vid = arg(2);\r | |
| 734 | $op = $_POST['op'] ? $_POST['op'] : arg(4);\r | |
| 735 | $edit = $_POST['edit'];\r | |
| 736 | \r | |
| 737 | switch ($op) {\r | |
| 738 | case t('Save'): \r | |
| 739 | case 'edit':\r | |
| 740 | drupal_set_title(t('Edit term translations'));\r | |
| 741 | $output = translation_taxonomy_form($vid, arg(5), $edit);\r | |
| 742 | break;\r | |
| 743 | case t('Submit'):\r | |
| 744 | drupal_set_title(t('Submit'));\r | |
| 745 | translation_taxonomy_term_save($edit);\r | |
| 746 | $output = translation_taxonomy_overview($vid);\r | |
| 747 | break;\r | |
| 748 | case 'delete':\r | |
| 749 | //print theme('page', node_delete($edit), t('Delete'));\r | |
| 750 | break;\r | |
| 751 | default:\r | |
| 752 | $output = translation_taxonomy_overview($vid);\r | |
| 753 | }\r | |
| 754 | return $output; \r | |
| 755 | } \r | |
| 756 | \r | |
| 757 | /**\r | |
| 758 | * Generate a tabular listing of translations for vocabularies.\r | |
| 759 | */\r | |
| e46f1746 JR |
760 | function translation_taxonomy_overview($vid) {\r |
| 761 | $vocabulary = taxonomy_get_vocabulary($vid);\r | |
| 762 | drupal_set_title(check_plain($vocabulary->name));\r | |
| 763 | \r | |
| 764 | $languages = i18n_supported_languages();\r | |
| 765 | $header = array_merge($languages, array(t('Operations')));\r | |
| 766 | $links = array();\r | |
| 767 | $types = array();\r | |
| 768 | // Get terms/translations for this vocab \r | |
| 769 | $result = db_query('SELECT * FROM {term_data} t WHERE vid=%d',$vocabulary->vid);\r | |
| 770 | $terms = array();\r | |
| 771 | while ($term = db_fetch_object($result)) {\r | |
| 772 | if($term->trid && $term->language) {\r | |
| 773 | $terms[$term->trid][$term->language] = $term;\r | |
| 774 | }\r | |
| 775 | }\r | |
| 776 | // Reorder data for rows and languages\r | |
| 777 | foreach ($terms as $trid => $terms) {\r | |
| 778 | $thisrow = array();\r | |
| 779 | foreach ($languages as $lang => $name) {\r | |
| 780 | if (array_key_exists($lang, $terms)) {\r | |
| 63d8e564 | 781 | $thisrow[] = l($terms[$lang]->name, 'taxonomy/term/'.$terms[$lang]->tid);\r |
| e46f1746 JR |
782 | }\r |
| 783 | else {\r | |
| 784 | $thisrow[] = '--';\r | |
| 785 | }\r | |
| 786 | }\r | |
| 787 | $thisrow[] = l(t('edit'), "admin/taxonomy/$vid/translation/edit/$trid");\r | |
| 788 | $rows[] = $thisrow;\r | |
| 789 | }\r | |
| 790 | $output .= theme('table', $header, $rows);\r | |
| 791 | $output .= l(t('new translation'), "admin/taxonomy/$vid/translation/edit/new");\r | |
| 792 | return $output;\r | |
| 793 | }\r | |
| 794 | \r | |
| 94399f15 JR |
795 | /**\r |
| 796 | * Produces a vocabulary translation form\r | |
| 797 | */\r | |
| e46f1746 JR |
798 | function translation_taxonomy_form($vid, $trid = NULL, $edit = array()) {\r |
| 799 | $languages = i18n_supported_languages();\r | |
| 800 | if ($trid == 'new') {\r | |
| 801 | $translations = array();\r | |
| 802 | } else {\r | |
| 803 | $form['trid'] = array('#type' => 'hidden', '#value' => $trid);\r | |
| 804 | $translations = translation_term_get_translations(array('trid' =>$trid));\r | |
| 805 | } \r | |
| 806 | //var_dump($translations);\r | |
| 807 | $vocabulary = taxonomy_get_vocabulary($vid);\r | |
| 808 | \r | |
| 809 | // List of terms for languages\r | |
| 810 | foreach ($languages as $lang => $langname) {\r | |
| 811 | $current = isset($translations[$lang]) ? $translations[$lang]->tid : '';\r | |
| 812 | $list = translation_vocabulary_get_terms($vid, $lang, 'all');\r | |
| 813 | $list[''] = '--';\r | |
| 814 | $form[$lang] = array('#type' => 'fieldset', '#tree' => TRUE);\r | |
| 815 | $form[$lang]['tid'] = array(\r | |
| 816 | '#type' => 'select', \r | |
| 817 | '#title' => $langname,\r | |
| 818 | '#default_value' => $current,\r | |
| 819 | '#options' => $list\r | |
| 820 | );\r | |
| 821 | $form[$lang]['old'] = array('#type' => 'hidden', '#value' =>$current);\r | |
| 822 | }\r | |
| 823 | \r | |
| 824 | $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));\r | |
| 825 | return drupal_get_form('translation_taxonomy', $form);\r | |
| 826 | }\r | |
| 827 | \r | |
| 94399f15 JR |
828 | /**\r |
| 829 | * Process vocabulary translation form\r | |
| 830 | */\r | |
| e46f1746 JR |
831 | function translation_taxonomy_submit($form_id, $form_values) {\r |
| 832 | $trid = $form_values['trid'];\r | |
| 833 | $languages = i18n_supported_languages();\r | |
| 834 | $translations = array();\r | |
| 835 | // Delete old translations\r | |
| 836 | if($trid){\r | |
| 63d8e564 | 837 | db_query("UPDATE {term_data} SET trid = 0 WHERE trid = %d", $trid);\r |
| e46f1746 JR |
838 | }\r |
| 839 | foreach ($languages as $lang => $name) {\r | |
| 840 | if (is_numeric($form_values[$lang]['tid'])) {\r | |
| 841 | $translations[$lang] = $form_values[$lang]['tid'];\r | |
| 842 | }\r | |
| 843 | }\r | |
| 844 | if(count($translations)) {\r | |
| 845 | $trid = is_numeric($trid) ? $trid : db_next_id('{term_data}_trid');\r | |
| 63d8e564 | 846 | db_query('UPDATE {term_data} SET trid=%d WHERE tid IN (%s)', $trid, implode(',',$translations));\r |
| e46f1746 JR |
847 | }\r |
| 848 | drupal_set_message(t('Term translations have been updated'));\r | |
| 849 | }\r | |
| 850 | \r | |
| 851 | /**\r | |
| 852 | * Converts a list of arrays to an array of the form keyfield => namefield\r | |
| 853 | */\r | |
| 854 | function translation_array2list($data, $keyfield, $namefield = 'name') {\r | |
| 855 | foreach ($data as $key => $value) {\r | |
| 856 | if (is_array($data)) {\r | |
| 857 | $list[$value[$keyfield]] = $value[$namefield];\r | |
| 858 | }\r | |
| 859 | else {\r | |
| 860 | $list[$value->$keyfield] = $value->$namefield;\r | |
| 861 | }\r | |
| 862 | }\r | |
| 863 | return $list;\r | |
| 864 | }\r | |
| 865 | \r | |
| 94399f15 JR |
866 | /**\r |
| 867 | * Get term translations\r | |
| 868 | * \r | |
| 869 | * @return\r | |
| 870 | * An array of the from lang => Term\r | |
| 871 | */ \r | |
| e46f1746 JR |
872 | function translation_term_get_translations($params, $getall = TRUE) {\r |
| 873 | foreach($params as $field => $value) {\r | |
| 874 | $conds[] = "i.$field = '%s'";\r | |
| 875 | $values[] = $value;\r | |
| 876 | }\r | |
| 877 | if(!$getall){ // If not all, a parameter must be tid\r | |
| 878 | $conds[] = "t.tid != %d";\r | |
| 879 | $values[] = $params['tid'];\r | |
| 94399f15 JR |
880 | }\r |
| 881 | $conds[] = "t.trid != 0";\r | |
| e46f1746 JR |
882 | $sql = 'SELECT t.* FROM {term_data} t INNER JOIN {term_data} i ON t.trid = i.trid WHERE '. implode(' AND ', $conds);;\r |
| 883 | $result = db_query($sql, $values);\r | |
| 884 | $items = array();\r | |
| 885 | while ($data = db_fetch_object($result)) {\r | |
| 886 | $items[$data->language] = $data;\r | |
| 887 | }\r | |
| 888 | return $items; \r | |
| 889 | }\r | |
| 890 | \r | |
| 94399f15 JR |
891 | /**\r |
| 892 | * Produces url of translated page\r | |
| 893 | */\r | |
| e46f1746 JR |
894 | function translation_url($url, $lang) {\r |
| 895 | global $i18n_langpath;\r | |
| 896 | // If !url get from original request\r | |
| 897 | if (!$url) {\r | |
| 898 | $url = _i18n_get_original_path();\r | |
| 899 | }\r | |
| 900 | // If url has lang_prefix, remove it\r | |
| 901 | i18n_get_lang_prefix($url, true);\r | |
| 902 | // are we looking at a node?\r | |
| 903 | if (preg_match("/^(node\/)([0-9]*)$/",$url,$matches)) {\r | |
| 904 | if ($nid = translation_node_nid($matches[2], $lang)) {\r | |
| 905 | $url = "node/$nid";\r | |
| 906 | }\r | |
| 907 | }\r | |
| 908 | // or a taxonomy term\r | |
| 909 | elseif (preg_match("/^(taxonomy\/term\/)([^\/]*)$/",$url,$matches)) {//or at a taxonomy-listing?\r | |
| 910 | if ($str_tids = translation_taxonomy_tids($matches[2], $lang)) {\r | |
| 911 | $url = "taxonomy/term/$str_tids";\r | |
| 912 | }\r | |
| 913 | }\r | |
| 914 | \r | |
| 915 | return $url;\r | |
| 916 | }\r | |
| 917 | \r | |
| 918 | /**\r | |
| 919 | * Returns an url-part, pointing to the translated node, if exists \r | |
| 920 | */\r | |
| 921 | function translation_node_nid($nid, $lang) {\r | |
| 922 | $sql = 'SELECT n.nid FROM {i18n_node} n INNER JOIN {i18n_node} a ON n.nid = a.nid INNER JOIN {i18n_node} b ON a.trid = b.trid AND b.nid =%d WHERE n.nid != %d AND n.language = \'%s\' AND a.trid != 0';\r | |
| 923 | return db_result(db_query($sql, $nid, $nid, $lang));\r | |
| 924 | }\r | |
| 925 | /**\r | |
| 926 | * Returns an url for the translated taxonomy-page, if exists \r | |
| 927 | */\r | |
| 928 | function translation_taxonomy_tids($str_tids, $lang) {\r | |
| 929 | if (preg_match('/^([0-9]+[+ ])+[0-9]+$/', $str_tids)) {\r | |
| 930 | $separator = '+';\r | |
| 931 | // The '+' character in a query string may be parsed as ' '.\r | |
| 932 | $tids = preg_split('/[+ ]/', $str_tids);\r | |
| 933 | }\r | |
| 934 | else if (preg_match('/^([0-9]+,)*[0-9]+$/', $str_tids)) {\r | |
| 935 | $separator = ',';\r | |
| 936 | $tids = explode(',', $str_tids);\r | |
| 937 | }\r | |
| 938 | else {\r | |
| 939 | return;\r | |
| 940 | }\r | |
| 941 | $translated_tids = array();\r | |
| 942 | foreach ($tids as $tid) {\r | |
| 943 | if ($translated_tid = translation_term_get_translations(array('tid' =>$tid))) {\r | |
| 944 | $translated_tids[] = $translated_tid[$lang]->tid;\r | |
| 945 | }\r | |
| 946 | }\r | |
| 947 | return implode($separator, $translated_tids);\r | |
| 948 | }\r | |
| 94399f15 | 949 | \r |
| e46f1746 JR |
950 | /**\r |
| 951 | * function translation_get_links\r | |
| 952 | * \r | |
| 953 | * Returns an array of links for all languages, with or without names\r | |
| 954 | */\r | |
| 955 | function translation_get_links($path = '', $names = 1) {\r | |
| 956 | $current = i18n_get_lang();\r | |
| 957 | foreach(i18n_supported_languages() as $lang => $name){\r | |
| 958 | $url = translation_url($path, $lang);\r | |
| 959 | $name = $names ? $name: '' ; // Should be localized??\r | |
| 960 | $links[]= theme('i18n_link', $name, i18n_path($url, $lang) , $lang);\r | |
| 961 | }\r | |
| 962 | return $links; \r | |
| 963 | }\r | |
| 964 | \r | |
| 965 | /**\r | |
| 94399f15 JR |
966 | * Return status for translations workflow\r |
| 967 | */\r | |
| 968 | function _translation_status(){\r | |
| 969 | return array(\r | |
| 970 | TRANSLATION_STATUS_NONE => t('None'), \r | |
| 971 | TRANSLATION_STATUS_SOURCE => t('Source content (to be translated)'), \r | |
| 972 | TRANSLATION_STATUS_WORKING => t('Translation in progress'), \r | |
| 973 | TRANSLATION_STATUS_TRANSLATED => t('Translated content'),\r | |
| 974 | TRANSLATION_STATUS_UPDATED => t('Source updated (to update translation)'));\r | |
| 975 | }\r | |
| 976 | \r | |
| 977 | /**\r | |
| 978 | * Theme a link to node translation\r | |
| e46f1746 JR |
979 | */\r |
| 980 | function theme_translation_node_link($node, $lang, $baselang = NULL, $title = FALSE){\r | |
| 981 | $baselang = $baselang ? $baselang : $lang;\r | |
| 982 | if($title){\r | |
| 983 | $name = $node->title;\r | |
| 984 | } else {\r | |
| 985 | $languages = i18n_supported_languages();\r | |
| 986 | $name = $languages[$lang];\r | |
| 987 | }\r | |
| 988 | return theme('i18n_link', $name, i18n_path('node/'.$node->nid, $baselang), $lang);\r | |
| 989 | }\r | |
| 990 | \r | |
| 94399f15 JR |
991 | /**\r |
| 992 | * Theme a link for a translation\r | |
| 993 | */\r | |
| e46f1746 JR |
994 | function theme_translation_link($text, $target, $lang, $separator=' ') {\r |
| 995 | return theme('i18n_link', $text, $target, $lang, $separator);\r | |
| 996 | }\r | |
| 997 | \r | |
| 94399f15 JR |
998 | /**\r |
| 999 | * Theme list of node translations\r | |
| 1000 | */\r | |
| e46f1746 JR |
1001 | function theme_translation_node_list($list){\r |
| 1002 | $header = array(t('Language'), t('Title'));\r | |
| 1003 | $languages = i18n_supported_languages();\r | |
| 1004 | foreach($list as $lang => $node){\r | |
| 1005 | $rows[] = array($languages[$lang], l($node->title, 'node/'.$node->nid) );\r | |
| 1006 | }\r | |
| 1007 | return theme('table', $header, $rows);\r | |
| 1008 | }\r | |
| d48b38b0 | 1009 | ?> |