first import
This commit is contained in:
47
sites/all/modules/i18n/i18n_translation/README.txt
Normal file
47
sites/all/modules/i18n/i18n_translation/README.txt
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
README.txt
|
||||
==========
|
||||
Drupal module: Translation set API
|
||||
==================================
|
||||
|
||||
This is a generic API to handle translation sets. It is being used for now
|
||||
for path translation and taxonomy term translation inside i18n package.
|
||||
|
||||
Translation sets can hold a collection of entities or other objects. A translation set is itself
|
||||
an Entity thus leveraging all the power of the Entity API.
|
||||
|
||||
It also provides some basic storage for translation sets and a generator of new translation set id.
|
||||
However, each module is responsible for storing which objects belong to which translation set for which
|
||||
it needs to verride some methods of the base i18n_translation_set class.
|
||||
|
||||
- load_translations()
|
||||
- save_translations()
|
||||
- clean_translations()
|
||||
- delete_translations()
|
||||
|
||||
Once these are implemented, to get the objects belonging to a translation set, indexed by language code,
|
||||
you can invoke this method on a translation set object:
|
||||
|
||||
- get_translations()
|
||||
|
||||
To define a new type of translation set, a module must implement hook_i18n_translation_set_info()
|
||||
as in this example:
|
||||
|
||||
/**
|
||||
* Implements hook_i18n_translation_set_info().
|
||||
*/
|
||||
function i18n_path_i18n_translation_set_info() {
|
||||
return array(
|
||||
'path' => array(
|
||||
'title' => t('Paths'),
|
||||
'class' => 'i18n_path_translation_set',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
See examples of overriding and extending this API:
|
||||
- i18n_path/i18n_path.inc
|
||||
- i18n_taxonomy/i18n_taxonomy.inc
|
||||
|
||||
====================================================================
|
||||
Jose A. Reyero, http://reyero.net
|
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Internationalization (i18n) module. Translation sets admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Overview page for translation sets
|
||||
*
|
||||
* @param $type
|
||||
* Translation set type to get a listing for this type only
|
||||
* @param $query
|
||||
* Base query to build upon
|
||||
*/
|
||||
function i18n_translation_admin_overview($type = NULL, $query = NULL) {
|
||||
// Build the sortable table header.
|
||||
$header['title'] = array('data' => t('Title'), 'field' => 't.title');
|
||||
if (!$type) {
|
||||
$header['type'] = array('data' => t('Type'), 'field' => 't.type');
|
||||
}
|
||||
$header['items'] = t('Items');
|
||||
$header['created'] = array('data' => t('Created'), 'field' => 't.created');
|
||||
$header['changed'] = array('data' => t('Updated'), 'field' => 't.changed', 'sort' => 'desc');
|
||||
$header['operations'] = array('data' => t('Operations'));
|
||||
|
||||
// Get the translation sets for this form
|
||||
$query = $query ? $query : db_select('i18n_translation_set', 't');
|
||||
$query = $query->extend('PagerDefault')->extend('TableSort');
|
||||
if ($type) {
|
||||
$query->condition('t.type', $type);
|
||||
}
|
||||
$tsids = $query
|
||||
->fields('t', array('tsid'))
|
||||
->limit(20)
|
||||
->orderByHeader($header)
|
||||
->execute()
|
||||
->fetchCol();
|
||||
$translations = $tsids ? entity_load('i18n_translation', $tsids) : array();
|
||||
|
||||
$form = drupal_get_form('i18n_translation_admin_form', $translations, $header);
|
||||
|
||||
$form['pager'] = array('#markup' => theme('pager'));
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin form
|
||||
*/
|
||||
function i18n_translation_admin_form($form, &$form_state, $translations, $header) {
|
||||
$destination = drupal_get_destination();
|
||||
$rows = array();
|
||||
foreach ($translations as $set) {
|
||||
$info = i18n_object_info($set->type);
|
||||
$rows[$set->tsid]['title'] = check_plain($set->get_title());
|
||||
if (isset($header['type'])) {
|
||||
$rows[$set->tsid]['type'] = isset($info['title']) ? $info['title'] : t('Unknown');
|
||||
}
|
||||
$rows[$set->tsid]['items'] = ($items = $set->get_links()) ? theme('links', array('links' => $items)) : '';
|
||||
$rows[$set->tsid] += array(
|
||||
'created' => format_date($set->created, 'short'),
|
||||
'changed' => format_date($set->changed, 'short'),
|
||||
'operations' => '',
|
||||
);
|
||||
|
||||
// Build a list of all the accessible operations for the current set.
|
||||
$operations = $set->get_operations();
|
||||
if (count($operations) > 1) {
|
||||
// Render an unordered list of operations links.
|
||||
$rows[$set->tsid]['operations'] = array(
|
||||
'data' => array(
|
||||
'#theme' => 'links__node_operations',
|
||||
'#links' => $operations,
|
||||
'#attributes' => array('class' => array('links', 'inline')),
|
||||
),
|
||||
);
|
||||
}
|
||||
elseif (!empty($operations)) {
|
||||
// Render the first and only operation as a link.
|
||||
$link = reset($operations);
|
||||
$rows[$set->tsid]['operations'] = array(
|
||||
'data' => array(
|
||||
'#type' => 'link',
|
||||
'#title' => $link['title'],
|
||||
'#href' => $link['href'],
|
||||
'#options' => array('query' => $link['query']),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
$form['translations'] = array(
|
||||
'#theme' => 'table',
|
||||
'#header' => $header,
|
||||
'#rows' => $rows,
|
||||
'#empty' => t('No translation sets available.'),
|
||||
);
|
||||
return $form;
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* API documentation for Internationalization module
|
||||
*
|
||||
* Most i18n hooks can be placed on each module.i18n.inc file but in this case
|
||||
* such file must be listed in the module.info file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provide information about translation sets and involved objects.
|
||||
*
|
||||
* @see i18n_translation_set_info()
|
||||
*
|
||||
* @see hook_i18n_object_info()
|
||||
*
|
||||
* This feature relies on object information provided by i18n_object_info().
|
||||
*/
|
||||
function hook_i18n_translation_set_info() {
|
||||
$info['taxonomy_term'] = array(
|
||||
'title' => t('Taxonomy term'),
|
||||
// The class that handles this translation sets
|
||||
'class' => 'i18n_taxonomy_translation_set',
|
||||
// Table and field into that table that keeps the translation set id for each item.
|
||||
'table' => 'taxonomy_term_data',
|
||||
'field' => 'i18n_tsid',
|
||||
// This is the parent object (i18n object type).
|
||||
'parent' => 'taxonomy_vocabulary',
|
||||
// Placeholders and path information for generating translation set pages for administration.
|
||||
'placeholder' => '%i18n_taxonomy_translation_set',
|
||||
'list path' => 'admin/structure/taxonomy/%taxonomy_vocabulary_machine_name/list/sets',
|
||||
'edit path' => 'admin/structure/taxonomy/%taxonomy_vocabulary_machine_name/list/sets/edit/%i18n_taxonomy_translation_set',
|
||||
'delete path' => 'admin/structure/taxonomy/%taxonomy_vocabulary_machine_name/list/sets/delete/%i18n_taxonomy_translation_set',
|
||||
'page callback' => 'i18n_taxonomy_term_translation_page',
|
||||
);
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter i18n object information provided by modules with the previous hook
|
||||
*
|
||||
* @see i18n_translation_set_info()
|
||||
*/
|
||||
function hook_i18n_translation_set_info_alter(&$info) {
|
||||
}
|
474
sites/all/modules/i18n/i18n_translation/i18n_translation.inc
Normal file
474
sites/all/modules/i18n/i18n_translation/i18n_translation.inc
Normal file
@@ -0,0 +1,474 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Internationalization (i18n) module - Translation set
|
||||
*/
|
||||
class i18n_translation_set {
|
||||
public $tsid = NULL;
|
||||
public $type;
|
||||
public $bundle = '';
|
||||
public $status = 0;
|
||||
public $master_id = 0;
|
||||
// It may optionally have a title
|
||||
public $title = '';
|
||||
// Translations indexed by language
|
||||
protected $translations = NULL;
|
||||
// Translation languages indexed by oid
|
||||
protected $object_languages = array();
|
||||
// Related translation sets indexed by tsid
|
||||
// Keep track of old translation sets objects belong to.
|
||||
protected $related_translations = array();
|
||||
/**
|
||||
* Constructor from object/array
|
||||
*/
|
||||
public function __construct($translation = NULL) {
|
||||
if ($translation) {
|
||||
foreach ((array)$translation as $key => $value) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a translation set
|
||||
*
|
||||
* @param $delete_translations
|
||||
* Whether to unlink translations from the set. Detaults to TRUE.
|
||||
*/
|
||||
public function delete($delete_translations = TRUE) {
|
||||
db_delete('i18n_translation_set')
|
||||
->condition('tsid', $this->tsid)
|
||||
->execute();
|
||||
if ($delete_translations) {
|
||||
$this->delete_translations();
|
||||
}
|
||||
$this->invoke_all('delete');
|
||||
$this->tsid = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke all modules
|
||||
*/
|
||||
public function invoke_all($op) {
|
||||
module_invoke_all('i18n_translation_set_' . $op, $this);
|
||||
module_invoke_all('entity_' . $op, $this, 'i18n_translation');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new translation set
|
||||
*
|
||||
* @param $save_translations
|
||||
* Whether to update linked objects so they belong to this set.
|
||||
*/
|
||||
public function insert($save_translations = TRUE) {
|
||||
$this->created = $this->changed = REQUEST_TIME;
|
||||
$status = drupal_write_record('i18n_translation_set', $this);
|
||||
if ($save_translations) {
|
||||
$this->save_translations();
|
||||
$this->update_related();
|
||||
}
|
||||
$this->invoke_all('insert');
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save translation set
|
||||
*
|
||||
* @param $save_translations
|
||||
* Whether to update linked objects so they belong to this set.
|
||||
*/
|
||||
public function save($save_translations = TRUE) {
|
||||
$this->invoke_all('presave');
|
||||
return empty($this->tsid) ? $this->insert($save_translations) : $this->update($save_translations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a translation set
|
||||
*
|
||||
* @param $update_translations
|
||||
* Whether to update objects linked to this set.
|
||||
*/
|
||||
public function update($update_translations = TRUE) {
|
||||
$this->changed = REQUEST_TIME;
|
||||
$status = drupal_write_record('i18n_translation_set', $this, 'tsid');
|
||||
if ($update_translations) {
|
||||
$this->clean_translations();
|
||||
$this->save_translations();
|
||||
$this->update_related();
|
||||
}
|
||||
$this->invoke_all('update');
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a translation set or delete if empty.
|
||||
*/
|
||||
public function update_delete() {
|
||||
if ($this->get_translations()) {
|
||||
$result = $this->save(TRUE);
|
||||
// Update related translation sets too.
|
||||
$this->update_related();
|
||||
return $result;
|
||||
}
|
||||
else {
|
||||
return $this->delete(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update related translation sets
|
||||
*/
|
||||
protected function update_related($op = 'update_delete') {
|
||||
foreach ($this->related_translations as $translation_set) {
|
||||
$translation_set->$op();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean all items in this translation set
|
||||
*
|
||||
* Unlink other items (not current translations from this translation set)
|
||||
*/
|
||||
public function clean_translations() {
|
||||
if (($table = $this->get_table()) && ($field = $this->get_field())) {
|
||||
$query = db_update($table)
|
||||
->fields(array($field => 0))
|
||||
->condition($field, $this->tsid);
|
||||
if ($translations = $this->get_translations()) {
|
||||
$query->condition('language', array_keys($translations), 'NOT IN');
|
||||
}
|
||||
return $query->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save translations in this translation set
|
||||
*/
|
||||
public function save_translations() {
|
||||
if (($table = $this->get_table()) && ($field = $this->get_field())) {
|
||||
if ($keys = $this->get_translations_keys()) {
|
||||
return db_update($table)
|
||||
->fields(array($field => $this->tsid))
|
||||
->condition($this->key_field(), $keys)
|
||||
->execute();
|
||||
}
|
||||
else {
|
||||
return $this->delete_translations();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete translations in this translation set
|
||||
*
|
||||
* It won't delete objects, just unlink them from translation set
|
||||
*/
|
||||
public function delete_translations() {
|
||||
if (($table = $this->get_table()) && ($field = $this->get_field())) {
|
||||
return db_update($table)
|
||||
->fields(array($field => 0))
|
||||
->condition($field, $this->tsid)
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translations, indexed by language
|
||||
*/
|
||||
public function get_translations() {
|
||||
$translations = array();
|
||||
foreach ($this->get_objects() as $lang => $object) {
|
||||
$translations[$lang] = $object->get_object();
|
||||
}
|
||||
return $translations;
|
||||
}
|
||||
/**
|
||||
* Reset translations, set empty array or new array of translations.
|
||||
*
|
||||
* @param $translations array
|
||||
* Array of langcode => item
|
||||
*/
|
||||
public function reset_translations($translations = array()) {
|
||||
$this->translations = array();
|
||||
$this->add_translations($translations);
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Get translations as i18n objects, indexed by language
|
||||
*/
|
||||
public function get_objects() {
|
||||
if (!isset($this->translations)) {
|
||||
$this->translations = array();
|
||||
// Disable selection query altering, just in case
|
||||
$previous = i18n_select(FALSE);
|
||||
$this->add_translations($this->load_translations());
|
||||
i18n_select($previous);
|
||||
}
|
||||
return $this->translations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item for language
|
||||
*/
|
||||
public function get_item($langcode) {
|
||||
if (($translations = $this->get_translations()) && isset($translations[$langcode])) {
|
||||
return $translations[$langcode];
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get translations keys, indexed by language
|
||||
*/
|
||||
public function get_translations_keys() {
|
||||
$keys = array();
|
||||
foreach ($this->get_objects() as $lang => $object) {
|
||||
if ($id = $object->get_key()) {
|
||||
$keys[$lang] = $id;
|
||||
}
|
||||
}
|
||||
return array_filter($keys);
|
||||
}
|
||||
/**
|
||||
* Get edit path for this translation set
|
||||
*/
|
||||
public function get_edit_path() {
|
||||
if ($path = $this->get_info('edit path')) {
|
||||
return strtr($path, $this->get_path_placeholders('delete'));
|
||||
}
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get operations as renderable links
|
||||
*/
|
||||
public function get_operations() {
|
||||
$destination = drupal_get_destination();
|
||||
$operations = array();
|
||||
if ($path = $this->get_edit_path()) {
|
||||
$operations['edit'] = array(
|
||||
'title' => t('edit'),
|
||||
'href' => $path,
|
||||
'query' => $destination,
|
||||
);
|
||||
}
|
||||
if ($path = $this->get_delete_path()) {
|
||||
$operations['delete'] = array(
|
||||
'title' => t('delete'),
|
||||
'href' => $path,
|
||||
'query' => $destination,
|
||||
);
|
||||
}
|
||||
return $operations;
|
||||
}
|
||||
/**
|
||||
* Get items as renderable links
|
||||
*/
|
||||
public function get_links() {
|
||||
$language_list = language_list();
|
||||
$items = array();
|
||||
foreach ($this->get_objects() as $langcode => $object) {
|
||||
$title = $object->get_title();
|
||||
$path = $object->get_path();
|
||||
$language = isset($language_list[$langcode]) ? $language_list[$langcode] : NULL;
|
||||
$items[$langcode] = array(
|
||||
'title' => $title,
|
||||
'href' => $path ? $path : NULL,
|
||||
'language' => $language,
|
||||
);
|
||||
if ($language && function_exists('languageicons_link_add')) {
|
||||
languageicons_link_add($items[$langcode]);
|
||||
}
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
/**
|
||||
* Get overview (list) path for this translation set
|
||||
*/
|
||||
public function get_list_path() {
|
||||
return $this->get_info('list path');
|
||||
}
|
||||
/**
|
||||
* Get delete path for this translation set
|
||||
*/
|
||||
public function get_delete_path() {
|
||||
if ($path = $this->get_info('delete path')) {
|
||||
return strtr($path, $this->get_path_placeholders('delete'));
|
||||
}
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get placeholder values for path replacement
|
||||
*/
|
||||
function get_path_placeholders($op = 'list') {
|
||||
$values['%operation'] = $op;
|
||||
$values['%type'] = $this->type;
|
||||
$values['%i18n_translation_set'] = $this->tsid;
|
||||
if ($placeholder = $this->get_info('placeholder')) {
|
||||
$values[$placeholder] = $this->tsid;
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get field on translations table that stores the translation set id (tsid)
|
||||
*/
|
||||
protected function get_field() {
|
||||
return $this->get_info('field');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get property from translation set info
|
||||
*/
|
||||
public function get_info($property, $default = NULL) {
|
||||
$info = i18n_translation_set_info($this->type);
|
||||
return $info && isset($info[$property]) ? $info[$property] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table name, where translation items are stored.
|
||||
*/
|
||||
protected function get_table() {
|
||||
return $this->get_info('table');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title for this set
|
||||
*/
|
||||
public function get_title() {
|
||||
if (!empty($this->title)) {
|
||||
return $this->title;
|
||||
}
|
||||
elseif ($translations = $this->get_objects()) {
|
||||
foreach ($translations as $object) {
|
||||
$names[] = $object->get_title();
|
||||
}
|
||||
return implode(' / ', $names);
|
||||
}
|
||||
else {
|
||||
return t('Undefined');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item list
|
||||
*/
|
||||
public function item_list() {
|
||||
$language_list = language_list();
|
||||
$items = array();
|
||||
foreach ($this->get_objects() as $langcode => $object) {
|
||||
$title = $object->get_title();
|
||||
$path = $object->get_path();
|
||||
if ($title && $path) {
|
||||
$options = isset($language_list[$langcode]) ? array('language' => $language_list[$langcode]) : array();
|
||||
$items[$langcode] = l($title, $path, $options);
|
||||
}
|
||||
elseif ($title) {
|
||||
$items[$langcode] = check_plain($title);
|
||||
}
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add array of translation items
|
||||
*
|
||||
* @param $translations array
|
||||
* Translation items indexed by language code
|
||||
*/
|
||||
public function add_translations($translations) {
|
||||
foreach ($translations as $langcode => $item) {
|
||||
$this->add_item($item, $langcode);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add translation item
|
||||
*/
|
||||
public function add_item($item, $langcode = NULL) {
|
||||
$object = i18n_object($this->type, $item);
|
||||
$langcode = $langcode ? $langcode : $object->get_langcode();
|
||||
// Check whether this item belongs to another translation set
|
||||
$old_tsid = $object->get_tsid();
|
||||
if ($old_tsid && $old_tsid != $this->tsid) {
|
||||
$this->related_translations[$old_tsid] = i18n_translation_set_load($old_tsid);
|
||||
$this->related_translations[$old_tsid]->remove_object($object);
|
||||
}
|
||||
if ($langcode) {
|
||||
$this->get_translations();
|
||||
$object->set_tsid($this->tsid);
|
||||
$this->translations[$langcode] = $object;
|
||||
$this->object_languages[$object->get_index()] = $langcode;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove item / language from translation set
|
||||
*
|
||||
* @param $item
|
||||
* Item to remove from this translation set, it must have a language property.
|
||||
*/
|
||||
public function remove_item($item) {
|
||||
$this->remove_object(i18n_object($this->type, $item));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove i18n object from translation set.
|
||||
*/
|
||||
public function remove_object($object) {
|
||||
// As object's language may have changed, we use our object_languages index better.
|
||||
$index = $object->get_index();
|
||||
$this->get_translations();
|
||||
if (isset($this->object_languages[$index])) {
|
||||
$langcode = $this->object_languages[$index];
|
||||
unset($this->translations[$langcode]);
|
||||
unset($this->object_languages[$index]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove language from translation set.
|
||||
*
|
||||
* @param $langcode
|
||||
* Language to remove from this translation set.
|
||||
*/
|
||||
public function remove_language($langcode) {
|
||||
$this->get_translations();
|
||||
if (isset($this->translations[$langcode])) {
|
||||
$this->remove_object($this->translations[$langcode]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all translations as objects indexed by language
|
||||
*/
|
||||
public function load_translations() {
|
||||
if (($table = $this->get_table()) && ($field = $this->get_field())) {
|
||||
return db_select($table, 't')
|
||||
->fields('t')
|
||||
->condition('t.' . $field, $this->tsid)
|
||||
->execute()
|
||||
->fetchAllAssoc('language');
|
||||
}
|
||||
else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get key field for this translation items
|
||||
*/
|
||||
protected function key_field() {
|
||||
$info = i18n_object_info($this->type);
|
||||
return $info['key'];
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
name = Translation sets
|
||||
description = Simple translation sets API for generic objects
|
||||
dependencies[] = i18n
|
||||
package = Multilingual - Internationalization
|
||||
core = 7.x
|
||||
|
||||
files[] = i18n_translation.inc
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-01-13
|
||||
version = "7.x-1.8"
|
||||
core = "7.x"
|
||||
project = "i18n"
|
||||
datestamp = "1358075001"
|
||||
|
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the text module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function i18n_translation_install() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_schema().
|
||||
*/
|
||||
function i18n_translation_schema() {
|
||||
$schema['i18n_translation_set'] = array(
|
||||
'description' => 'Translation set.',
|
||||
'fields' => array(
|
||||
'tsid' => array(
|
||||
'description' => 'The primary identifier for a translation set.',
|
||||
'type' => 'serial',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'title' => array(
|
||||
'description' => 'The title of this translation set, always treated as non-markup plain text.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'type' => array(
|
||||
'description' => 'Object type or entity type.',
|
||||
'type' => 'varchar',
|
||||
'length' => 32,
|
||||
'not null' => TRUE,
|
||||
'default' => ''
|
||||
),
|
||||
'bundle' => array(
|
||||
'description' => 'Optional bundle for entity translation sets.',
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => ''
|
||||
),
|
||||
'master_id' => array(
|
||||
'description' => 'The master object/entity id (the others will be synchronized with this one).',
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'status' => array(
|
||||
'description' => 'Status of this translation set. TBD.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 1,
|
||||
),
|
||||
'created' => array(
|
||||
'description' => 'The Unix timestamp when the set was created.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'changed' => array(
|
||||
'description' => 'The Unix timestamp when the set was most recently saved.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'entity_bundle' => array('type', 'bundle'),
|
||||
),
|
||||
'primary key' => array('tsid'),
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
351
sites/all/modules/i18n/i18n_translation/i18n_translation.module
Normal file
351
sites/all/modules/i18n/i18n_translation/i18n_translation.module
Normal file
@@ -0,0 +1,351 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Internationalization (i18n) module - Entity translations
|
||||
*/
|
||||
|
||||
// Language list with only enabled languages
|
||||
define('I18N_ENTITY_LANGUAGES_ENABLED', 0);
|
||||
// Language list with all languages
|
||||
define('I18N_ENTITY_LANGUAGES_EXTENDED', 1);
|
||||
|
||||
/**
|
||||
* Default entity controller for notifications objects
|
||||
*/
|
||||
class I18nTranslationSetController extends DrupalDefaultEntityController {
|
||||
/**
|
||||
* Builds objects of specific classes upon loading.
|
||||
*
|
||||
* @param $queried_entities
|
||||
* Associative array of query results, keyed on the entity ID.
|
||||
* @param $revision_id
|
||||
* ID of the revision that was loaded, or FALSE if teh most current revision
|
||||
* was loaded.
|
||||
*/
|
||||
protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
|
||||
foreach ($queried_entities as $id => $entity) {
|
||||
$queried_entities[$id] = i18n_translation_set_build($entity->type, $entity);
|
||||
}
|
||||
return parent::attachLoad($queried_entities, $revision_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_info().
|
||||
*/
|
||||
function i18n_translation_entity_info() {
|
||||
$bundles = array();
|
||||
foreach (i18n_translation_set_info() as $type => $info) {
|
||||
$bundles[$type] = array(
|
||||
'label' => $info['title'],
|
||||
);
|
||||
}
|
||||
$return = array(
|
||||
'i18n_translation' => array(
|
||||
'label' => t('Translation set'),
|
||||
'controller class' => 'I18nTranslationSetController',
|
||||
'base table' => 'i18n_translation_set',
|
||||
//'uri callback' => 'taxonomy_term_uri',
|
||||
'fieldable' => FALSE,
|
||||
'entity keys' => array(
|
||||
'id' => 'tsid',
|
||||
'bundle' => 'type',
|
||||
'label' => 'title',
|
||||
),
|
||||
'bundle keys' => array(
|
||||
'bundle' => 'type',
|
||||
),
|
||||
'bundles' => $bundles,
|
||||
),
|
||||
);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu()
|
||||
*/
|
||||
function i18n_translation_menu() {
|
||||
$items['admin/config/regional/i18n_translation'] = array(
|
||||
'title' => 'Translation sets',
|
||||
'description' => 'Translation sets overview.',
|
||||
'page callback' => 'i18n_translation_admin_overview',
|
||||
//'page arguments' => array('i18n_translation_set_overview'),
|
||||
'access arguments' => array('administer site configuration'),
|
||||
'file' => 'i18n_translation.admin.inc',
|
||||
'weight' => 10,
|
||||
);
|
||||
$items['admin/config/regional/i18n_translation/configure'] = array(
|
||||
'title' => 'Translation sets',
|
||||
'description' => 'Overview of existing translation sets.',
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_hook_info().
|
||||
*/
|
||||
function i18n_translation_hook_info() {
|
||||
$hooks['i18n_translation_set_info'] = array(
|
||||
'group' => 'i18n',
|
||||
);
|
||||
return $hooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this object can be part of a translation set
|
||||
*/
|
||||
function i18n_translation_check_object($type, $object) {
|
||||
if ($info = i18n_translation_set_info($type)) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get form element for translation mode and language
|
||||
*
|
||||
* @param $object_type
|
||||
* Object type for the container element
|
||||
* @param $i18n_mode
|
||||
* Current or default translation mode
|
||||
* @param $langcode
|
||||
* Current or default language code
|
||||
* @param $options
|
||||
* Restricted list of translation modes if we don't want all of them
|
||||
*/
|
||||
function i18n_translation_mode_element($object_type, $i18n_mode = I18N_MODE_NONE, $langcode = LANGUAGE_NONE, $options = NULL) {
|
||||
$form['i18n_translation'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Multilingual options'),
|
||||
'#collapsible' => TRUE,
|
||||
);
|
||||
$form['i18n_translation']['i18n_mode'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Translation mode'),
|
||||
'#options' => i18n_translation_options($object_type, $options),
|
||||
'#default_value' => $i18n_mode,
|
||||
'#description' => t('For localizable elements, to have all items available for translation visit the <a href="@locale-refresh">translation refresh</a> page.', array('@locale-refresh' => url('admin/config/regional/translate/i18n_string'))),
|
||||
);
|
||||
$form['i18n_translation']['language'] = array(
|
||||
'#default_value' => $langcode ? $langcode : LANGUAGE_NONE,
|
||||
'#description' => t('Predefined language. If set, it will apply to all items.'),
|
||||
'#required' => TRUE,
|
||||
'#states' => array(
|
||||
'visible' => array('input[name="i18n_mode"]' => array('value' => (string)I18N_MODE_LANGUAGE)),
|
||||
),
|
||||
) + i18n_element_language_select();
|
||||
|
||||
// The option value 'Language neutral' makes no sense here.
|
||||
$form['i18n_translation']['language']['#options'][LANGUAGE_NONE] = t('- Select a language -');
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of translation modes
|
||||
*
|
||||
* @param $container_type
|
||||
* Object type for the container
|
||||
* @param $options
|
||||
* Options to include. If none, defaults for container type will be returned.
|
||||
*/
|
||||
function i18n_translation_options($container_type, $options = NULL) {
|
||||
// Get names and translation options for container object and items
|
||||
$container_info = i18n_object_info($container_type, 'translation container');
|
||||
$replacements = array(
|
||||
'@container_name' => $container_info['name'],
|
||||
'@item_name_multiple' => $container_info['item name'],
|
||||
'@item_name_multiple_capitalized' => ucfirst($container_info['item name']),
|
||||
);
|
||||
$options = $options ? $options : $container_info['options'];
|
||||
return i18n_translation_options_list($replacements, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of translation modes
|
||||
*/
|
||||
function i18n_translation_options_list($replacements = array(), $options = array()) {
|
||||
$list = array(
|
||||
I18N_MODE_NONE => t('No multilingual options for @item_name_multiple. Only the @container_name will be translatable.', $replacements),
|
||||
I18N_MODE_LOCALIZE => t('Localize. @item_name_multiple_capitalized are common for all languages, but their name and description may be localized.', $replacements),
|
||||
I18N_MODE_TRANSLATE => t('Translate. Different @item_name_multiple will be allowed for each language and they can be translated.', $replacements),
|
||||
I18N_MODE_MULTIPLE => t('Translate and Localize. @item_name_multiple_capitalized with language will allow translations. @item_name_multiple_capitalized without language will be localized.', $replacements),
|
||||
I18N_MODE_LANGUAGE => t('Fixed Language. @item_name_multiple_capitalized will have a global language and they will only show up for pages in that language.', $replacements),
|
||||
);
|
||||
if ($options) {
|
||||
foreach (array_keys($list) as $key) {
|
||||
if (!in_array($key, $options, TRUE)) {
|
||||
unset($list[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build translation fieldset for object
|
||||
*/
|
||||
function i18n_translation_set_element($type, $object) {
|
||||
$element = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Translations'),
|
||||
);
|
||||
if ($set = i18n_translation_object($type, $object)) {
|
||||
$element['values']['#markup'] = i18n_translation_format_items($set->item_list());
|
||||
}
|
||||
else {
|
||||
$element['message']['#markup'] = t('No translations');
|
||||
}
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format translation set info as table
|
||||
*/
|
||||
function i18n_translation_format_items($translations) {
|
||||
foreach ($translations as $langcode => $item) {
|
||||
$rows[] = array(i18n_language_name($langcode), $item);
|
||||
}
|
||||
return !empty($rows) ? theme('table', array('rows' => $rows)) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get translation set for object
|
||||
*/
|
||||
function i18n_translation_object($type, $object, $create = FALSE) {
|
||||
if (($field = i18n_translation_set_info($type, 'field', 'i18n_tsid')) && ($tsid = i18n_object_field($object, $field))) {
|
||||
return i18n_translation_set_load($tsid, $type);
|
||||
}
|
||||
elseif ($create) {
|
||||
$set = i18n_translation_set_build($type);
|
||||
if ($langcode = i18n_object_langcode($object)) {
|
||||
$set->add_item($object, $langcode);
|
||||
}
|
||||
return $set;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about translation sets
|
||||
*/
|
||||
function i18n_translation_set_info($type = NULL, $property = NULL, $default = NULL) {
|
||||
$info = &drupal_static(__FUNCTION__);
|
||||
if (!$info) {
|
||||
$info = module_invoke_all('i18n_translation_set_info');
|
||||
drupal_alter('i18n_translation_set_info', $info);
|
||||
}
|
||||
if ($property && $type) {
|
||||
return isset($info[$type][$property]) ? $info[$type][$property] : $default;
|
||||
}
|
||||
elseif ($type) {
|
||||
return isset($info[$type]) ? $info[$type] : $default;
|
||||
}
|
||||
else {
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a translation set from type, data
|
||||
*/
|
||||
function i18n_translation_set_build($type, $data = array()) {
|
||||
$class = i18n_translation_set_info($type, 'class', 'i18n_translation_set');
|
||||
$set = new $class((array)$data);
|
||||
$set->type = $type;
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new translation set
|
||||
*/
|
||||
function i18n_translation_set_create($type, $bundle = '', $translations = NULL, $master_id = 0) {
|
||||
$set = i18n_translation_set_build($type, array('type' => $type, 'bundle' => $bundle, 'master_id' => $master_id, 'translations' => $translations));
|
||||
$set->insert();
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load single translation set.
|
||||
*
|
||||
* @param int $tsid
|
||||
* Translation set id.
|
||||
* @param string $type
|
||||
* (Optional) translation set type (bundle).
|
||||
*/
|
||||
function i18n_translation_set_load($tsid, $type = NULL) {
|
||||
$conditions['tsid'] = $tsid;
|
||||
$list = entity_load('i18n_translation', array($tsid));
|
||||
$entity = reset($list);
|
||||
if ($entity && $type && $entity->type != $type) {
|
||||
return NULL;
|
||||
}
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Index objects in translation set by language
|
||||
*/
|
||||
function i18n_translation_set_index($translations) {
|
||||
$list = array();
|
||||
foreach ($translations as $object) {
|
||||
if ($lang = i18n_object_langcode($object)) {
|
||||
$list[$lang] = $object;
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translation set generic form
|
||||
*/
|
||||
function i18n_translation_set_overview($form, &$form_state, $type = NULL, $tsids = NULL) {
|
||||
module_load_include('admin.inc', 'i18n_translation');
|
||||
return i18n_translation_admin_form($form, $form_state, $type, $tsids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a tabular listing of translations for this type.
|
||||
*/
|
||||
function i18n_translation_set_list_manage($type) {
|
||||
module_load_include('admin.inc', 'i18n_translation');
|
||||
return i18n_translation_admin_overview($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask for confirmation of translation set deletion
|
||||
*/
|
||||
function i18n_translation_set_delete_confirm($form, &$form_state, $translation_set) {
|
||||
$form['#translation_set'] = $translation_set;
|
||||
$form['tsid'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => $translation_set->tsid,
|
||||
);
|
||||
if ($items = $translation_set->item_list()) {
|
||||
$form['items'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Items in this translation set'),
|
||||
'#markup' => theme('item_list', array('items' => $items)),
|
||||
);
|
||||
}
|
||||
return confirm_form($form,
|
||||
t('Are you sure you want to delete %title translation set?', array('%title' => $translation_set->get_title())),
|
||||
i18n_translation_set_info($translation_set->type, 'list path'),
|
||||
t('This action cannot be undone.'),
|
||||
t('Delete'),
|
||||
t('Cancel')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute translation set deletion
|
||||
*/
|
||||
function i18n_translation_set_delete_confirm_submit($form, &$form_state) {
|
||||
if ($form_state['values']['confirm']) {
|
||||
$set = i18n_translation_set_load($form_state['values']['tsid']);
|
||||
$set->delete(TRUE);
|
||||
drupal_set_message(t('The translation set has been deleted.'));
|
||||
}
|
||||
|
||||
$form_state['redirect'] = i18n_translation_set_info($set->type, 'list path');
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Generic translation page for objects
|
||||
*/
|
||||
|
||||
/**
|
||||
* Translate object, create translation set
|
||||
*/
|
||||
function i18n_translation_object_translate_page($type, $object) {
|
||||
$page = i18n_translation_set_info($type, 'page callback');
|
||||
return call_user_func($page, $type, $object);
|
||||
}
|
Reference in New Issue
Block a user