summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJose Reyero2007-10-22 12:21:26 (GMT)
committer Jose Reyero2007-10-22 12:21:26 (GMT)
commitafcc0a2566c86e96d3b6008347ea2a88dc34b320 (patch)
tree6a6c0256686995f55c36e7d9821353934372e4fd
parentffe1b4698a965a953d9326109863bba34e4a5e70 (diff)
Upgrading for Drupal 6
-rw-r--r--INSTALL.txt34
-rw-r--r--README.txt49
-rw-r--r--i18n.info3
-rw-r--r--i18n.install67
-rw-r--r--i18n.module978
-rw-r--r--translation/translation.info4
-rw-r--r--translation/translation.module1055
7 files changed, 460 insertions, 1730 deletions
diff --git a/INSTALL.txt b/INSTALL.txt
index 3d3c11f..83dfeb6 100644
--- a/INSTALL.txt
+++ b/INSTALL.txt
@@ -3,10 +3,9 @@
********************************************************************
Name: i18n module and translation module
Author: Jose A. Reyero
-Email: drupal at reyero dot net
********************************************************************
- This is the 5.x version of i18n module, and works with Drupal 5.x
+ This is the 6.x version of i18n module, and works with Drupal 6.x
********************************************************************
********************************************************************
@@ -29,41 +28,10 @@ POST-INSTALLATION/CONFIGURATION:
- Configure the modules in
Administer > Site Configuration > Multilingual system
- You might get an error message about languages not being enabled yet.
- Visit the suggested page (Manage Languages) and enable the languages you need.
- In case you find out they're already enabled, just press the button "save configuration".
-
-- Enable multilingual support for each content type you want to translate
- administer > content management > content types > edit (for each type separately)
-
- A new field 'language' and a new tab 'translations' will be available when editing these node types
-
-- There are now two language blocks
- - A simple language switcher provided by i18n.module
- - A translation block provided by translation.module
-
- Set up language for existing nodes, editing them manually.
- Set up language for existing taxonomy terms
Only terms in the node's language or terms without language will show up when editing a node
-Language Definition [NEW for Drupal 5]
-===================
-RECOMMENDED: You can use the languages defined -and enabled- in 'locale' module
-
-ADVANCED, EXPERTS ONLY:
-Modify the Drupal configuration file '../settings.php' to define the languages you want to use.
- For instance, for English, Spanish:
-
- $conf['i18n_languages'] = array(
- 'site_default' => 'en', // Default language
- 'name' => array('es' => "Spanish", 'en' => 'English'), // English names for languages
- 'native' => array('es' => "Español", 'en' => 'English'), // Native names
- 'enabled' => array('es' => TRUE, 'en' => TRUE), // Languages enabled
- // 'rtl' => array('es' => TRUE), // This only if Spanish were an RTL language, which is not
- );
-
-* This will override languages defined by locale module
-
Language dependent variables
============================
The list of variables to be made language dependent must be defined in the config file:
diff --git a/README.txt b/README.txt
index 503587f..a2289ce 100644
--- a/README.txt
+++ b/README.txt
@@ -2,59 +2,32 @@ README.txt
==========
********************************************************************
-This is i18n package, development version , and works with Drupal 5.x
+This is i18n package, development version , and works with Drupal 6.x
********************************************************************
WARNING: DO READ THE INSTALL FILE
********************************************************************
Updated documentation will be kept on-line at http://drupal.org/node/67817
********************************************************************
-This is not a single module anymore but a collection of modules providing complementary features
- i18n --> basic module which will add language to nodes, vocabularies and terms
- translation --> module to add translation relationships
-
-********************************************************************
-These modules provide support for multilingual Drupal sites:
- * Multilingual content, some basic translation interface, and links between translated versions
- * Translation of the user interface for registered and anonymous users (with locale)
- * Detection of the brower language
- * Keeps the language settings accross consecutive requests using URL rewriting.
- * Provides a block for language switching -i18n.module- and one for translations -translation.module-
-Multilingual content:
-=====================
-Multilingual content means providing content translated to different languages or language specific content, which is not the same as interface translation. Interface translation is done through Drupal's localization system.
-This module supports:
- - Multilingual nodes
- - Multilingual taxonomy vocabularies and terms
- - Translations for nodes and terms
+This is a collection of modules providing multilingual features.
+These modules will build onto Drupal 6 core features enabling a full multilingual site
-When you navigate the site using multiple languages, the pages will just show terms and nodes for the chosen language plus the ones that haven't a definde language.
-When editing a node, you must click on 'Preview' after changing language for the right vocabularies and terms to be shown.
+i18n: core i18n functionality
+=============================
+- Multilingual variables
+- Extended language API for other modules
-The multi language support is expected to work for all node types, and node listings
+languageicons: language icons for translation links
+=============
+This module will be spin-off from the main package
-Taxonomy translation:
+i18ntaxonomy: Taxonomy translation:
====================
You can create vocabularies and terms with or without language.
- If you set language for a vocabulary/term, that term will just show up for pages in that language
- If you set language for a vocabulary, all the terms in that vocabulary will be assigned that language.
- When editing nodes, if you change the language for a node, you have to click on 'Preview' to have the right vocabularies/terms for that language. Otherwise, the language/taxonomy data for that node could be inconsistent.
-About URL aliasing with language codes -requires path module
-============================================================
-Incoming URL's are now translated following these steps:
-1. First, a translation is searched for path with language code: 'en/mypage'
-2. If not found, language code is removed, and path translation is searched again: 'mypage'
-
-Thus, you can define aliases with or without language codes in them.
-
-This language code will be taken from browser if enabled 'Browser language detection, or will be the default otherwise.
-
-To have aliases for a translated node/page, you have to define each of them. I.e.:
- en/mycustompath -> node/34 (which is suppossed to be the english version)
- es/mycustompath -> node/35 (which should be the spanish version)
-
-For outgoing URL's, the language code will be added automatically.
About language dependent variables:
==================================
diff --git a/i18n.info b/i18n.info
index f2ea38e..a41cb17 100644
--- a/i18n.info
+++ b/i18n.info
@@ -2,4 +2,5 @@ name = Internationalization
description = Enables multilingual content.
dependencies = locale
package = Multilanguage - i18n
-
+version = VERSION
+core = 6.x \ No newline at end of file
diff --git a/i18n.install b/i18n.install
index 0ad080d..33d6603 100644
--- a/i18n.install
+++ b/i18n.install
@@ -9,30 +9,25 @@ function i18n_install() {
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
+ /**
db_query("CREATE TABLE {i18n_node} (
nid int(11) unsigned NOT NULL ,
trid int(10) unsigned NOT NULL default '0',
language VARCHAR(12) NOT NULL default '',
status smallint(6) NOT NULL default '0',
PRIMARY KEY (nid)
- )");
- db_query("ALTER TABLE {term_data}
- ADD language varchar(12) NOT NULL default '',
- ADD trid int(10) unsigned NOT NULL default '0'
- ");
- db_query("ALTER TABLE {vocabulary}
- ADD language varchar(12) NOT NULL default ''
- ");
+ ) ");
+ */
db_query("CREATE TABLE {i18n_variable} (
name varchar(48) NOT NULL default '',
language varchar(12) NOT NULL default '',
value longtext NOT NULL,
PRIMARY KEY (name, language)
- )");
-
+ ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
break;
case 'pgsql':
+ /*
db_query("CREATE TABLE {i18n_node} (
nid integer NOT NULL default '0',
trid integer NOT NULL default '0',
@@ -40,31 +35,16 @@ function i18n_install() {
status smallint NOT NULL default '0',
PRIMARY KEY (nid)
)");
+ */
db_query("CREATE TABLE {i18n_variable} (
name varchar(48) NOT NULL default '',
language varchar(12) NOT NULL default '',
value text NOT NULL,
PRIMARY KEY (name, language)
)");
- db_query("ALTER TABLE {term_data} ADD language varchar(12)");
- db_query("UPDATE {term_data} SET language=''");
- db_query("ALTER TABLE {term_data} ALTER COLUMN language SET NOT NULL");
- db_query("ALTER TABLE {term_data} ALTER COLUMN language SET DEFAULT ''");
-
- db_query("ALTER TABLE {term_data} ADD trid integer");
- db_query("UPDATE {term_data} SET trid='0'");
- db_query("ALTER TABLE {term_data} ALTER COLUMN trid SET NOT NULL");
- db_query("ALTER TABLE {term_data} ALTER COLUMN trid SET DEFAULT '0'");
-
- db_query("ALTER TABLE {vocabulary} ADD language varchar(12)");
- db_query("UPDATE {vocabulary} SET language=''");
- db_query("ALTER TABLE {vocabulary} ALTER COLUMN language SET NOT NULL");
- db_query("ALTER TABLE {vocabulary} ALTER COLUMN language SET DEFAULT ''");
-
- // Sequences
- db_query("CREATE SEQUENCE {i18n_node}_trid_seq INCREMENT 1 START 1");
- db_query("CREATE SEQUENCE {term_data}_trid_seq INCREMENT 1 START 1");
- }
+ }
+ // Set module weight for it to run after core modules
+ db_query("UPDATE {system} SET weight = -10 WHERE name = 'i18n' AND type = 'module'");
}
/**
@@ -101,4 +81,31 @@ function i18n_update_4(){
)");
return $items;
}
-?> \ No newline at end of file
+
+/**
+ * Drupal 5 updates
+ */
+// Multilingual menu items
+function i18n_update_5(){
+ $items[] = update_sql("ALTER TABLE {menu} ADD language VARCHAR(12) NOT NULL default ''");
+ return $items;
+}
+// Module weithgts
+function i18n_update_6(){
+ // Old module weights. Caused some trouble with other modules.
+}
+// Redefinition of module weights
+function i18n_update_7(){
+ $items[] = update_sql("UPDATE {system} SET weight = -10 WHERE name = 'i18n' AND type = 'module'");
+ $items[] = update_sql("UPDATE {system} SET weight = 10 WHERE name = 'translation' AND type = 'module'");
+ return $items;
+}
+// Update tables to utf8
+function i18n_update_8(){
+ return _system_update_utf8(array('i18n_variable'));
+}
+
+/**
+ * Drupal 6 updates
+ */
+ // Move node language and trid into node table \ No newline at end of file
diff --git a/i18n.module b/i18n.module
index 04ea0b6..05876bd 100644
--- a/i18n.module
+++ b/i18n.module
@@ -2,41 +2,32 @@
// $Id$
/**
+ * @file
* Internationalization (i18n) module
*
+ * Trimmed down
+ * - Language initialization
+ *
* @author Jose A. Reyero, 2004
*
*/
-/**
- * Module initialization
- *
- * Get language from path if exists and Initialize i18n system
- */
+// Some constants. Language support modes for content
+define('LANGUAGE_SUPPORT_NONE', 0);
+define('LANGUAGE_SUPPORT_NORMAL', 1);
+define('LANGUAGE_SUPPORT_EXTENDED', 2);
/**
- * This one expects to be called first from common.inc
+ * Implementation of hook_theme()
*/
-function i18n_get_lang($setlanguage = NULL) {
- static $i18n_language;
- //see if the language is already set.
- if ($setlanguage) {
- $i18n_language = $setlanguage;
- } elseif ($i18n_language) {
- return $i18n_language;
- } else {
- _i18n_init();
- return $i18n_language = _i18n_get_lang();
- }
+function i18n_theme() {
+ return array(
+ 'i18n_language_icon' => array(
+ 'arguments' => array('langcode' => array()),
+ ),
+ );
}
-/**
- * Minimum initialization
- */
-function _i18n_init(){
- global $i18n_langpath;
- $path = _i18n_get_original_path();
- $i18n_langpath = i18n_get_lang_prefix($path);
-}
+
/**
* Language block
@@ -58,42 +49,27 @@ function i18n_block($op = 'list', $delta = 0) {
/**
* Implementation of hook_init()
*
- * Complete initialization. Only when module enabled.
- * May do a redirect from home page for not to get wrong versions in cache
- * Warning: when in bootstrap mode, this may be called before i18n_get_lang()
+ * Will initialize language dependent variables
+ * Modify rewriting conditions when viewing specific nodes
*/
function i18n_init(){
- global $i18n_langpath;
- $lang = i18n_get_lang();
- $path = _i18n_get_original_path();
- // Init selection mode
- i18n_selection_mode(variable_get('i18n_selection_mode', 'simple'));
- // Multi tables, for backwards compatibility and experimentation
- _i18n_set_db_prefix($lang);
-
- if ($path == '') { // Main page
- // Check for update or cron scripts to disable rewriting and redirection
- if(preg_match('|/(?!index\.php)\w+\.php|', request_uri())){
- i18n_selection_mode('off');
- } elseif( variable_get('cache', 0) && $lang != i18n_default_language() ) {
- // Redirect to main page in $lang
- _i18n_goto($lang);
- } else {
- $_GET['q'] = i18n_frontpage($lang);
- }
- } elseif ($lang == $path) { // When path is only language code
- $_GET['q'] = i18n_frontpage($lang);
- }
- elseif ($i18n_langpath) {
- //search alias with and without lang and remove lang.
- $_GET['q'] = i18n_get_normal_path($path);
- }
-
// If not in bootstrap, variable init
if(!_i18n_is_bootstrap()){
//include drupal_get_path('module', 'i18n').'/i18n.inc';
i18n_variable_init();
- }
+ }
+ if (arg(0) == 'node') {
+ if(isset($_POST['language']) && $_POST['language']) {
+ $pagelang = $_POST['language'];
+ } elseif( is_numeric(arg(1)) && $node = node_load(arg(1)) ) {
+ // Node language when loading specific nodes
+ $pagelang = $node->language;
+ }
+ if(isset($pagelang)) i18n_selection_mode('node', db_escape_string($pagelang));
+ } elseif(arg(0) == 'admin' && arg(0) == 'content' && user_access('administer all languages')) {
+ // No restrictions for administration pages
+ i18n_selection_mode('off');
+ }
}
/**
@@ -106,11 +82,11 @@ function i18n_help($section = 'admin/help#i18n' ) {
$output .= '<ul>';
$output .= '<li>'.t('Translation of the user interface for anonymous users (combined with locale)').'</li>';
$output .= '<li>'.t('Multi-language for content. Adds a language field for nodes and taxonomy vocabularies and terms').'</li>';
- $output .= '<li>'.t('Basic translation management').'</li>';
$output .= '<li>'.t('Browser language detection').'</li>';
$output .= '<li>'.t('Keeps the language setting accross consecutive requests using URL rewriting').'</li>';
$output .= '<li>'.t('Provides a block for language selection and two theme functions: <i>i18n_flags</i> and <i>i18n_links</i>').'</li>';
$output .= '<li>'.t('Support for long locale names').'</li>';
+ $output .= '<li>'.t('Multilingual menu items').'</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;
@@ -122,43 +98,21 @@ function i18n_help($section = 'admin/help#i18n' ) {
/**
* Implementation of hook_menu().
- * Modify rewriting conditions when viewing specific nodes
*/
-function i18n_menu($may_cache) {
- $items = array();
- if ($may_cache) {
- $items[] = array(
- 'path' => 'admin/settings/i18n',
- 'title' => t('Multilingual system'),
- 'description' => t('Configure multilingual content and translation.'),
- 'callback' => 'drupal_get_form',
- 'callback arguments' => array('i18n_admin_settings'),
- 'access' => user_access('administer site configuration'),
- );
- $items[] = array(
- 'path' => 'admin/settings/i18n/main',
- 'title' => t('Internationalization'),
- 'type' => MENU_DEFAULT_LOCAL_TASK
- );
- $items[] = array('path' => 'admin/settings/i18n/language',
- 'title' => t('Manage languages'),
- 'description' => t('Configure languages.'),
- 'callback' => 'locale_admin_manage',
- 'type' => MENU_LOCAL_TASK);
- } else {
- if (arg(0) == 'node') {
- if(isset($_POST['edit']['language']) && $_POST['edit']['language']) {
- $language = $_POST['edit']['language'];
- } elseif( is_numeric(arg(1)) && $node = node_load(arg(1)) ) {
- // Node language when loading specific nodes
- $language = $node->language;
- }
- if($language) i18n_selection_mode('node', db_escape_string($language));
- } elseif(arg(0) == 'admin') {
- // No restrictions for administration pages
- i18n_selection_mode('off');
- }
- }
+function i18n_menu() {
+ $items[] = array(
+ 'path' => 'admin/settings/i18n',
+ 'title' => 'Multilingual system',
+ 'description' => 'Configure multilingual content and translation.',
+ 'callback' => 'drupal_get_form',
+ 'callback arguments' => array('i18n_admin_settings'),
+ 'access' => user_access('administer site configuration'),
+ );
+ $items[] = array(
+ 'path' => 'admin/settings/i18n/main',
+ 'title' => 'Internationalization',
+ 'type' => MENU_DEFAULT_LOCAL_TASK
+ );
return $items;
}
@@ -166,6 +120,7 @@ function i18n_menu($may_cache) {
/**
* Implementation of hook_nodeapi().
*/
+/*
function i18n_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
if (variable_get("i18n_node_$node->type", 0)) {
switch ($op) {
@@ -174,102 +129,88 @@ function i18n_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
case 'insert':
case 'update':
db_query("DELETE FROM {i18n_node} WHERE nid=%d",$node->nid);
- if($node->language){
+ if ($node->language){
+ // Assign a trid from the beginning
db_query("INSERT INTO {i18n_node} (nid, trid, language, status) VALUES(%d, '%d', '%s', '%d')", $node->nid, $node->trid, $node->language, $node->i18n_status);
}
+ // Handle menu items. Fixes duplication issue and language for menu items which happens when editing nodes in languages other than current.
+ if (isset($node->menu) && !$node->menu['delete'] && $node->menu['title']) {
+ $item = $node->menu;
+ $item['path'] = ($item['path']) ? $item['path'] : "node/$node->nid";
+ $item['type'] = $item['type'] | MENU_MODIFIED_BY_ADMIN;
+ if ($item['mid']) {
+ // Update menu item
+ db_query("UPDATE {menu} SET pid = %d, path = '%s', title = '%s', description = '%s', weight = %d, type = %d, language = '%s' WHERE mid = %d", $item['pid'], $item['path'], $item['title'], $item['description'], $item['weight'], $item['type'], $node->language, $item['mid']);
+ drupal_set_message(t('The menu item %title has been updated with node language.', array('%title' => $item['title'])));
+ } elseif(SAVED_NEW == menu_save_item($item)) {
+ // Creating new menu item with node language
+ db_query("UPDATE {menu} SET language = '%s' WHERE mid = %d", $node->language, $item['mid']);
+ drupal_set_message(t('The menu item %title has been added with node language.', array('%title' => $item['title'])));
+ }
+ menu_rebuild();
+ unset($node->menu); // Avoid further processing by menu module
+ }
+ // Pathauto integration. Dynamic replacement of variables to allow different patterns per language
+ if (module_exists('path') && module_exists('pathauto')) {
+ // Language for pathauto variables is either node language or default language
+ $language = $node->language ? $node->language : i18n_default_language();
+ if ($language != i18n_get_lang()) {
+ i18n_variable_init($language, 'pathauto_node');
+ }
+ }
break;
case 'delete':
db_query('DELETE FROM {i18n_node} WHERE nid=%d', $node->nid);
break;
+ case 'prepare':
+ // Book pages, set the right language nodes and outlines
+ if (arg(3) == 'parent' && is_numeric(arg(4)) && ($parent = node_load(arg(4))) && $parent->language) {
+ $node->language = $parent->language;
+ i18n_selection_mode('node', $parent->language);
+ }
+ break;
}
}
}
-
+*/
/**
- * Implementation of hook_taxonomy
+ * Implementation of hook_user()
*
- * $edit parameter may be an array or an object !!
- */
-function i18n_taxonomy($op, $type, $edit = NULL) {
- $edit = (array)$edit;
- switch ("$type/$op") {
- case 'term/insert':
- case 'term/update':
- $language = isset($edit['language']) ? $edit['language'] : '';
- db_query("UPDATE {term_data} SET language='%s' WHERE tid=%d", $language, $edit['tid']);
- break;
- case 'vocabulary/insert':
- case 'vocabulary/update':
- $language = isset($edit['language']) ? $edit['language'] : '';
- db_query("UPDATE {vocabulary} SET language='%s' WHERE vid=%d", $language, $edit['vid']);
- if ($language && $op == 'update') {
- db_query("UPDATE {term_data} t SET t.language='%s' WHERE t.vid=%d", $edit['language'], $edit['vid']);
- drupal_set_message(t('Reset language for all terms.'));
- }
- break;
+ * Switch to user's language after login
+ */
+function i18n_user($op, &$edit, &$account, $category = NULL) {
+ if($op == 'login' && $account->language) {
+ $_SESSION['language'] = $account->language;
+ i18n_get_lang($account->language);
}
}
/**
* Form builder function.
*
+ * TO DO: Add exclude paths for content selection
* Some options have been removed from previous versions:
* - Languages are now taken from locale module unless defined in settings file
* - Language dependent tables are authomatically used if defined in settings file
*/
function i18n_admin_settings() {
- // Check languages
- $languages = variable_get('i18n_languages', array());
- if (!count($languages) || ! count($languages['active']) > 1 ) {
- drupal_set_message(t('No languages enabled. Visit the !locale_admin page to set up your languages.', array('%locale_admin' => l(t('Manage languages'), 'admin/settings/locale/'))), 'error');
- }
- $form['i18n_browser'] = array(
- '#type' => 'radios',
- '#title' => t('Browser language detection'),
- '#default_value' => variable_get('i18n_browser', 0),
- '#options' => array(t('Disabled'), t('Enabled' )),
- '#description' => t("User browser language for home page and links without language prefix."),
- );
-
- // Language icons
- $form['icons'] = array(
- '#type' => 'fieldset',
- '#title' => t('Language icons settings'),
- '#collapsible' => TRUE,
- '#collapsed' => FALSE,
- );
- $form['icons']['i18n_icon_path'] = array(
- '#type' => 'textfield',
- '#title' => t('Language icons path'),
- '#default_value' => variable_get('i18n_icon_path', drupal_get_path('module', 'i18n').'/flags/*.png'),
- '#size' => 70,
- '#maxlength' => 180,
- '#description' => t('Path for language icons, relative to Drupal installation. \'*\' is a placeholder for language code.'),
- );
- $form['icons']['i18n_icon_size'] = array(
- '#type' => 'textfield',
- '#title' => t('Language icons size'),
- '#default_value' => variable_get('i18n_icon_size', '16x12'),
- '#size' => 10,
- '#maxlength' => 10,
- '#description' => t('Image size for language icons, in the form "width x height".'),
- );
- // Advanced options
- $form['advanced'] = array(
+ // Content selection options
+ $form['selection'] = array(
'#type' => 'fieldset',
- '#title' => t('Advanced settings'),
- '#collapsible' => TRUE,
- '#collapsed' => TRUE,
+ '#title' => t('Content selection'),
+ //'#collapsible' => TRUE,
+ //'#collapsed' => TRUE,
);
- $form['advanced']['i18n_selection_mode'] = array(
+ $form['selection']['i18n_selection_mode'] = array(
'#type' => 'radios',
'#title' => t('Content selection mode'),
'#default_value' => variable_get('i18n_selection_mode', 'simple'),
'#options' => _i18n_selection_mode(),
'#description' => t('Determines which content to show depending on language.'),
);
+
return system_settings_form($form);
}
@@ -278,30 +219,9 @@ function i18n_admin_settings() {
* Simple i18n API
*/
-/**
- * Get list of supported languages
- */
-function i18n_supported_languages() {
- return i18n_languages('active');
-}
-/**
- * Returns default language
- */
-function i18n_default_language(){
- return i18n_languages('site_default');
-}
-/**
- * Check whether language is RTL
- *
- * @param $language
- * Language to check, defaults to current language
- */
-function i18n_language_rtl($language = NULL) {
- $language = $language ? $language : i18n_get_lang();
- return i18n_language_property($language, 'rtl') ? TRUE : FALSE;
-}
+
/**
* Get language properties
@@ -312,7 +232,7 @@ function i18n_language_rtl($language = NULL) {
* It may be 'name', 'native', 'ltr'...
*/
function i18n_language_property($code, $property = 'native') {
- $languages = i18n_languages($property);
+ $languages = language_list($property);
return $languages[$code];
}
@@ -332,229 +252,81 @@ function i18n_languages($key = 'active') {
if($languages = variable_get('i18n_languages', 0)) {
foreach($languages['name'] as $code => $name) {
if($languages['enabled'][$code]) {
- $languages['active'][$code] = $languages['native'][$code];
+ $languages['active'][$code] = $name;
}
}
} else {
- $languages = locale_supported_languages();
- $languages['site_default'] = key($languages);
+ // It is possible that languages are not initialized
+ if (function_exists('locale_supported_languages')) {
+ $languages = locale_supported_languages();
+ } else {
+ // Worst case scenario: locale module not loaded, for cached pages, at least this won't break everything
+ unset($languages); // There's some PHP bug: http://www.zend.com/zend/week/week98.php
+ $languages['name'] = array('en' => 'English');
+ }
+ $languages['site_default'] = key($languages['name']);
$languages['active'] = $languages['name'];
$languages['native'] = $languages['name'];
}
+ // Sort everything alphabetically
+ asort($languages['name']);
+ asort($languages['active']);
+ asort($languages['native']);
}
return $key ? $languages[$key] : $languages;
}
/**
- * Get language from browser settings, but only if it is a valid language
- */
-function i18n_get_browser_lang() {
- $languages = i18n_supported_languages();
- $exploded_server = explode(";", $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
- $accept=explode(',', array_shift($exploded_server));
- foreach ($accept as $lang) {
- if(empty($lang)) {
- continue;
- } elseif (array_key_exists($lang, $languages)) {
- return $lang;
- } elseif (array_key_exists(substr($lang, 0, 2), $languages)) {
- return substr($lang, 0, 2);
- }
- }
-}
-
-/**
- * Get language code from path.
- *
- * @param $path
- * @param $trim
- * TRUE to remove language code from $path
- */
-function i18n_get_lang_prefix(&$path, $trim = FALSE) {
- $exploded_path = explode('/', $path);
- $maybelang = array_shift($exploded_path);
- $languages = i18n_supported_languages();
- if(array_key_exists($maybelang, $languages)){
- if($trim) {
- $path = trim(substr($path, strlen($maybelang)),'/');
- }
- return $maybelang;
- }
-}
-
-/**
- * Language dependent front page
- * This function will search for aliases like 'en/home', 'es/home'...
- */
-function i18n_frontpage($lang = NULL) {
- $lang = $lang ? $lang : _i18n_get_lang();
- return i18n_get_normal_path($lang.'/'.variable_get('site_frontpage','node'));
-}
-
-/**
- * This function is similar to drupal_get_normal_path, but language-aware
- * Also removes language from path
- */
-function i18n_get_normal_path($path) {
- $prefix = i18n_get_lang_prefix($path, TRUE);
- if(!$prefix || _i18n_is_bootstrap()){
- // If bootstrap, drupal_lookup_path is not defined
- return $path;
- } // First, check alias with lang
- elseif($alias = drupal_lookup_path('source', $prefix.'/'.$path)){
- i18n_get_lang_prefix($alias, TRUE); // In case alias has language
- return $alias;
- } // Check alias without lang
- elseif($alias = drupal_lookup_path('source', $path)){
- i18n_get_lang_prefix($alias, TRUE);
- return $alias;
- }
- else {
- return $path;
- }
-}
-
-/**
* More i18n API
*/
/**
- * Produces i18n paths, with language prefix
- * If path is empty or site frontpage, path = 'lang'
- * Check for frontpage and search for alias before adding language
+ * Get node language
*/
-function i18n_path($path, $lang) {
- if (!$path || $path == i18n_frontpage($lang)) {
- return $lang;
- } elseif($alias = drupal_lookup_path('alias', $path)) {
- if($prefix = i18n_get_lang_prefix($alias)) {
- // This alias will be valid only if it has the same language
- return ($prefix == $lang) ? $alias : $lang.'/'.$path;
- } else { // Alias without language prefix
- return $lang.'/'.$alias;
- }
- } else { // Alias for language path will be searched later
- return $lang.'/'.$path;
- }
-}
-
function i18n_node_get_lang($nid, $default = '') {
- $lang = db_result(db_query('SELECT language FROM {i18n_node} WHERE nid=%d',$nid));
+ $lang = db_result(db_query('SELECT language FROM {node} WHERE nid=%d',$nid));
return $lang ? $lang : $default ;
}
/**
- * Returns main language, two letter code
+ * Get allowed languages for node
+ *
+ * This allows node types to define its own language list implementing hook 'language_list'
*/
-function i18n_get_main_lang($lang = NULL){
- $lang = $lang ? $lang : i18n_get_lang();
- return substr($lang, 2);
+function i18n_node_language_list($node) {
+ if ($languages = node_invoke($node, 'language_list')) {
+ return $languages; // The node module manages its own language list
+ } elseif(variable_get('i18n_node_'.$node->type, 0) == LANGUAGE_SUPPORT_EXTENDED) {
+ return i18n_language_list(TRUE); // All defined languages
+ } else {
+ return i18n_language_list(); // All enabled languages
+ }
}
/**
* Function i18n_get_links
*
* Returns an array of links for all languages, with or without names/flags
+ *
+ * @param $path
+ * Drupal internal path
+ * @param $query
+ * Query string
+ * @param $names
+ * Names to use for the links. Defaults to native language names
*/
-function i18n_get_links($path = '', $query = NULL) {
+function i18n_get_links($path = '', $query = NULL, $names = NULL) {
if($path == i18n_frontpage()) {
$path = '';
}
- foreach(i18n_supported_languages() as $lang => $name){
- $links[$lang]= theme('i18n_link', $name, i18n_path($path, $lang), $lang, $query);
+ $names = $names ? $names : i18n_languages('native');
+ foreach (array_keys(i18n_supported_languages()) as $lang){
+ $links[$lang]= theme('i18n_link', $names[$lang], i18n_path($path, $lang), $lang, $query);
}
return $links;
}
/**
- * Gets language, checking in order:
- *
- * 1. Path language
- * 2. User language
- * 3. Browser language
- * 4. Default language
- */
-
-function _i18n_get_lang() {
- global $user, $i18n_langpath;
- static $i18n_lang;
- // Check whether the language is already set.
- if ($i18n_lang) {
- return $i18n_lang;
- }
- // Language not set, find one
- $languages = i18n_supported_languages();
- if ($i18n_langpath && array_key_exists($i18n_langpath,$languages)) {
- $i18n_lang = $i18n_langpath;
- }
- elseif ($user->uid && $user->language && array_key_exists($user->language,$languages)) {
- $i18n_lang = $user->language;
- }
- elseif (variable_get("i18n_browser",0) && $lang=i18n_get_browser_lang()) {
- $i18n_lang=$lang;
- }
- else {
- $i18n_lang=key($languages);
- }
- return $i18n_lang;
-}
-
-/**
- * Check whether we are in bootstrap mode
- */
-function _i18n_is_bootstrap(){
- return !function_exists('drupal_get_headers');
-}
-
-/**
- * Sets db_prefix to given language
- */
-function _i18n_set_db_prefix($lang) {
- global $db_prefix, $db_prefix_i18n;
- if (is_array($db_prefix_i18n)) {
- $db_prefix = array_merge($db_prefix, str_replace('**', $lang, $db_prefix_i18n));
- }
-}
-
-/**
- * To get the original path.
- * Cannot use $_GET["q"] cause it may have been already changed
- */
-function _i18n_get_original_path() {
- return isset($_REQUEST["q"]) ? trim($_REQUEST["q"],"/") : '';
-}
-
-/**
- * Returns list of enabled languages from locale module
- *
- * Some code borrowed from locale module.
- * And yes, if locale enabled, languages are cached twice. But better twice than never ;-)
- */
-function _i18n_locale_supported_languages() {
- if(function_exists('locale_supported_languages')){
- $languages = locale_supported_languages();
- return $languages['name'];
- } else {
- $result = db_query('SELECT locale, name FROM {locales_meta} WHERE enabled = 1 ORDER BY isdefault DESC, name ASC');
- while ($row = db_fetch_object($result)) {
- $enabled[$row->locale] = $row->name;
- }
- return $enabled;
- }
-}
-
-/**
- * Emulates drupal_goto, it may not be loaded yet
- */
-function _i18n_goto($lang){
- if(!function_exists('drupal_goto')){
- require_once './includes/common.inc';
- require_once './includes/path.inc';
- }
- drupal_goto($lang);
-}
-
-/**
* i18n_selection_mode
*
* Allows several modes for query rewriting and to change them programatically
@@ -586,7 +358,7 @@ function i18n_selection_mode($mode= NULL, $params= NULL){
$current_value = $params;
}
}
-
+// List of selection modes
function _i18n_selection_mode(){
return array(
'simple' => t('Only current language and no language'),
@@ -596,6 +368,14 @@ function _i18n_selection_mode(){
'off' => t('All content. No language conditions apply'),
);
}
+// List of language support modes for content
+function _i18n_content_languages() {
+ return array(
+ LANGUAGE_SUPPORT_NONE => t('Disabled'),
+ LANGUAGE_SUPPORT_NORMAL => t('Normal - All enabled languages will be allowed.'),
+ LANGUAGE_SUPPORT_EXTENDED => t('Extended - All defined languages will be allowed.')
+ );
+}
/**
* @name Themeable functions
@@ -615,100 +395,46 @@ function theme_i18n_link($text, $target, $lang, $query= NULL, $fragment = NULL){
return $output;
}
-/**
- * Theme language icon
- *
- * This function can be overridden for no language icons
- */
-function theme_i18n_language_icon($lang){
- if ($path = variable_get('i18n_icon_path', drupal_get_path('module', 'i18n').'/flags/*.png')) {
- $languages = i18n_supported_languages();
- $src = base_path().str_replace('*', $lang, $path);
- list($width, $height) = explode('x', variable_get('i18n_icon_size', '16x12'));
- $attribs = array('class' => 'i18n-icon', 'width' => $width, 'height' => $height, 'alt' => $languages[$lang]);
- return "<img src=\"$src\" ".drupal_attributes($attribs)." />";
- }
-}
-
/* @} */
/**
- * Implementation of conf_url_rewrite
- *
- * This is a conditional definition, just in case it is defined somewhere else.
- * If so, path rewriting won't work properly but at least it won't break Drupal
- */
-
-if(!function_exists('custom_url_rewrite')) {
- function custom_url_rewrite($type, $path, $original) {
- return i18n_url_rewrite($type, $path, $original);
- }
-}
-
-/**
- * Rewrites path with current language
- */
-function i18n_url_rewrite($type, $path, $original){
- if ($type == 'alias' && !i18n_get_lang_prefix($path) ){
- return $path ? i18n_get_lang() . '/'. $path : i18n_get_lang();
- } else {
- return $path;
- }
-}
-
-/**
* Implementation of hook_db_rewrite_sql()
*/
function i18n_db_rewrite_sql($query, $primary_table, $primary_key){
- // Some exceptions for query rewrites
- $mode = i18n_selection_mode();
- // drupal_set_message("i18n_db_rewrite mode=$mode query=$query");
- if ($mode == 'off') return;
-
+
switch ($primary_table) {
case 'n':
case 'node':
- // Node queries
- return i18n_db_node_rewrite($query, $primary_table, $primary_key, $mode);
- case 't':
- case 'v':
- // Taxonomy queries
- return i18n_db_taxonomy_rewrite($query, $primary_table, $primary_key, $mode);
+ // Node queries.
+ // No rewrite for translation module queries
+ if (preg_match("/.*FROM {node} WHERE.* tnid/", $query)) return;
+ // When loading specific nodes, language conditions shouldn't apply
+ if (preg_match("/WHERE.*\s$primary_table.nid\s*=\s*(\d|%d)/", $query)) return;
+ // If language conditions already there, get out
+ if (preg_match("/i18n/", $query)) return;
+
+ //$result['join'] = "LEFT JOIN {i18n_node} i18n ON $primary_table.nid = i18n.nid";
+ $result['where'] = i18n_db_rewrite_where($primary_table, 'node');
+ return $result;
}
}
/**
- * Rewrite node queries
- */
-function i18n_db_node_rewrite($query, $primary_table, $primary_key, $mode){
- // When loading specific nodes, language conditions shouldn't apply
- if (preg_match("/WHERE.*\s$primary_table.nid\s*=\s*(\d|%d)/", $query)) return;
-
- $result['join'] = "LEFT JOIN {i18n_node} i18n ON $primary_table.nid = i18n.nid";
- $result['where'] = i18n_db_rewrite_where('i18n', $mode);
-
- return $result;
-}
-
-/**
- * Rewrite taxonomy queries
- */
-function i18n_db_taxonomy_rewrite($query, $primary_table, $primary_key, $mode){
- // When loading specific terms, vocabs, language conditions shouldn't apply
- if (preg_match("/WHERE.* $primary_table\.tid\s*(=\s*\d|IN)/", $query)) return;
- // Taxonomy for specific node
- if (preg_match("/WHERE r\.nid = \%d/", $query)) return;
-
- $result['where'] = i18n_db_rewrite_where($primary_table, $mode);
-
- return $result;
-}
-
-/**
* Rewrites queries depending on rewriting mode
*/
-function i18n_db_rewrite_where($alias, $mode){
+function i18n_db_rewrite_where($alias, $type, $mode = NULL){
+ if (!$mode) {
+ // Some exceptions for query rewrites
+ $mode = i18n_selection_mode();
+ // drupal_set_message("i18n_db_rewrite mode=$mode query=$query");
+ }
+ // Special case. Selection mode is 'strict' but this should be only for node queries
+ if ($mode == 'strict' && $type != 'node') {
+ $mode = 'simple';
+ }
switch($mode){
+ case 'off':
+ return '';
case 'simple':
return "$alias.language ='".i18n_get_lang()."' OR $alias.language ='' OR $alias.language IS NULL" ;
case 'mixed':
@@ -721,7 +447,7 @@ function i18n_db_rewrite_where($alias, $mode){
case 'default':
return "$alias.language ='".i18n_default_language()."' OR $alias.language ='' OR $alias.language IS NULL" ;
case 'custom':
- return str_replace('%alias',$alias, i18n_selection_mode('params'));
+ return str_replace('%alias', $alias, i18n_selection_mode('params'));
}
}
@@ -737,97 +463,80 @@ function i18n_exit(){
*
* This is the place to add language fields to all forms
*/
-function i18n_form_alter($form_id, &$form) {
- //drupal_set_message("i18n_form_alter form_id=$form_id ");
+function i18n_form_alter(&$form, $form_state, $form_id) {
+ //drupal_set_message("DEBUG: i18n_form_alter form_id=$form_id ");
switch($form_id){
- case 'taxonomy_overview_vocabularies':
- $vocabularies = taxonomy_get_vocabularies();
- $languages = i18n_supported_languages();
- foreach ($vocabularies as $vocabulary) {
- if($vocabulary->language) $form[$vocabulary->vid]['type']['#value'] = $form[$vocabulary->vid]['type']['#value'].'&nbsp('.$languages[$vocabulary->language].')';
- }
- break;
- case 'taxonomy_form_vocabulary': // Taxonomy vocabulary
- if(isset($form['vid'])) {
- $vocabulary = taxonomy_get_vocabulary($form['vid']['#value']);
- }
- $form['language'] = _i18n_language_select(isset($vocabulary) ? $vocabulary->language : i18n_get_lang(),t('This language will be set for all terms in this vocabulary'));
- break;
-
- case 'taxonomy_form_term': // Taxonomy term
- if(isset($form['tid']) && is_numeric($form['tid']['#value'])) {
- $term = taxonomy_get_term($form['tid']['#value']);
- }
- $form['language'] = _i18n_language_select(isset($term) ? $term->language : i18n_get_lang());
- break;
-
case 'node_type_form':
$node_type = $form['old_type']['#value'];
- $form['workflow']['i18n_node'] = array(
+ // Build a fieldset to allow some more options here
+ $form['workflow']['i18n'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Multilingual options'),
+ );
+ $form['workflow']['i18n']['i18n_node'] = array(
'#type' => 'radios',
- '#title' => t('Multilingual support'),
+ '#title' => t('Multilingual content'),
'#default_value' => variable_get('i18n_node_'.$node_type, 0),
- '#options' => array(t('Disabled'), t('Enabled')),
- '#description' => t('Enables language field and multilingual support for this content type.'),
+ '#options' => _i18n_content_languages(),
+ '#description' => t('Enables language field and translations for this content type.'),
);
break;
- case '_locale_admin_manage_screen': // Locale language settings
- $languages = locale_supported_languages(TRUE, TRUE);
- $i18nlangs = variable_get('i18n_languages', array());
- $form['native'] = array('#tree' => TRUE);
- foreach ($languages['name'] as $key => $lang) {
- $options[$key] = '';
-
- $form['native'][$key] = array('#type' => 'textfield',
- '#default_value' => $i18nlangs['native'][$key] ? $i18nlangs['native'][$key] : $lang,
- '#size' => 15,
- '#maxlength' => 64,
- );
- }
- $form['rtl'] = array(
- '#type' => 'checkboxes',
- '#options' => $options,
- '#default_value' => $i18nlangs['rtl']
- );
- $form['#base'] = 'i18n_admin_manage_screen';
- if(!is_array($form['#submit'])) {
- $form['#submit'] = array('_locale_admin_manage_screen_submit' => array());
- }
- $form['#submit'] = array('i18n_admin_manage_screen_submit' => array()) + $form['#submit'];
- break;
-
+
default:
// Node edit form
- if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
+ /** @ TO DO Upgrade
+ if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id && $node = $form['#node']) {
// Language field
if(variable_get('i18n_node_'.$form['type']['#value'], 0) && !isset($form['i18n']['language'])) {
- // Language field
- $form['i18n'] = array('#type' => 'fieldset', '#title' => t('Multilingual settings'), '#collapsible' => TRUE, '#collapsed' => FALSE, '#weight' => -4);
- // Language will default to current only when creating a node
+ // Language field
+ $form['i18n'] = array('#type' => 'fieldset', '#title' => t('Multilingual settings'), '#collapsible' => TRUE, '#collapsed' => FALSE, '#weight' => -4);
+ // Language will default to current only when creating a node
$language = isset($form['#node']->language) ? $form['#node']->language : (arg(1)=='add' ? i18n_get_lang() : '');
- $form['i18n']['language'] = _i18n_language_select($language, t('If you change the Language, you must click on <i>Preview</i> to get the right Categories &amp; Terms for that language.'), -4);
+ $form['i18n']['language'] = _i18n_language_select($language, t('If you change the Language, you must click on <i>Preview</i> to get the right Categories &amp; Terms for that language.'), -4, i18n_node_language_list($node));
+ $form['i18n']['trid'] = array('#type' => 'value', '#value' => $form['#node']->trid);
}
// Correction for lang/node/nid aliases generated by path module
- // if($form['#node']->path && $form['#node']->path == i18n_get_lang().'/node/'.$form['#node']->nid){
- if($form['#node']->path) {
- $alias = drupal_lookup_path('alias', 'node/'.$form['#node']->nid);
- if($alias && $alias != 'node/'.$form['#node']->nid){
+ // if($form['#node']->path && $form['#node']->path == i18n_get_lang().'/node/'.$form['#node']->nid){
+ if($node->path) {
+ $alias = drupal_lookup_path('alias', 'node/'.$node->nid);
+ if($alias && $alias != 'node/'.$node->nid){
$form['#node']->path = $alias;
} else {
unset($form['#node']->path);
}
}
}
+ */
// Multilingual variables in settings form
- if ($form['#base'] == 'system_settings_form' && $variables = variable_get('i18n_variables', 0)) {
- if(i18n_form_alter_settings($form, $variables)) {
- $form['#submit'] = array('i18n_variable_form_submit' => array());
+ if (isset($form['#theme']) && $form['#theme'] == 'system_settings_form' && $variables = variable_get('i18n_variables', 0)) {
+ if (i18n_form_alter_settings($form, $variables)) {
+ $form['#submit'][] = 'i18n_variable_form_submit';
}
}
}
}
/**
+ * Implementation of hook_perm().
+ *
+ * Permissions defined
+ * - administer all languages
+ * Disables language conditions for administration pages, so the user can view objects for all languages at the same time.
+ * This applies for: menu items, taxonomy
+ */
+function i18n_perm() {
+ return array('administer all languages');
+}
+/**
+ * Process menu and menu item add/edit form submissions.
+ */
+function i18n_menu_edit_item_form_submit($form_id, $form_values) {
+ $mid = menu_edit_item_save($form_values);
+ db_query("UPDATE {menu} SET language = '%s' WHERE mid = %d", $form_values['language'], $mid);
+ return 'admin/build/menu';
+}
+
+/**
* Theme the locale admin manager form.
*/
function theme_i18n_admin_manage_screen($form) {
@@ -859,13 +568,14 @@ function i18n_admin_manage_screen_submit($form_id, $form_values) {
}
variable_set('i18n_languages', $save);
}
+
/**
* Check for multilingual variables in form
*/
function i18n_form_alter_settings(&$form, &$variables) {
$result = 0;
- foreach(element_children($form) as $field) {
- if($form[$field]['#type'] == 'fieldset') {
+ foreach (element_children($form) as $field) {
+ if(isset($form[$field]['#type']) && $form[$field]['#type'] == 'fieldset') {
$result += i18n_form_alter_settings($form[$field], $variables);
}
elseif (in_array($field, $variables)) {
@@ -879,12 +589,13 @@ function i18n_form_alter_settings(&$form, &$variables) {
/**
* Save multilingual variables and remove them from form
*/
-function i18n_variable_form_submit($form_id, $form_values) {
+function i18n_variable_form_submit($form, &$form_state) {
+ $form_values = $form_state['values'];
$op = isset($form_values['op']) ? $form_values['op'] : '';
$variables = variable_get('i18n_variables', array());
$language = i18n_get_lang();
foreach ($form_values as $key => $value) {
- if(in_array($key, $variables)) {
+ if (in_array($key, $variables)) {
if ($op == t('Reset to defaults')) {
i18n_variable_del($key, $language);
}
@@ -898,19 +609,26 @@ function i18n_variable_form_submit($form_id, $form_values) {
}
}
// Re-submit form
- system_settings_form_submit($form_id, $form_values);
+ // system_settings_form_submit($form_id, $form_values);
}
/**
- * Initialization of multilingual variables
+ * Initialization of multilingual variables
+ *
+ * @param $language
+ * Language to retrieve variables. Defaults to current language
+ * @param $prefix
+ * Variable name prefix to load just a selected group of variables
*/
-function i18n_variable_init(){
+function i18n_variable_init($language = NULL, $prefix = ''){
global $conf;
global $i18n_conf;
- $lang = _i18n_get_lang();
- if($i18n_variables = variable_get('i18n_variables', '')){
- $i18n_conf = array();
- $variables = _i18n_variable_init();
+ $language = $language ? $language : i18n_get_lang();
+ if ($i18n_variables = variable_get('i18n_variables', '')){
+ if (!$i18n_conf) {
+ $i18n_conf = array();
+ }
+ $variables = _i18n_variable_init($language, $prefix);
foreach($i18n_variables as $name){
$i18n_conf[$name] = isset($variables[$name]) ? $variables[$name] : (isset($conf[$name]) ? $conf[$name] : '');
}
@@ -918,75 +636,40 @@ function i18n_variable_init(){
}
}
-/**
- * Set a persistent language dependent variable.
- *
- * @param $name
- * The name of the variable to set.
- * @param $value
- * The value to set. This can be any PHP data type; these functions take care
- * of serialization as necessary.
- */
-function i18n_variable_set($name, $value, $language) {
- global $conf, $i18n_conf;
-
- db_lock_table('i18n_variable');
- db_query("DELETE FROM {i18n_variable} WHERE name = '%s' AND language='%s'", $name, $language);
- db_query("INSERT INTO {i18n_variable} (name, language, value) VALUES ('%s', '%s', '%s')", $name, $language, serialize($value));
- db_unlock_tables();
- cache_clear_all('variables:'.$language, 'cache');
-
- $conf[$name] = $value;
- $i18n_conf[$name] = $value;
-}
-
-/**
- * Unset a persistent multilingual variable.
- *
- * @param $name
- * The name of the variable to undefine.
- */
-function i18n_variable_del($name, $language) {
- global $conf, $i18n_conf;
-
- db_query("DELETE FROM {i18n_variable} WHERE name = '%s' AND language='%s'", $name, $language);
- cache_clear_all('variables:'.$language, 'cache');
-
- unset($conf[$name]);
- unset($i18n_conf[$name]);
-}
/**
* Helper function to create language selector
*/
-function _i18n_language_select($value ='', $description ='', $weight = -20){
+function _i18n_language_select($value ='', $description ='', $weight = -20, $languages = NULL){
+ $languages = $languages ? $languages : i18n_language_list();
return array(
'#type' => 'select',
'#title' => t('Language'),
'#default_value' => $value,
- '#options' => array_merge(array('' => ''), i18n_supported_languages()),
+ '#options' => array_merge(array('' => ''), $languages),
'#description' => $description,
'#weight' => $weight,
);
}
-function _i18n_variable_init(){
- $lang = _i18n_get_lang();
+/**
+ * Load language variables into array
+ */
+function _i18n_variable_init($language, $prefix = ''){
$variables = array();
- if ($cached = cache_get('variables:'.$lang)) {
- $variables = unserialize($cached->data);
+ $cacheid = 'variables:'.$language.($prefix ? ':'.$prefix : '');
+ if ($cached = cache_get($cacheid)) {
+ $variables = $cached->data;
}
else {
- $result = db_query("SELECT * FROM {i18n_variable} WHERE language='%s'", $lang);
+ $result = db_query("SELECT * FROM {i18n_variable} WHERE language='%s' AND name LIKE '%s%'", $language, $prefix);
while ($variable = db_fetch_object($result)) {
$variables[$variable->name] = unserialize($variable->value);
}
- cache_set('variables:'.$lang, 'cache', serialize($variables));
+ cache_set($cacheid, $variables);
}
-
- return $variables;
-
+ return $variables;
}
/**
@@ -996,7 +679,7 @@ function _i18n_variable_exit(){
global $i18n_conf;
global $conf;
if($i18n_conf){
- $lang = _i18n_get_lang();
+ $lang = i18n_get_lang();
$refresh = FALSE;
// Rewritten because array_diff_assoc may fail with array variables
foreach($i18n_conf as $name => $value){
@@ -1012,3 +695,160 @@ function _i18n_variable_exit(){
}
}
}
+
+/**
+ * Check whether we are in bootstrap mode
+ */
+function _i18n_is_bootstrap(){
+ return !function_exists('drupal_get_headers');
+}
+
+/**
+ * Sets db_prefix to given language
+ */
+function _i18n_set_db_prefix($lang) {
+ global $db_prefix, $db_prefix_i18n;
+ if (is_array($db_prefix_i18n)) {
+ $db_prefix = array_merge($db_prefix, str_replace('**', $lang, $db_prefix_i18n));
+ }
+}
+
+/**
+ * To get the original path.
+ * Cannot use $_GET["q"] cause it may have been already changed
+ */
+function _i18n_get_original_path() {
+ return isset($_REQUEST["q"]) ? trim($_REQUEST["q"],"/") : '';
+}
+
+/**
+ * Drupal 6, backwards compatibility layer
+ * @ TO DO Fully upgrade all the modules and remove
+ */
+/**
+ * This one expects to be called first from common.inc
+ */
+function i18n_get_lang($setlanguage = NULL) {
+ global $language;
+
+ return $language->language;
+}
+
+/**
+ * Returns default language
+ */
+function i18n_default_language(){
+ return language_default('language');
+}
+
+/**
+ * Language dependent front page
+ * This function will search for aliases like 'en/home', 'es/home'...
+ */
+function i18n_frontpage($lang = NULL) {
+ $lang = $lang ? $lang : i18n_get_lang();
+ return i18n_get_normal_path($lang.'/'.variable_get('site_frontpage','node'));
+}
+
+/**
+ * Get localized language list, sort alphabetically
+ *
+ * @param $all
+ * TRUE for all languages, not only enabled
+ */
+function i18n_language_list($field = 'name', $all = FALSE) {
+ if ($all) {
+ $languages = language_list();
+ }
+ else {
+ $languages = language_list('enabled');
+ $languages = $languages[1];
+ }
+ $list = array();
+ foreach ($languages as $language) {
+ $list[$language->language] = ($field == 'name') ? t($language->name) : $language->$field;
+ }
+ return $list;
+}
+
+/**
+ * Get list of supported languages
+ * @param $all
+ * TRUE to get all defined languages
+ */
+function i18n_supported_languages($all = FALSE) {
+ return i18n_language_list('native', $all);
+}
+
+/**
+ * @defgroup i18n_api Extended language API
+ * @{
+ * This is an extended language API to be used by modules in i18n package.
+ */
+
+/**
+ * Set a persistent language dependent variable.
+ *
+ * @param $name
+ * The name of the variable to set.
+ * @param $value
+ * The value to set. This can be any PHP data type; these functions take care
+ * of serialization as necessary.
+ * @param $langcode
+ * Language code
+ */
+function i18n_variable_set($name, $value, $langcode) {
+ global $conf, $i18n_conf;
+
+ db_lock_table('i18n_variable');
+ db_query("DELETE FROM {i18n_variable} WHERE name = '%s' AND language='%s'", $name, $langcode);
+ db_query("INSERT INTO {i18n_variable} (name, language, value) VALUES ('%s', '%s', '%s')", $name, $langcode, serialize($value));
+ db_unlock_tables();
+
+ cache_clear_all('variables:'.$langcode, 'cache');
+
+ $conf[$name] = $value;
+ $i18n_conf[$name] = $value;
+}
+
+/**
+ * Unset a persistent multilingual variable.
+ *
+ * @param $name
+ * The name of the variable to undefine.
+ * @param $langcode
+ * Language code
+ */
+function i18n_variable_del($name, $langcode) {
+ global $conf, $i18n_conf;
+
+ db_query("DELETE FROM {i18n_variable} WHERE name = '%s' AND language='%s'", $name, $langcode);
+ cache_clear_all('variables:'.$langcode, 'cache');
+
+ unset($conf[$name]);
+ unset($i18n_conf[$name]);
+}
+
+/**
+ * Utility. Get part of array variable
+ */
+function i18n_array_variable_get($name, $element, $default = NULL) {
+ if (($values = variable_get($name, array())) && isset($values[$element])) {
+ return $values[$element];
+ } else {
+ return $default;
+ }
+}
+
+/**
+ * Utility. Set part of array variable
+ */
+function i18n_array_variable_set($name, $element, $value) {
+ $values = variable_get($name, array());
+ $values[$element] = $value;
+ variable_set($name, $values);
+}
+
+/**
+ * @} End of "defgroup i18n_api".
+ */
diff --git a/translation/translation.info b/translation/translation.info
deleted file mode 100644
index 25f136f..0000000
--- a/translation/translation.info
+++ /dev/null
@@ -1,4 +0,0 @@
-name = Translation
-description = Manages translations between nodes and taxonomy terms.
-dependencies = i18n
-package = Multilanguage - i18n
diff --git a/translation/translation.module b/translation/translation.module
deleted file mode 100644
index 6a8760f..0000000
--- a/translation/translation.module
+++ /dev/null
@@ -1,1055 +0,0 @@
-<?php
-// $Id$
-
-/**
- * Internationalization (i18n) package.
- *
- * Translation module: translation
- *
- * @author Jose A. Reyero, 2004, http://www.reyero.net
- *
- */
-
-// Status for translations
-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);
-
-/**
- * Implementation of hook_help().
- */
-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('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;
-}
-
-/**
- * Implementation of hook_menu().
- */
-function translation_menu($may_cache) {
- $items = array();
-
- if ($may_cache) {
- $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)) && variable_get('i18n_node_'.translation_get_node_type(arg(1)), 0)) {
- $access = user_access('translate nodes');
- $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);
-
- }
- // Special redirections and rewrite conditions
- 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()) ) {
- // Special redirection for product types
- 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))) {
- drupal_goto(url("node/add/product/$ptype", "translation=$source_nid&language=$lang", NULL, TRUE));
- }
- // Change rewrite conditions when translating node
- i18n_selection_mode('translation', db_escape_string($lang));
- }
- }
-
- return $items;
-}
-
-/**
- * Implementation of hook_perm
- */
-function translation_perm(){
- return array('translate nodes');
-}
-
-/**
- * Form builder function: settings form
- */
-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);
-}
-
-/**
- * Implementation of hook_block().
- *
- * This is a simple language switcher which knows nothing about translations
- */
-function translation_block($op = 'list', $delta = 0) {
- if ($op == 'list') {
- $blocks[0]['info'] = t('Translations');
- }
- 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;
-}
-
-/**
- * Implementation of hook_form_alter().
- */
-function translation_form_alter($form_id, &$form) {
- // drupal_set_message('translation_form_alter');
- // Node edit 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_supported_languages();
- // Translation workflow, default
- if ($node->nid && $node->translation) {
- $translations = $node->translation;
- }
- elseif (isset($_GET['translation']) && user_access('translate nodes')) {
- // We are translating a node: node/add/type/translation/nid/lang
- $translation_nid = $_GET['translation'];
- $language = $_GET['language'];
- // Load the node to be translated and populate fields
- $trans = node_load($translation_nid);
- $form['i18n']['translation_nid'] = array('#type' => 'hidden', '#value' => $translation_nid);
- $form['i18n']['language']['#default_value'] = $language;
- // Do not allow language change
- $form['i18n']['language']['#disabled'] = TRUE;
- $form['i18n']['language']['#description'] = t('Language cannot be changed while creating a translation.');
- translation_node_populate_fields($trans, $form, $node);
- if($trans->trid){
- $form['i18n']['trid'] = array('#type' => 'hidden', '#value' => $trans->trid);
- }
- // Translations are taken from source node
- $translations = $trans->translation;
- $translations[$trans->language] = $trans;
- }
- if ($translations) {
- // Unset invalid languages
- foreach(array_keys($translations) as $lang) {
- unset($form['i18n']['language']['#options'][$lang]);
- }
- // Add translation list
- $form['i18n']['#title'] = t('Language and translations');
- $form['i18n']['translations'] = array(
- '#type' => 'markup',
- '#value' => theme('translation_node_list', $translations, FALSE)
- );
- }
- // Translation workflow
- 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);
- }
- // Clone files for original node ?
- 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);
- }
- }
- // Translate taxonomy terms
- // TO-DO: take care of module order. Default ordering is filename so it depends on install which is too bad!!
- if(isset($trans->taxonomy) && is_array($trans->taxonomy)) {
- // Set translated taxonomy terms
- $form['#node']->taxonomy = array();
- foreach ($trans->taxonomy as $tid => $term) {
- $translated_terms = translation_term_get_translations(array('tid' =>$tid));
- if ($translated_terms && $newterm = $translated_terms[$language]) {
- $form['#node']->taxonomy[$newterm->tid] = $newterm;
- //drupal_set_message("DEBUG: Translated term $tid to ". $newterm->tid);
- }
- // Run again taxonomy_form_alter ?
- if(isset($form['taxonomy'])) {
- unset($form['taxonomy']);
- taxonomy_form_alter($form_id, $form);
- }
- }
- }
- }
-}
-
-/**
- * Implementation of hook_nodeapi().
- *
- * Delete case is now handled in i18n_nodeapi
- */
-function translation_nodeapi(&$node, $op, $arg = 0) {
- if (variable_get("i18n_node_$node->type", 0)) {
- switch ($op) {
- case 'load':
- $node->translation = translation_node_get_translations(array('nid' =>$node->nid), FALSE);
- break;
- case 'insert':
- if($node->translation_nid) {
- // If not existing translation set, update both nodes. Otherwise trid is saved by i18n module
- 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);
- }
- // Clone files for node attachments
- if(isset($node->translation_files)) {
- foreach($node->translation_files as $fid => $file) {
- if(!$file['remove']) {
- // We are using revisions to have a file linked to different nodes, different descriptions
- db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $file['fid'], $node->vid, $file['list'], $file['description']);
- }
- }
- }
- }
- break;
- }
- }
-}
-
-/**
- * Fills up some fields from source node
- */
-function translation_node_populate_fields($source, &$form, &$node, $level = 0){
- $fields = array();
- $language = $form['i18n']['language']['#default_value'];
- foreach(element_children($form) as $key) {
- if($key == 'nid' || $key == 'vid' || $key == 'i18n'){
- continue;
- } elseif(isset($source->$key) && !isset($node->$key)) {
- if($level == 0 && $key == 'parent' && is_numeric($source->parent)) {
- // Translate book outline
- $trans = translation_node_get_translations(array('nid' => $source->parent));
- if(isset($trans[$language])) {
- $form['parent']['#default_value'] = $trans[$language]->nid;
- }
- } else {
- $node->$key = $form[$key]['#default_value'] = $source->$key;
- $fields[] = $key;
- }
- } elseif(!isset($form[$key]['#tree'])) {
- translation_node_populate_fields($source, $form[$key], $node, $level +1);
- }
- }
- // For debugging
- //if($fields) drupal_set_message("Populated fields ($level): ". implode(', ', $fields));
-}
-
-/**
- * Multilingual Nodes support
- */
-
-/**
- * This is the callback for the tab 'translation' for nodes
- */
-function translation_node_page() {
- $args = func_get_args();
- $op = $args[0];
- $nid = arg(1);
- $node = node_load($nid);
- // If node has no language, just warning message. Function returns here
- 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($node->title);
- $output = '';
- switch($op){
- case 'select':
- $output .= translation_node_overview($node);
- $output .= translation_node_select($node, $args[1]);
- break;
- case 'remove':
- case t('Remove'):
- db_query("UPDATE {i18n_node} SET trid = NULL WHERE nid=%d", $node->nid);
- drupal_set_message("The node has been removed from the translation set");
- drupal_goto("node/$node->nid/translation");
- default:
- $output .= translation_node_overview($node);
- }
- return $output;
-}
-
-/**
- * Form builder function
- */
-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_supported_languages();
-
- $form['nodes']['nid'] = array(
- '#type' => 'radios', '#title' => t('Select translation for %language', array('%language' => $languages[$lang])),
- '#default_value' => isset($node->translation[$lang]) ? $node->translation[$lang]->nid : '',
- '#options' => $list);
- $form['pager'] = array('#value' => theme('pager'));
- $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
- return $form;
-}
-
-/**
- * Menu callback: administration page for node translations
- */
-function translation_admin_content() {
- $output = '';
- $defaults = array('translation_language' => i18n_get_lang(), 'source_status' => TRANSLATION_STATUS_SOURCE);
- // Filter forms
- $output .= drupal_get_form('node_filter_form');
- $output .= drupal_get_form('translation_filter_form', $defaults);
- // Node listing depending on previous forms
- $output .= drupal_get_form('translation_admin_nodes');
-
- return $output;
-}
-
-/**
- * Form builder. Administrative form for node translations
- */
-function translation_admin_nodes() {
- // First, translation filter because it may need parameters for join conditions
- $filter = translation_build_filter_query();
- $where = $filter['where'];
- $params = $filter['args'];
- $join = $filter['join'];
-
- $filter = node_build_filter_query();
- // Remove WHERE
- if($filter['where']) {
- $where += array(str_replace('WHERE', '', $filter['where']));
- }
-
- $params = array_merge($params, $filter['args']);
-
- $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) : '');
-
- // Fetch data
- //drupal_set_message("DEBUG:query: $sql");
- //drupal_set_message("DEBUG:params: ".implode(', ', $params));
- 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();
-
- // Fetch language for translations
- $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 {
- $form['operations'][$node->nid] = array('#value' => l(t('create translation'), 'node/add/'.$node->type, array(), "translation=$node->nid&language=$language").
- ' | '.l(t('select node'), "node/$node->nid/translation/select/$language", array(), $destination));
- }
- }
- }
- /*
- $form['nodes'] = array('#type' => 'checkboxes', '#options' => $nodes);
- */
- $form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
- return $form;
-}
-
-
-/**
- * Build query for node administration filters based on session.
- */
-function translation_build_filter_query() {
-
- // Build query
- $where = $args = array();
- $join = '';
- // This will produce an empty 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);
-}
-
-/**
- * Returns form for translation administration filters.
- */
-function translation_filter_form($defaults = array()) {
- $session = &$_SESSION['translation_filter'];
- $session = is_array($session) ? $session : $defaults;
-
- // Save defaults for form reset
- $form['_defaults'] = array('#type' => 'value', '#value' => $defaults);
- $form['filters'] = array('#type' => 'fieldset',
- '#title' => t('And translation conditions are'),
- );
- $languages = i18n_supported_languages();
- // Translation and language conditions
-
- $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 (count($session)) {
- $form['filters']['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset'));
- }
- return $form;
-}
-
-function theme_translation_filter_form($form) {
- $form['filters']['source_language']['#prefix'] = '<table><tr><td>';
- $form['filters']['source_status']['#suffix'] = '</td><td>';
- $form['filters']['buttons']['#prefix'] = '</td><td>';
- $form['filters']['buttons']['#suffix'] = '</td></tr></table>';
- return drupal_render($form);
-}
-/**
- * Builds translation admin filters
- */
-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;
- }
-
-}
-
-/**
- * Theme node administration overview.
- */
-function theme_translation_admin_nodes($form) {
- // Overview table:
- $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;
-}
-
-/**
- * Shows overview of current translations plus remove button
- */
-function translation_node_overview($node) {
- $languages = i18n_supported_languages();
- unset($languages[$node->language]);
- // $output = t('<h2>Current translations</h2>');
- $header = array(t('Language'), t('Title'), t('Status'), t('Options'));
- // Special links for product nodes
- $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');
- $options[] = l(t('create translation'), $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);
-}
-
-/**
- * Form to remove node from translation set
- */
-function translation_node_remove($node) {
- $form['submit'] = array('#type' => 'submit', '#value' => t('Remove'), '#suffix' => t('Remove node from this translation set'));
- $form['#action'] = url('node/'.$node->nid.'/translation/remove');
- return $form;
-}
-
-/**
- * Form to select a translation from existing nodes
- */
-function translation_node_select($node, $lang) {
- $languages = i18n_supported_languages();
- // Disable i18n rewrite. Order by trid to show first nodes with no translation
- 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]) );
- }
-}
-
-/**
- * Process translation node form
- */
-function translation_node_form_submit($form_id, $form_values){
- $op = $_POST['op'];
- $source_nid = $form_values['source_nid'];
- $language = $form_values['language'];
- $nid = $form_values['nid'];
- if( $source_nid && $language && $nid ) {
- if($trid = $form_values['trid']){
- // Delete old translations
- 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'));
-
- }
-}
-
-/**
- * Taxonomy hook
- * $edit parameter is an array, not an object !!
- */
- // $op = insert, update, delete
-function translation_taxonomy($op, $type = NULL, $edit = NULL) {
- if (!is_array($op)) {
- switch ("$type/$op") {
- case 'term/insert':
- case 'term/update':
- if (!$edit['language'] && $edit['trid']) {
- // Removed language, remove 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;
- }
- } else {
- return $op;
- }
-}
-/**
- * Implementation of hook_link().
- */
-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) {
- // Add node link if published
- if($trnode->status) {
- $baselang = variable_get('i18n_translation_links', 0) ? i18n_get_lang() : $lang;
- $links['translation-'.$lang]= theme('translation_node_link', $trnode , $lang, $baselang);
- }
- }
- }
- return $links;
-}
-
-/**
- * Returns a list for terms for vocabulary, language
- */
-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;
-}
-
-/**
- * Get translations
- *
- * @param $params
- * array of parameters
- * @param $getall
- * TRUE to get the also node itself
- */
-function translation_node_get_translations($params, $getall = TRUE) {
- foreach($params as $field => $value) {
- $conds[] = "b.$field = '%s'";
- $values[] = $value;
- }
- if(!$getall){ // If not all, a parameter must be nid
- $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;
-}
-
-/**
- * Returns node type for nid
- */
-function translation_get_node_type($nid) {
- return db_result(db_query('SELECT type FROM {node} WHERE nid=%d', $nid));
-}
-
-/**
- * Multilingual Taxonomy
- *
- */
-
-/**
- * This is the callback for taxonomy translations
- *
- * Gets the urls:
- * admin/taxonomy/i18n/term/xx
- * admin/taxonomy/i18n/term/new/xx
- * admin/taxonomy/vid/translation/op/trid
- */
-
-function translation_taxonomy_admin() {
- $vid = arg(3);
- $op = $_POST['op'] ? $_POST['op'] : arg(5);
- $edit = $_POST['edit'];
-
- switch ($op) {
- case t('Save'):
- case 'edit':
- drupal_set_title(t('Edit term translations'));
- $output = translation_taxonomy_form($vid, arg(6), $edit);
- break;
- case t('Submit'):
- drupal_set_title(t('Submit'));
- translation_taxonomy_term_save($edit);
- $output = translation_taxonomy_overview($vid);
- break;
- case 'delete':
- //print theme('page', node_delete($edit), t('Delete'));
- break;
- default:
- $output = translation_taxonomy_overview($vid);
- }
- return $output;
-}
-
-/**
- * Generate a tabular listing of translations for vocabularies.
- */
-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();
- // Get terms/translations for this vocab
- $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;
- }
- }
- // Reorder data for rows and languages
- foreach ($terms as $trid => $terms) {
- $thisrow = array();
- foreach ($languages as $lang => $name) {
- if (array_key_exists($lang, $terms)) {
- $thisrow[] = $terms[$lang]->name;
- }
- 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/edit/new");
- return $output;
-}
-
-/**
- * Produces a vocabulary translation form
- */
-function translation_taxonomy_form($vid, $trid = NULL, $edit = array()) {
- $languages = i18n_supported_languages();
- if ($trid == 'new') {
- $translations = array();
- } else {
- $form['trid'] = array('#type' => 'hidden', '#value' => $trid);
- $translations = translation_term_get_translations(array('trid' =>$trid));
- }
- //var_dump($translations);
- $vocabulary = taxonomy_get_vocabulary($vid);
-
- // List of terms for languages
- 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'));
- return drupal_get_form('translation_taxonomy', $form);
-}
-
-/**
- * Process vocabulary translation form
- */
-function translation_taxonomy_submit($form_id, $form_values) {
- $trid = $form_values['trid'];
- $languages = i18n_supported_languages();
- $translations = array();
- // Delete old translations
- if($trid){
- db_query("UPDATE {term_data} SET trid = 0 WHERE trid=%d", $trid);
- }
- foreach ($languages as $lang => $name) {
- if (is_numeric($form_values[$lang]['tid'])) {
- $translations[$lang] = $form_values[$lang]['tid'];
- }
- }
- if(count($translations)) {
- $trid = is_numeric($trid) ? $trid : db_next_id('{term_data}_trid');
- db_query('UPDATE {term_data} SET trid=%d WHERE tid IN(%s)', $trid, implode(',',$translations));
- }
- drupal_set_message(t('Term translations have been updated'));
-}
-
-/**
- * Converts a list of arrays to an array of the form keyfield => namefield
- */
-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;
-}
-
-/**
- * Get term translations
- *
- * @return
- * An array of the from lang => Term
- */
-function translation_term_get_translations($params, $getall = TRUE) {
- foreach($params as $field => $value) {
- $conds[] = "i.$field = '%s'";
- $values[] = $value;
- }
- if(!$getall){ // If not all, a parameter must be tid
- $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;
-}
-
-/**
- * Produces url of translated page
- */
-function translation_url($url, $lang) {
- global $i18n_langpath;
- // If !url get from original request
- if (!$url) {
- $url = _i18n_get_original_path();
- }
- // If url has lang_prefix, remove it
- i18n_get_lang_prefix($url, true);
- // are we looking at a node?
- if (preg_match("/^(node\/)([0-9]*)$/",$url,$matches)) {
- if ($nid = translation_node_nid($matches[2], $lang)) {
- $url = "node/$nid";
- }
- }
- // or a taxonomy term
- elseif (preg_match("/^(taxonomy\/term\/)([^\/]*)$/",$url,$matches)) {//or at a taxonomy-listing?
- if ($str_tids = translation_taxonomy_tids($matches[2], $lang)) {
- $url = "taxonomy/term/$str_tids";
- }
- }
-
- return $url;
-}
-
-/**
- * Returns an url-part, pointing to the translated node, if exists
- */
-function translation_node_nid($nid, $lang) {
- $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';
- return db_result(db_query($sql, $nid, $nid, $lang));
-}
-
-/**
- * Returns an url for the translated taxonomy-page, if exists
- */
-function translation_taxonomy_tids($str_tids, $lang) {
- if (preg_match('/^([0-9]+[+ ])+[0-9]+$/', $str_tids)) {
- $separator = '+';
- // The '+' character in a query string may be parsed as ' '.
- $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_get_translations(array('tid' =>$tid))) {
- $translated_tids[] = $translated_tid[$lang]->tid;
- }
- }
- return implode($separator, $translated_tids);
-}
-
-/**
- * function translation_get_links
- *
- * Returns an array of links for all languages, with or without names
- */
-function translation_get_links($path = '', $query = NULL) {
- $current = i18n_get_lang();
- foreach(i18n_supported_languages() as $lang => $name){
- $url = translation_url($path, $lang);
- $links[]= theme('i18n_link', $name, i18n_path($url, $lang) , $lang, $query);
- }
- return $links;
-}
-
-/**
- * Return status for translations workflow
- */
-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)'));
-}
-
-/**
- * Theme a link to node translation
- *
- * Since Drupal 5, returns array instead of html
- */
-function theme_translation_node_link($node, $lang, $baselang = NULL, $title = FALSE){
- $baselang = $baselang ? $baselang : $lang;
-
- if($title){
- $name = $node->title;
- } else {
- $languages = i18n_supported_languages();
- $name = $languages[$lang];
- }
- return array(
- 'title' => $name,
- 'href' => i18n_path('node/'.$node->nid, $baselang)
- );
-}
-
-/**
- * Theme a link for a translation
- */
-function theme_translation_link($text, $target, $lang, $separator='&nbsp;') {
- return theme('i18n_link', $text, $target, $lang, $separator);
-}
-
-/**
- * Theme list of node translations
- */
-function theme_translation_node_list($list){
- $header = array(t('Language'), t('Title'));
- $languages = i18n_supported_languages();
- foreach($list as $lang => $node){
- $rows[] = array($languages[$lang], l($node->title, 'node/'.$node->nid) );
- }
- return theme('table', $header, $rows);
-}