View source
<?php
define('TRANSLATION_STATUS_NONE', 0);
define('TRANSLATION_STATUS_SOURCE', 1);
define('TRANSLATION_STATUS_WORKING', 2);
define('TRANSLATION_STATUS_TRANSLATED', 3);
define('TRANSLATION_STATUS_UPDATED', 4);
function translation_help($section = 'admin/help#translation') {
switch ($section) {
case 'admin/help#translation':
$output = '<p>' . t('This module is part of i18n package and provides support for translation relationships.') . '</p>';
$output .= '<p>' . t('The objects you can define translation relationships for are:') . '</p>';
$output .= '<ul>';
$output .= '<li>' . t('Nodes.') . '</li>';
$output .= '<li>' . t('Taxonomy Terms') . '</li>';
$output .= '</ul>';
$output .= '<p>' . t('Additional features:') . '</p>';
$output .= '<ul>';
$output .= '<li>' . t('<i>Translations</i> block that looks like the language switcher provided by i18n module but also links to translations when available.') . '</li>';
$output .= '<li>' . t('Basic translation workflow and administration page for content translation.') . '</li>';
$output .= '<li>' . t('Links for node translations that can be displayed below each node, depending on module settings.') . '</li>';
$output .= '</ul>';
$output .= '<p>' . t('For more information please read the <a href="@i18n">on-line help pages</a>.', array(
'@i18n' => 'http://drupal.org/node/31631',
)) . '</p>';
return $output;
break;
case 'admin/access#translation':
$output = t('<h2>Translations</h2>');
$output = t('<strong>translate nodes</strong> <p>This one, combined with create content permissions, will allow to create node translation</p>');
}
return $output;
}
function translation_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'translation/autocomplete',
'title' => t('translation node autocomplete'),
'callback' => 'translation_node_autocomplete',
'access' => user_access('translate nodes'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/settings/i18n/translation',
'title' => t('Translation'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'translation_admin_settings',
),
'access' => user_access('administer site configuration'),
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/content/translation',
'title' => t('Translations'),
'description' => t("Manage content translations."),
'callback' => 'translation_admin_content',
'position' => 'left',
'access' => user_access('translate nodes'),
);
$items[] = array(
'path' => 'admin/content/translation/overview',
'title' => t('List'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
}
else {
if (arg(0) == 'node' && is_numeric(arg(1)) && ($node = node_load(arg(1))) && variable_get('i18n_node_' . translation_get_node_type(arg(1)), 0)) {
$access = translation_access($node) && node_access('view', $node);
$type = MENU_LOCAL_TASK;
$items[] = array(
'path' => 'node/' . arg(1) . '/translation',
'title' => t('Translation'),
'callback' => 'translation_node_page',
'access' => $access,
'type' => $type,
'weight' => 3,
);
}
if (arg(0) == 'admin' && arg(1) == 'content' && arg(2) == 'taxonomy' && is_numeric(arg(3))) {
$items[] = array(
'path' => 'admin/content/taxonomy/' . arg(3) . '/translation',
'title' => t('Translation'),
'callback' => 'translation_taxonomy_admin',
'access' => user_access('administer taxonomy'),
'type' => MENU_LOCAL_TASK,
);
}
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())) {
if (arg(2) == 'product' && module_exists('product') && !arg(3) && is_numeric($source_nid) && ($ptype = db_result(db_query("SELECT ptype FROM {ec_product} WHERE nid = %d", $source_nid)))) {
drupal_goto(url("node/add/product/{$ptype}", "translation={$source_nid}&language={$lang}", NULL, TRUE));
}
i18n_selection_mode('translation', db_escape_string($lang));
}
}
return $items;
}
function translation_perm() {
return array(
'translate nodes',
'translate own nodes',
);
}
function translation_access($node) {
global $user;
return user_access('translate nodes') || $node->uid == $user->uid && user_access('translate own nodes');
}
function translation_admin_settings() {
$form['i18n_translation_links'] = array(
'#type' => 'radios',
'#title' => t('Language Management'),
'#default_value' => variable_get('i18n_translation_links', 0),
'#options' => array(
t('Interface language depends on content.'),
t('Interface language is independent'),
),
'#description' => t("Whether the whole page should switch language when clicking on a node translation or not."),
);
$form['i18n_translation_node_links'] = array(
'#type' => 'radios',
'#title' => t('Links to node translations'),
'#default_value' => variable_get('i18n_translation_node_links', 0),
'#options' => array(
t('None.'),
t('Main page only'),
t('Teaser and Main page'),
),
'#description' => t("Links from nodes to translated versions."),
);
$form['i18n_translation_workflow'] = array(
'#type' => 'radios',
'#title' => t('Translation workflow'),
'#default_value' => variable_get('i18n_translation_workflow', 1),
'#options' => array(
t('Disabled'),
t('Enabled'),
),
'#description' => t("If enabled some worklow will be provided for content translation."),
);
return system_settings_form($form);
}
function translation_block($op = 'list', $delta = 0) {
if ($op == 'list') {
$blocks[0]['info'] = t('Translations for Content');
}
elseif ($op == 'view') {
$blocks['subject'] = t('Languages');
$query = drupal_query_string_encode($_GET, array(
'q',
));
$blocks['content'] = theme('item_list', translation_get_links($_GET['q'], empty($query) ? NULL : $query));
}
return $blocks;
}
function translation_form_alter($form_id, &$form) {
if (isset($form['type']) && $form['type']['#value'] . '_node_form' == $form_id && variable_get('i18n_node_' . $form['type']['#value'], 0)) {
$node = $form['#node'];
$languages = i18n_node_language_list($node);
if ($node->nid && $node->translation) {
$translations = $node->translation;
}
elseif (isset($node->translation_source) && translation_access($node->translation_source)) {
$translation_nid = $node->translation_nid;
$language = $node->language;
$trans = $node->translation_source;
$form['i18n']['translation_nid'] = array(
'#type' => 'hidden',
'#value' => $translation_nid,
);
$form['i18n']['language']['#default_value'] = $language;
$form['i18n']['language']['#disabled'] = TRUE;
$form['i18n']['language']['#description'] = t('Language cannot be changed while creating a translation.');
if ($trans->trid) {
$form['i18n']['trid'] = array(
'#type' => 'hidden',
'#value' => $trans->trid,
);
}
$translations = $trans->translation;
$translations[$trans->language] = $trans;
}
if ($translations) {
foreach (array_keys($translations) as $lang) {
unset($form['i18n']['language']['#options'][$lang]);
}
$form['i18n']['#title'] = t('Language and translations');
$form['i18n']['translations'] = array(
'#type' => 'markup',
'#value' => theme('translation_node_list', $translations, FALSE),
);
}
if (variable_get('i18n_translation_workflow', 1) && (user_access('translate nodes') || user_access('administer nodes'))) {
$form['i18n']['i18n_status'] = array(
'#type' => 'select',
'#title' => t('Translation workflow'),
'#options' => _translation_status(),
'#description' => t('Use the translation workflow to keep track of content that needs translation.'),
);
if ($node->nid) {
$form['i18n']['i18n_status']['#default_value'] = isset($node->i18n_status) ? $node->i18n_status : TRANSLATION_STATUS_NONE;
}
elseif (isset($trans)) {
$form['i18n']['i18n_status']['#default_value'] = TRANSLATION_STATUS_WORKING;
}
}
else {
$form['i18n']['i18n_status'] = array(
'#type' => 'value',
'#value' => isset($node->i18n_status) ? $node->i18n_status : TRANSLATION_STATUS_NONE,
);
}
if (isset($trans) && is_array($trans->files) && count($trans->files)) {
$form['i18n']['translation_files'] = array(
'#type' => 'fieldset',
'#title' => t('Files from translated content'),
'#tree' => TRUE,
'#prefix' => '<div class="attachments">',
'#suffix' => '</div>',
'#theme' => 'upload_form_current',
'#description' => t('You can remove the files for this translation or keep the original files and translate the description.'),
);
foreach ($trans->files as $key => $file) {
$description = file_create_url(strpos($file->fid, 'upload') === false ? $file->filepath : file_create_filename($file->filename, file_create_path()));
$description = "<small>" . check_plain($description) . "</small>";
$form['i18n']['translation_files'][$key]['description'] = array(
'#type' => 'textfield',
'#default_value' => strlen($file->description) ? $file->description : $file->filename,
'#maxlength' => 256,
'#description' => $description,
);
$form['i18n']['translation_files'][$key]['size'] = array(
'#type' => 'markup',
'#value' => format_size($file->filesize),
);
$form['i18n']['translation_files'][$key]['remove'] = array(
'#type' => 'checkbox',
'#default_value' => 0,
);
$form['i18n']['translation_files'][$key]['list'] = array(
'#type' => 'checkbox',
'#default_value' => $file->list,
);
$form['i18n']['translation_files'][$key]['fid'] = array(
'#type' => 'value',
'#value' => $file->fid,
);
}
}
}
}
function translation_nodeapi(&$node, $op, $arg = 0) {
if (variable_get("i18n_node_{$node->type}", 0)) {
switch ($op) {
case 'load':
return array(
'translation' => translation_node_get_translations(array(
'nid' => $node->nid,
), FALSE),
);
break;
case 'insert':
if ($node->translation_nid) {
if (!$node->trid) {
$node->trid = db_next_id('{i18n_node}_trid');
db_query("UPDATE {i18n_node} SET trid = %d WHERE nid=%d OR nid=%d", $node->trid, $node->nid, $node->translation_nid);
}
if (isset($node->translation_files)) {
foreach ($node->translation_files as $fid => $file) {
if (!$file['remove']) {
db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $file['fid'], $node->vid, $file['list'], $file['description']);
}
}
}
}
break;
case 'prepare':
if (empty($node->nid) && isset($_GET['translation']) && is_numeric($_GET['translation']) && !empty($_GET['language'])) {
translation_node_prepare($node, $_GET['translation'], $_GET['language']);
}
break;
}
if (module_exists('nat')) {
translation_nodeapi_nat($node, $op);
}
}
}
function translation_nodeapi_nat(&$node, $op) {
$nat_config = variable_get('nat_config', array());
if (($op == 'insert' || $op == 'update') && isset($nat_config['types'][$node->type]) && !empty($nat_config['types'][$node->type]) && ($nat_terms = translation_nat_get_terms($node->nid))) {
$translations = $term_trids = array();
foreach ($nat_terms as $term) {
db_query("UPDATE {term_data} SET language = '%s' WHERE tid = %d", $node->language, $term->tid);
$translations[$term->vid][$node->language] = $term;
if ($term->trid) {
$term_trids[$term->vid] = $term->trid;
}
}
if ($node->trid) {
$node_translations = $node->trid ? translation_node_get_translations(array(
'nid' => $node->nid,
)) : array();
foreach ($node_translations as $trnode) {
foreach (nat_get_terms($trnode->nid) as $term) {
if (!$term->language) {
$term->language = $trnode->language;
db_query("UPDATE {term_data} SET language = '%s' WHERE tid = %d", $term->language, $term->tid);
}
$translations[$term->vid][$term->language] = $term;
if ($term->trid) {
$term_trids[$term->vid] = $term->trid;
}
}
}
foreach ($nat_terms as $term) {
if (count($translations[$term->vid]) > 1) {
$translation_set = $translations[$term->vid];
$trid = isset($term_trids[$term->vid]) ? $term_trids[$term->vid] : 0;
translation_taxonomy_save($translation_set, $trid);
}
}
}
}
}
function translation_nat_get_terms($nid) {
$return = array();
$result = db_query("SELECT td.* FROM {nat} n INNER JOIN {term_data} td USING (tid) WHERE n.nid = %d", $nid);
while ($term = db_fetch_object($result)) {
$return[$term->tid] = $term;
}
return $return;
}
function translation_node_prepare(&$node, $sourcenid, $language) {
$source = node_load($sourcenid);
if (empty($source) || !translation_access($source) || !node_access('view', $source)) {
return;
}
$language_list = i18n_node_language_list($node);
if (!isset($language_list[$language]) || $source->language == $language) {
return;
}
$node->translation_source = drupal_clone($source);
$node->translation_nid = $sourcenid;
$node->language = $language;
if (is_array($source->taxonomy)) {
$node->taxonomy = array();
foreach ($source->taxonomy as $tid => $term) {
if ($term->language) {
$translated_terms = translation_term_get_translations(array(
'tid' => $tid,
));
if ($translated_terms && ($newterm = $translated_terms[$node->language])) {
$node->taxonomy[$newterm->tid] = $newterm;
}
}
else {
$node->taxonomy[$tid] = $term;
}
}
}
if ($source->parent && ($translations = translation_node_get_translations(array(
'nid' => $source->parent,
))) && isset($translations[$language])) {
$node->parent = $translations[$language]->nid;
}
$node->translation = $source->translation;
$node->translation[$source->language] = $source;
if (filter_access($source->format)) {
$node->body = $source->body;
}
unset($source->nid, $source->vid, $source->path, $source->language, $source->files, $source->body);
foreach ($source as $field => $value) {
if (!isset($node->{$field})) {
$node->{$field} = $value;
}
}
}
function translation_node_page() {
$args = func_get_args();
$op = $args[0];
$nid = arg(1);
$node = node_load($nid);
if (!$node->language) {
form_set_error('language', t("You need to set a language before creating a translation."));
drupal_goto("node/{$nid}/edit");
}
drupal_set_title(check_plain($node->title));
$output = '';
switch ($op) {
case 'select':
$output .= translation_node_overview($node);
$output .= translation_node_select($node, $args[1]);
break;
default:
$output .= translation_node_overview($node);
}
return $output;
}
function translation_node_form($node, $lang, $list) {
$form['node'] = array(
'#type' => 'value',
'#value' => $node,
);
$form['language'] = array(
'#type' => 'hidden',
'#value' => $lang,
);
$form['source_nid'] = array(
'#type' => 'hidden',
'#value' => $node->nid,
);
$form['trid'] = array(
'#type' => 'hidden',
'#value' => $node->trid,
);
$languages = i18n_node_language_list($node);
$form['select'] = array(
'#type' => 'fieldset',
'#title' => t('Select translation for %language', array(
'%language' => $languages[$lang],
)),
);
$form['select']['lookup'] = array(
'#type' => 'textfield',
'#title' => t('Search for node'),
'#description' => t('Enter node id or title'),
'#size' => 80,
'#maxlength' => 254,
'#autocomplete_path' => 'translation/autocomplete/' . $lang,
);
$form['select']['nodes']['nid'] = array(
'#type' => 'radios',
'#title' => t('Or select from the list'),
'#default_value' => isset($node->translation[$lang]) ? $node->translation[$lang]->nid : '',
'#options' => $list,
);
$form['select']['pager'] = array(
'#value' => theme('pager'),
);
$form['select']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
function translation_node_autocomplete($lang = NULL, $string = NULL) {
$languages = i18n_supported_languages();
if ($lang && $string && in_array($lang, array_keys($languages))) {
$matches = array();
$result = db_query(db_rewrite_sql("SELECT n.nid, n.title FROM {node} n INNER JOIN {i18n_node} i ON n.nid = i.nid WHERE (LOWER(n.title) LIKE LOWER('%s%%') OR n.nid = %d) AND i.language = '%s'"), $string, $string, $lang);
while ($nodelist = db_fetch_object($result)) {
$title = check_plain($nodelist->title);
$matches["{$nodelist->nid} - {$title}"] = "{$title} [nid={$nodelist->nid}]";
}
print drupal_to_js($matches);
}
exit;
}
function translation_admin_content() {
$output = '';
$defaults = array(
'translation_language' => i18n_get_lang(),
'source_status' => TRANSLATION_STATUS_SOURCE,
);
$output .= drupal_get_form('node_filter_form');
$output .= drupal_get_form('translation_filter_form', $defaults);
$output .= drupal_get_form('translation_admin_nodes');
return $output;
}
function translation_admin_nodes() {
$filter = translation_build_filter_query();
$where = $filter['where'];
$params = $filter['args'];
$join = $filter['join'];
$filter = node_build_filter_query();
if (!empty($filter['where'])) {
$where += array_merge($where, array(
str_replace('WHERE', '', $filter['where']),
));
}
if (!empty($filter['args'])) {
$params = array_merge($params, $filter['args']);
}
if (!empty($filter['join'])) {
$join .= ' ' . $filter['join'];
}
$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 " . "FROM {node} n INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {i18n_node} i ON n.nid = i.nid " . "LEFT JOIN {i18n_node} i2 ON i.trid = i2.trid AND 0 <> i2.trid AND i.language <> i2.language {$join}" . (count($where) ? ' WHERE ' . implode(' AND ', $where) : '');
i18n_selection_mode('off');
$result = pager_query(db_rewrite_sql($sql), 50, 0, NULL, $params);
i18n_selection_mode('reset');
$languages = i18n_supported_languages();
$translation_status = _translation_status();
$language = isset($_SESSION['translation_filter']['translation_language']) ? $_SESSION['translation_filter']['translation_language'] : i18n_get_lang();
$destination = drupal_get_destination();
while ($node = db_fetch_object($result)) {
$nodes[$node->nid] = '';
$form['language'][$node->nid] = array(
'#value' => $languages[$node->language],
);
$form['title'][$node->nid] = array(
'#value' => l($node->title, 'node/' . $node->nid) . ' ' . theme('mark', node_mark($node->nid, $node->changed)),
);
$form['name'][$node->nid] = array(
'#value' => node_get_types('name', $node),
);
$form['username'][$node->nid] = array(
'#value' => theme('username', $node),
);
$form['status'][$node->nid] = array(
'#value' => $node->status ? t('published') : t('not published'),
);
if ($node->translation_nid) {
$form['translation_status'][$node->nid] = array(
'#value' => $translation_status[$node->translation_status],
);
$form['operations'][$node->nid] = array(
'#value' => l(t('edit translation'), 'node/' . $node->translation_nid . '/edit', array(), $destination),
);
}
else {
$form['translation_status'][$node->nid] = array(
'#value' => '--',
);
if ($language == $node->language) {
$form['operations'][$node->nid] = array(
'#value' => '--',
);
}
else {
$prefix = variable_get('i18n_translation_links', 0) ? i18n_get_lang() : $language;
$form['operations'][$node->nid] = array(
'#value' => l(t('create translation'), $prefix . '/node/add/' . $node->type, array(), "translation={$node->nid}&language={$language}") . ' | ' . l(t('select node'), "node/{$node->nid}/translation/select/{$language}", array(), $destination),
);
}
}
}
$form['pager'] = array(
'#value' => theme('pager', NULL, 50, 0),
);
return $form;
}
function translation_build_filter_query() {
$where = $args = array();
$join = '';
if (!is_array($_SESSION['translation_filter'])) {
$_SESSION['translation_filter'] = array();
}
foreach ($_SESSION['translation_filter'] as $type => $value) {
switch ($type) {
case 'source_language':
$where[] = "i.language = '%s'";
$args[] = $value;
break;
case 'translation_language':
$join .= " AND i2.language ='" . db_escape_string($value) . "' ";
break;
case 'source_status':
$where[] = "i.status = %d";
$args[] = $value;
break;
case 'translation_status':
$join .= " AND i2.status = " . db_escape_string($value);
break;
}
}
return array(
'where' => $where,
'join' => $join,
'args' => $args,
);
}
function translation_filter_form($defaults = array()) {
$session =& $_SESSION['translation_filter'];
$session = is_array($session) ? $session : $defaults;
$form['_defaults'] = array(
'#type' => 'value',
'#value' => $defaults,
);
$form['filters'] = array(
'#type' => 'fieldset',
'#title' => t('And translation conditions are'),
'#theme' => 'translation_filter_form_layout',
);
$languages = i18n_supported_languages();
$form['filters']['source_language'] = array(
'#type' => 'select',
'#title' => t('source language'),
'#options' => array(
'' => '',
) + $languages,
'#default_value' => $session['source_language'],
);
$form['filters']['source_status'] = array(
'#type' => 'select',
'#title' => t('source status'),
'#options' => array(
'' => '',
) + _translation_status(),
'#default_value' => $session['source_status'],
);
$form['filters']['translation_language'] = array(
'#type' => 'select',
'#title' => t('translation language'),
'#options' => array(
'' => '',
) + $languages,
'#default_value' => $session['translation_language'],
);
$form['filters']['translation_status'] = array(
'#type' => 'select',
'#title' => t('translation status'),
'#options' => array(
'' => '',
) + _translation_status(),
'#default_value' => $session['translation_status'],
);
$form['filters']['buttons']['submit'] = array(
'#type' => 'submit',
'#value' => t('Filter'),
);
if (!empty($session)) {
$form['filters']['buttons']['reset'] = array(
'#type' => 'submit',
'#value' => t('Reset'),
);
}
return $form;
}
function theme_translation_filter_form_layout($form) {
$output = '<table><tr>';
$output .= '<td>' . drupal_render($form['source_language']) . '</td>';
$output .= '<td>' . drupal_render($form['translation_language']) . '</td>';
$output .= '</tr><tr>';
$output .= '<td>' . drupal_render($form['source_status']) . '</td>';
$output .= '<td>' . drupal_render($form['translation_status']) . '</td>';
$output .= '</tr><table>';
$output .= drupal_render($form);
return $output;
}
function translation_filter_form_submit($form_id, $form_values) {
$op = $_POST['op'];
$session =& $_SESSION['translation_filter'];
switch ($op) {
case t('Filter'):
$session = array();
foreach ($form_values as $name => $value) {
if ($value) {
$session[$name] = $value;
}
}
break;
case t('Reset'):
$session = $form_values['_defaults'];
break;
}
}
function theme_translation_admin_nodes($form) {
$header = array(
t('Language'),
t('Title'),
t('Type'),
t('Author'),
t('Status'),
t('Translation status'),
t('Operations'),
);
$output .= drupal_render($form['options']);
if (isset($form['title']) && is_array($form['title'])) {
foreach (element_children($form['title']) as $key) {
$row = array();
$row[] = drupal_render($form['language'][$key]);
$row[] = drupal_render($form['title'][$key]);
$row[] = drupal_render($form['name'][$key]);
$row[] = drupal_render($form['username'][$key]);
$row[] = drupal_render($form['status'][$key]);
$row[] = drupal_render($form['translation_status'][$key]);
$row[] = drupal_render($form['operations'][$key]);
$rows[] = $row;
}
}
else {
$rows[] = array(
array(
'data' => t('No posts available.'),
'colspan' => '6',
),
);
}
$output .= theme('table', $header, $rows);
if ($form['pager']['#value']) {
$output .= drupal_render($form['pager']);
}
$output .= drupal_render($form);
return $output;
}
function translation_node_overview($node) {
$languages = i18n_node_language_list($node);
unset($languages[$node->language]);
$header = array(
t('Language'),
t('Title'),
t('Status'),
t('Options'),
);
$createlink = $node->type == 'product' ? "node/add/{$node->type}/{$node->ptype}" : "node/add/{$node->type}";
foreach ($languages as $lang => $langname) {
$options = array();
if (isset($node->translation[$lang])) {
$trnode = $node->translation[$lang];
$title = l($trnode->title, 'node/' . $trnode->nid);
$status = $trnode->status ? t('Published') : t('Not published');
}
else {
$title = t('Not translated');
$prefix = variable_get('i18n_translation_links', 0) ? i18n_get_lang() : $lang;
$options[] = l(t('create translation'), $prefix . '/' . $createlink, array(), "translation={$node->nid}&language={$lang}");
$status = '--';
}
$options[] = l(t('select node'), "node/{$node->nid}/translation/select/{$lang}");
$rows[] = array(
$langname,
$title,
$status,
implode(" | ", $options),
);
}
$output .= theme('table', $header, $rows);
if ($node->trid) {
$output .= drupal_get_form('translation_node_remove', $node);
}
return theme('box', t('Current translations'), $output);
}
function translation_node_remove($node) {
$form['remove'] = array(
'#type' => 'fieldset',
'#title' => t('Remove from translation'),
'#description' => t('This will just unlink the node from this translation set.'),
);
$form['remove']['node'] = array(
'#type' => 'value',
'#value' => $node,
);
$form['remove']['submit'] = array(
'#type' => 'submit',
'#value' => t('Remove'),
);
return $form;
}
function translation_node_remove_submit($form_id, $form_values) {
$node = $form_values['node'];
db_query("UPDATE {i18n_node} SET trid = 0 WHERE nid = %d", $node->nid);
drupal_set_message(t("The node has been removed from the translation set"));
drupal_goto("node/{$node->nid}/translation");
}
function translation_node_select($node, $lang) {
$languages = i18n_supported_languages();
i18n_selection_mode('off');
$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);
i18n_selection_mode('reset');
while ($trnode = db_fetch_object($result)) {
$list[$trnode->nid] = l($trnode->title, "node/{$trnode->nid}");
}
if ($list) {
return drupal_get_form('translation_node_form', $node, $lang, $list);
}
else {
return t("<p>No nodes available in %language</p>", array(
'%language' => $languages[$lang],
));
}
}
function translation_node_form_submit($form_id, $form_values) {
$op = $_POST['op'];
$source_nid = $form_values['source_nid'];
$language = $form_values['language'];
if ($form_values['nid']) {
$nid = $form_values['nid'];
}
if ($form_values['lookup'] && ($number = intval($form_values['lookup']))) {
$nid = $number;
}
if ($source_nid && $language && $nid && ($node = node_load($nid)) && $node->language == $language) {
if ($trid = $form_values['trid']) {
db_query("UPDATE {i18n_node} SET trid = 0 WHERE trid = %d AND language = '%s'", $trid, $language);
}
else {
$trid = db_next_id('{i18n_node}_trid');
}
db_query("UPDATE {i18n_node} SET trid = %d WHERE nid=%d OR nid=%d", $trid, $source_nid, $nid);
drupal_set_message(t('The translation has been saved'));
}
}
function translation_taxonomy($op, $type = NULL, $edit = NULL) {
switch ("{$type}/{$op}") {
case 'term/insert':
case 'term/update':
if (!$edit['language'] && $edit['trid']) {
db_query('UPDATE {term_data} SET trid = 0 WHERE tid = %d', $edit['tid']);
if (db_affected_rows()) {
drupal_set_message(t('Removed translation information from term'));
}
}
break;
}
}
function translation_link($type, $node = NULL, $teaser = FALSE) {
$languages = i18n_supported_languages();
$links = array();
if ($type == 'node' && variable_get('i18n_translation_node_links', 0) > ($teaser ? 1 : 0) && $node->translation) {
foreach ($node->translation as $lang => $trnode) {
if ($trnode->status) {
$baselang = variable_get('i18n_translation_links', 0) || !isset($languages[$lang]) ? i18n_get_lang() : $lang;
$links['translation-' . $lang] = theme('translation_node_link', $trnode, $lang, $baselang);
}
}
}
return $links;
}
function translation_vocabulary_get_terms($vid, $lang, $status = 'all') {
switch ($status) {
case 'translated':
$andsql = ' AND trid > 0';
break;
case 'untranslated':
$andsql = ' AND trid = 0';
break;
default:
$andsql = '';
}
$result = db_query("SELECT * FROM {term_data} WHERE vid=%d AND language='%s' {$andsql}", $vid, $lang);
$list = array();
while ($term = db_fetch_object($result)) {
$list[$term->tid] = $term->name;
}
return $list;
}
function translation_node_get_translations($params, $getall = TRUE) {
foreach ($params as $field => $value) {
$conds[] = "b.{$field} = '%s'";
$values[] = $value;
}
if (!$getall) {
$conds[] = "n.nid <> %d";
$values[] = $params['nid'];
}
$conds[] = "b.trid <> 0";
$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);
i18n_selection_mode('off');
$result = db_query(db_rewrite_sql($sql), $values);
i18n_selection_mode('reset');
$items = array();
while ($node = db_fetch_object($result)) {
$items[$node->language] = $node;
}
return $items;
}
function translation_get_node_type($nid) {
return db_result(db_query('SELECT type FROM {node} WHERE nid=%d', $nid));
}
function translation_taxonomy_admin($op = NULL, $trid = NULL) {
$vid = arg(3);
$op = arg(5);
$trid = arg(6);
$output = '';
switch ($op) {
case 'edit':
case 'new':
drupal_set_title(t('Edit term translations'));
$output .= drupal_get_form('translation_taxonomy_term_form', $vid, $trid);
break;
default:
$output .= translation_taxonomy_overview($vid);
}
return $output;
}
function translation_taxonomy_overview($vid) {
$vocabulary = taxonomy_get_vocabulary($vid);
drupal_set_title(check_plain($vocabulary->name));
$languages = i18n_supported_languages();
$header = array_merge($languages, array(
t('Operations'),
));
$links = array();
$types = array();
$result = db_query('SELECT * FROM {term_data} t WHERE vid=%d', $vocabulary->vid);
$terms = array();
while ($term = db_fetch_object($result)) {
if ($term->trid && $term->language) {
$terms[$term->trid][$term->language] = $term;
}
}
foreach ($terms as $trid => $terms) {
$thisrow = array();
foreach ($languages as $lang => $name) {
if (array_key_exists($lang, $terms)) {
$thisrow[] = l($terms[$lang]->name, 'taxonomy/term/' . $terms[$lang]->tid);
}
else {
$thisrow[] = '--';
}
}
$thisrow[] = l(t('edit'), "admin/content/taxonomy/{$vid}/translation/edit/{$trid}");
$rows[] = $thisrow;
}
$output .= theme('table', $header, $rows);
$output .= l(t('new translation'), "admin/content/taxonomy/{$vid}/translation/new");
return $output;
}
function translation_taxonomy_term_form($vid, $trid = NULL) {
$languages = i18n_supported_languages();
if (!$trid) {
$translations = array();
}
else {
$form['trid'] = array(
'#type' => 'hidden',
'#value' => $trid,
);
$translations = translation_term_get_translations(array(
'trid' => $trid,
));
}
$vocabulary = taxonomy_get_vocabulary($vid);
foreach ($languages as $lang => $langname) {
$current = isset($translations[$lang]) ? $translations[$lang]->tid : '';
$list = translation_vocabulary_get_terms($vid, $lang, 'all');
$list[''] = '--';
$form[$lang] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
);
$form[$lang]['tid'] = array(
'#type' => 'select',
'#title' => $langname,
'#default_value' => $current,
'#options' => $list,
);
$form[$lang]['old'] = array(
'#type' => 'hidden',
'#value' => $current,
);
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
$form['#redirect'] = 'admin/content/taxonomy/' . $vid . '/translation';
return $form;
}
function translation_taxonomy_term_form_submit($form_id, $form_values) {
translation_taxonomy_save($form_values, $form_values['trid']);
drupal_set_message(t('Term translations have been updated'));
}
function translation_taxonomy_save($terms, $trid = 0) {
if ($trid) {
db_query("UPDATE {term_data} SET trid = 0 WHERE trid= %d", $trid);
}
$translations = array();
foreach (i18n_supported_languages() as $lang => $name) {
if (isset($terms[$lang]) && ($term = (array) $terms[$lang]) && ($tid = $term['tid'])) {
$translations[$lang] = $tid;
}
}
if (count($translations)) {
$trid = is_numeric($trid) && $trid ? $trid : db_next_id('{term_data}_trid');
db_query('UPDATE {term_data} SET trid = %d WHERE tid IN(%s)', $trid, implode(',', $translations));
}
}
function translation_array2list($data, $keyfield, $namefield = 'name') {
foreach ($data as $key => $value) {
if (is_array($data)) {
$list[$value[$keyfield]] = $value[$namefield];
}
else {
$list[$value->{$keyfield}] = $value->{$namefield};
}
}
return $list;
}
function translation_term_get_translations($params, $getall = TRUE) {
foreach ($params as $field => $value) {
$conds[] = "i.{$field} = '%s'";
$values[] = $value;
}
if (!$getall) {
$conds[] = "t.tid <> %d";
$values[] = $params['tid'];
}
$conds[] = "t.trid <> 0";
$sql = 'SELECT t.* FROM {term_data} t INNER JOIN {term_data} i ON t.trid = i.trid WHERE ' . implode(' AND ', $conds);
$result = db_query($sql, $values);
$items = array();
while ($data = db_fetch_object($result)) {
$items[$data->language] = $data;
}
return $items;
}
function translation_url($url, $lang) {
global $i18n_langpath;
if (!$url) {
$url = _i18n_get_original_path();
}
i18n_get_lang_prefix($url, true);
if (preg_match("/^(node\\/)([0-9]*)(.*)\$/", $url, $matches)) {
if ($nid = translation_node_nid($matches[2], $lang)) {
$url = "node/{$nid}" . $matches[3];
}
}
elseif (preg_match("/^(taxonomy\\/term\\/)([^\\/]*)(.*)\$/", $url, $matches)) {
if ($str_tids = translation_taxonomy_tids($matches[2], $lang)) {
$url = "taxonomy/term/{$str_tids}" . $matches[3];
}
}
return $url;
}
function translation_node_nid($nid, $language = NULL, $default = NULL) {
$translation = db_result(db_query("SELECT n.nid FROM {i18n_node} n INNER JOIN {i18n_node} a ON n.trid = a.trid AND n.nid <> a.nid WHERE a.nid = %d AND n.language = '%s' AND n.trid is not null AND n.trid <> 0", $nid, $language ? $language : i18n_get_lang()));
return $translation ? $translation : $default;
}
function translation_term_tid($tid, $language = NULL, $default = NULL) {
$translation = db_result(db_query("SELECT t.tid FROM {term_data} t INNER JOIN {term_data} a ON t.trid = a.trid AND t.tid <> a.tid WHERE a.tid = %d AND t.language = '%s' AND t.trid is not null AND t.trid <> 0", $tid, $language ? $language : i18n_get_lang()));
return $translation ? $translation : $default;
}
function translation_taxonomy_tids($str_tids, $lang) {
if (preg_match('/^([0-9]+[+ ])+[0-9]+$/', $str_tids)) {
$separator = '+';
$tids = preg_split('/[+ ]/', $str_tids);
}
else {
if (preg_match('/^([0-9]+,)*[0-9]+$/', $str_tids)) {
$separator = ',';
$tids = explode(',', $str_tids);
}
else {
return;
}
}
$translated_tids = array();
foreach ($tids as $tid) {
if ($translated_tid = translation_term_tid($tid, $lang)) {
$translated_tids[] = $translated_tid;
}
}
return implode($separator, $translated_tids);
}
function translation_get_links($path = '', $query = NULL, $names = NULL) {
$current = i18n_get_lang();
$names = $names ? $names : i18n_languages('native');
foreach (array_keys(i18n_supported_languages()) as $lang) {
$url = translation_url($path, $lang);
$links[] = theme('i18n_link', $names[$lang], i18n_path($url, $lang), $lang, $query);
}
return $links;
}
function _translation_status() {
return array(
TRANSLATION_STATUS_NONE => t('None'),
TRANSLATION_STATUS_SOURCE => t('Source content (to be translated)'),
TRANSLATION_STATUS_WORKING => t('Translation in progress'),
TRANSLATION_STATUS_TRANSLATED => t('Translated content'),
TRANSLATION_STATUS_UPDATED => t('Source updated (to update translation)'),
);
}
function theme_translation_node_link($node, $lang, $baselang = NULL, $title = FALSE) {
$baselang = $baselang ? $baselang : $lang;
if ($title) {
$name = $node->title;
}
else {
$languages = i18n_languages('native');
$name = $languages[$lang];
}
return array(
'title' => $name,
'href' => i18n_path('node/' . $node->nid, $baselang),
);
}
function theme_translation_link($text, $target, $lang, $separator = ' ') {
return theme('i18n_link', $text, $target, $lang, $separator);
}
function theme_translation_node_list($list) {
$header = array(
t('Language'),
t('Title'),
);
$languages = i18n_languages('name');
foreach ($list as $lang => $node) {
$rows[] = array(
$languages[$lang],
l($node->title, 'node/' . $node->nid),
);
}
return theme('table', $header, $rows);
}