first import

This commit is contained in:
Bachir Soussi Chiadmi
2015-04-08 11:40:19 +02:00
commit 1bc61b12ad
8435 changed files with 1582817 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
README.txt
==========
Drupal module: Path translation
==================================
This module provides some basic path translation feature for generic paths.
For paths belonging to objects that have translations, like nodes and taxonomy terms, the system can produce automatic
links for the language switcher.
For the rest of paths, this module allows to define which path is translation of which. Example:
1. We define a new 'path translation set' like
- English: node/1
- Spanish: taxonomy/term/3
2. Every time we are on any of these pages, the language switcher will point to the other path for each language.
This module is intended for translation of generic paths that don't have other way of being translated.
Note: path translations must be defined without aliases.
====================================================================
Jose A. Reyero, http://reyero.net

View File

@@ -0,0 +1,150 @@
<?php
/**
* @file
* Administration pages for path translation.
*/
/**
* Path overview page
*/
function i18n_path_admin_overview($type = NULL) {
module_load_include('admin.inc', 'i18n_translation');
return i18n_translation_admin_overview('path');
}
/**
* Path add/edit form
*/
function i18n_path_admin_form($form, $form_state, $translation_set = NULL) {
$form['translation_set'] = array('#type' => 'value', '#value' => $translation_set);
if ($translation_set) {
$paths = $translation_set->get_translations();
}
else {
$paths = array();
}
$form['title'] = array(
'#title' => t('Title'),
'#type' => 'textfield',
'#default_value' => $translation_set ? $translation_set->title : '',
'#description' => t('Optional descriptive name for this set.'),
);
$form['translations'] = array(
'#type' => 'fieldset',
'#title' => t('Translations'),
'#tree' => TRUE,
'#description' => t('The path for this menu link. This can be an internal Drupal path such as %add-node or an external URL such as %drupal. Enter %front to link to the front page.', array('%front' => '<front>', '%add-node' => 'node/add', '%drupal' => 'http://drupal.org')),
);
foreach (i18n_language_list() as $langcode => $name) {
$form['translations'][$langcode] = array(
'#type' => 'textfield',
'#title' => check_plain($name),
'#default_value' => !empty($paths[$langcode]) ? $paths[$langcode]->path : '',
);
}
$form['controls']['update'] = array(
'#type' => 'submit',
'#value' => t('Save'),
'#name' => 'save',
);
if ($translation_set) {
$form['controls']['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete'),
'#name' => 'delete',
);
}
return $form;
}
/**
* Process form validation
*/
function i18n_path_admin_form_validate($form, &$form_state) {
if ($form_state['triggering_element']['#name'] == 'save') {
$paths = &$form_state['values']['translations'];
if ($paths = array_filter($paths)) {
module_load_include('inc', 'menu', 'menu.admin');
foreach ($paths as $language => &$link_path) {
$link_path = i18n_prepare_normal_path($link_path, $language);
$validation_form_state = array(
'values' => array(
'link_path' => $link_path,
),
);
menu_edit_item_validate(array(), $validation_form_state);
}
}
else {
form_set_error('paths', t('There are no path translations to save.'));
}
}
}
/**
* Process form submission
*/
function i18n_path_admin_form_submit($form, &$form_state) {
$translation_set = $form_state['values']['translation_set'];
switch ($form_state['triggering_element']['#name']) {
case 'save':
$paths = array_filter($form_state['values']['translations']);
$translation_set = $translation_set ? $translation_set : i18n_translation_set_create('path');
$translation_set->title = '';
$translations = $translation_set->get_translations();
foreach ($paths as $lang => $path) {
if (isset($translations[$lang])) {
$translations[$lang]->path = $path;
}
else {
$translation_set->add_item($path, $lang);
}
}
foreach (array_diff(array_keys($translation_set->get_translations()), array_keys($paths)) as $language) {
$translation_set->remove_language($language);
unset($translations[$language]);
}
if (!empty($form_state['values']['title'])) {
$translation_set->title = $form_state['values']['title'];
}
$translation_set->save(TRUE);
drupal_set_message(t('The path translation has been saved.'));
break;
case 'delete':
$destination = array();
if (isset($_GET['destination'])) {
$destination = drupal_get_destination();
unset($_GET['destination']);
}
$form_state['redirect'] = array($translation_set->get_delete_path(), array('query' => $destination));
return;
}
$form_state['redirect'] = 'admin/config/regional/i18n_translation/path';
}
/**
* Save path translation set.
*/
function i18n_path_save_translations($paths, $tpid = NULL) {
$paths = array_filter($paths);
if (lock_acquire('i18n_path')) {
if ($tpid) {
db_delete('i18n_path')->condition('tpid', $tpid)->execute();
}
else {
$tpid = 1 + (int)db_query('SELECT MAX(tpid) FROM {i18n_path}')->fetchField();
}
foreach ($paths as $langcode => $path) {
db_insert('i18n_path')
->fields(array('tpid' => $tpid, 'language' => $langcode, 'path' => $path))
->execute();
}
lock_release('i18n_path');
return $tpid;
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* @file
* Internationalization (i18n) module - Translation set
*/
class i18n_path_translation_set extends i18n_translation_set {
/**
* Add translation item
*/
public function add_item($path, $langcode = NULL) {
// Path may be object or plain string
$item = is_object($path) ? $path : (object)array('path' => $path, 'language' => $langcode);
return parent::add_item($item, $langcode);
}
/**
* Clean path translations.
*
* Unlike other translation sets this actually deletes paths
*/
public function clean_translations() {
$delete = db_delete('i18n_path')
->condition('tsid', $this->tsid)
->condition('language', array_keys($this->get_translations()), 'NOT IN')
->execute();
}
/**
* Delete translation set
*/
public function delete_translations() {
return db_delete('i18n_path')
->condition('tsid', $this->tsid)
->execute();
}
/**
* Save all path translations
*/
public function save_translations() {
foreach ($this->get_translations() as $lang => $path) {
$path = is_object($path) ? $path : (object) array('path' => $path, 'language' => $lang, 'tsid' => $this->tsid);
drupal_write_record('i18n_path', $path, !empty($path->tpid) ? 'tpid' : array());
$this->add_item($path, $lang);
}
}
}
/**
* Path object
*/
class i18n_path_object extends i18n_object_wrapper {
/**
* Get title from item
*/
public function get_title() {
return $this->object->path;
}
/**
* Get path for item
*/
public function get_path() {
return check_url($this->object->path);
}
/**
* Get translate mode
*/
public function get_translate_mode() {
return I18N_MODE_TRANSLATE;
}
}

View File

@@ -0,0 +1,14 @@
name = Path translation
description = Define translations for generic paths
dependencies[] = i18n_translation
package = Multilingual - Internationalization
core = 7.x
files[] = i18n_path.inc
files[] = i18n_path.test
; Information added by drupal.org packaging script on 2013-01-13
version = "7.x-1.8"
core = "7.x"
project = "i18n"
datestamp = "1358075001"

View File

@@ -0,0 +1,92 @@
<?php
/**
* @file
* Install, update and uninstall functions for the text module.
*/
/**
* Implements hook_install().
*/
function i18n_path_install() {
// Set module weight for it to run after core modules, but before views.
db_update('system')
->fields(array('weight' => 5))
->condition('name', 'i18n_path', '=')
->condition('type', 'module', '=')
->execute();
}
/**
* Implements hook_schema().
*/
function i18n_path_schema() {
$schema['i18n_path'] = array(
'description' => 'Path translation',
'fields' => array(
'tpid' => array(
'description' => 'The primary identifier for a path in the translation set.',
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
),
'tsid' => array(
'description' => 'The primary identifier for a translation set.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
),
'path' => array(
'description' => 'The Drupal path this alias is for; e.g. node/12.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'language' => array(
'description' => "The language for which this path is a translation.",
'type' => 'varchar',
'length' => 12,
'not null' => TRUE,
'default' => '',
),
'pid' => array(
'description' => 'A unique path alias identifier if the path has an alias.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
),
'indexes' => array(
'path' => array('path'),
),
'unique keys' => array(
'set_language' => array('tsid', 'language'),
),
'foreign keys' => array(
'path_language' => array(
'table' => 'languages',
'columns' => array('language' => 'language'),
),
'translation_set' => array(
'table' => 'i18n_translation',
'columns' => array('tsid' => 'tsid'),
),
),
'primary key' => array('tpid'),
);
return $schema;
}
/**
* Set module weight.
*/
function i18n_path_update_7000(&$sandbox) {
// Set module weight for it to run after core modules, but before views.
db_update('system')
->fields(array('weight' => 5))
->condition('name', 'i18n_path', '=')
->condition('type', 'module', '=')
->execute();
}

View File

@@ -0,0 +1,141 @@
<?php
/**
* @file
* Internationalization (i18n) module - Path translation
*/
/**
* Implements hook_menu()
*/
function i18n_path_menu() {
$items['admin/config/regional/i18n_translation/path'] = array(
'title' => 'Paths',
'description' => 'Path translation.',
'page callback' => 'i18n_path_admin_overview',
'access arguments' => array('administer site configuration'),
'file' => 'i18n_path.admin.inc',
'type' => MENU_LOCAL_TASK,
'weight' => 10,
);
$items['admin/config/regional/i18n_translation/path/list'] = array(
'title' => 'Paths',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/config/regional/i18n_translation/path/add'] = array(
'title' => 'Add path translation',
'page callback' => 'drupal_get_form',
'page arguments' => array('i18n_path_admin_form'),
'access arguments' => array('administer site configuration'),
'file' => 'i18n_path.admin.inc',
'type' => MENU_LOCAL_ACTION,
'parent' => 'admin/config/regional/i18n_translation',
);
$items['admin/config/regional/i18n_translation/path/edit/%i18n_path_translation_set'] = array(
'title' => 'Edit path translation',
'page callback' => 'drupal_get_form',
'page arguments' => array('i18n_path_admin_form', 6),
'access arguments' => array('administer site configuration'),
'file' => 'i18n_path.admin.inc',
'type' => MENU_LOCAL_TASK,
'context' => MENU_CONTEXT_INLINE,
);
$items['admin/config/regional/i18n_translation/path/delete/%i18n_path_translation_set'] = array(
'title' => 'Delete path translation',
'page callback' => 'drupal_get_form',
'page arguments' => array('i18n_translation_set_delete_confirm', 6),
'access arguments' => array('administer site configuration'),
'file' => 'i18n_path.admin.inc',
'type' => MENU_LOCAL_TASK,
'context' => MENU_CONTEXT_INLINE,
);
return $items;
}
/**
* Implements hook_url_outbound_alter()
*/
/*
function i18n_path_url_outbound_alter(&$path, &$options, $original_path) {
if (!empty($options['language'])) {
$langcode = $options['language']->language;
$original = $options['alias'] ? drupal_get_normal_path($path, $langcode) : $original_path;
if (($translations = i18n_path_get_translations($path)) && !empty($translations[$langcode])) {
$path = $options['alias'] ? drupal_get_path_alias($translations[$langcode], $langcode) : $translations[$langcode];
}
}
}
*/
/**
* Get translations for path
*/
function i18n_path_get_translations($path) {
static $translations;
if (!isset($translations)) {
$translations = drupal_static(__FUNCTION__, array());
}
if (!isset($translations[$path])) {
$translations[$path] = db_query('SELECT p.language, p.path FROM {i18n_path} p INNER JOIN {i18n_path} ps ON p.tsid = ps.tsid WHERE ps.path = :path',
array(':path' => $path)
)->fetchAllKeyed();
}
return $translations[$path];
}
/**
* Implements hook_i18n_object_info().
*/
function i18n_path_i18n_object_info() {
return array(
'path' => array(
'title' => t('Path'),
'class' => 'i18n_path_object',
'key' => array('path', 'language'),
'translation set' => TRUE,
)
);
}
/**
* Implements hook_i18n_translation_set_info()
*/
function i18n_path_i18n_translation_set_info() {
return array(
'path' => array(
'title' => t('Path'),
'class' => 'i18n_path_translation_set',
'table' => 'i18n_path',
'field' => 'tsid',
'placeholder' => '%i18n_path_translation_set',
'edit path' => 'admin/config/regional/i18n_translation/path/edit/%i18n_path_translation_set',
'delete path' => 'admin/config/regional/i18n_translation/path/delete/%i18n_path_translation_set',
'list path' => 'admin/config/regional/i18n_translation/path',
),
);
}
/**
* Implements hook_i18n_translate_path()
*/
function i18n_path_i18n_translate_path($path) {
if ($translations = i18n_path_get_translations($path)) {
$result = array();
foreach ($translations as $langcode => $translated) {
$result[$langcode] = array(
'href' => $translated,
);
}
return $result;
}
}
/**
* Load translation set. Menu loading callback.
*/
function i18n_path_translation_set_load($tsid) {
return i18n_translation_set_load($tsid, 'path');
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* @file
* Test case for multilingual menus.
*/
class i18nPathTestCase extends Drupali18nTestCase {
public static function getInfo() {
return array(
'name' => 'Path translation',
'group' => 'Internationalization',
'description' => 'Path translation functions',
);
}
function setUp() {
parent::setUp('translation', 'i18n_path');
parent::setUpLanguages(array('administer site configuration'));
}
function checkTranslationLink($path, $language, $method = 'assertRaw') {
$this->{$method}($path, t('Found translation link. :language - :path', array(':language' => $language, ':path' => $path)));
}
function testPathTranslation() {
$this->setUpContentType(array('type' => 'page', 'mode' => TRANSLATION_ENABLED));
// Create 2 nodes in different languages.
$first_title = $this->randomName(10);
$first_body = $this->randomString(50);
$first_node = $this->createNode('page', $first_title, $first_body, $this->default_language);
$secondary_title = $this->randomName(10);
$secondary_body = $this->randomString(50);
$secondary_node = $this->createNode('page', $secondary_title, $secondary_body, $this->secondary_language);
$this->drupalGet('node/' . $first_node->nid);
$this->checkTranslationLink('node/' . $first_node->nid, $first_node->language);
$this->checkTranslationLink($this->secondary_language . '/node/' . $first_node->nid, $this->secondary_language, 'assertNoRaw');
$this->drupalGet('node/' . $secondary_node->nid);
$this->checkTranslationLink('node/' . $secondary_node->nid, $secondary_node->language);
$this->checkTranslationLink($this->secondary_language . '/node/' . $secondary_node->nid, $this->secondary_language);
$this->drupalGet('admin/config/regional/i18n_translation/path');
$this->clickLink(t('Add path translation'));
// create new translation set with two node links
$edit = array(
'title' => $this->randomName(10),
'translations[' . $this->default_language . ']' => 'node/' . $first_node->nid,
'translations[' . $this->secondary_language . ']' => 'node/' . $secondary_node->nid,
);
$this->drupalPost('admin/config/regional/i18n_translation/path/add', $edit, t('Save'));
$this->drupalGet('node/' . $first_node->nid);
$this->checkTranslationLink('node/' . $first_node->nid, $first_node->language);
$this->checkTranslationLink($this->secondary_language . '/node/' . $secondary_node->nid, $this->secondary_language);
$this->drupalGet('node/' . $secondary_node->nid);
$this->checkTranslationLink('node/' . $first_node->nid, $first_node->language);
$this->checkTranslationLink('node/' . $secondary_node->nid, $this->secondary_language);
// create new translation set with one node and one menu "token"
$edit = array(
'translations[' . $this->default_language . ']' => 'node/' . $first_node->nid,
'translations[' . $this->secondary_language . ']' => '<front>',
);
$this->drupalPost('admin/config/regional/i18n_translation/path/edit/1', $edit, t('Save'));
$this->drupalGet('node/' . $first_node->nid);
$this->checkTranslationLink('node/' . $first_node->nid, $first_node->language);
$this->checkTranslationLink('node/' . $secondary_node->nid, $this->secondary_language, 'assertNoLinkByHref');
$this->checkTranslationLink($this->secondary_language, $this->secondary_language);
// create new translation set with one node and an external menu link.
$url = 'http://' . $this->randomName(10) . '.' . $this->randomName(2);
$edit = array(
'translations[' . $this->default_language . ']' => 'node/' . $first_node->nid,
'translations[' . $this->secondary_language . ']' => $url,
);
$this->drupalPost('admin/config/regional/i18n_translation/path/edit/1', $edit, t('Save'));
$this->drupalGet('node/' . $first_node->nid);
$this->checkTranslationLink('node/' . $first_node->nid, $first_node->language);
$this->checkTranslationLink($url, $this->secondary_language);
}
}