Einträge Mehrsprachig machen

Per Standard sind nur die Adressgruppen von tt_address mehrsprachig. Dieser Artikel zeigt, wie man die Address Records mehrsprachig machen kann.

Mehrsprachige / Multilang Einträge von tt_address erfassen

Neulich wollte ich die Adressen mehrsprachig erfassen können, damit zum Beispiel die Funktion einer Person in mehreren Sprachen erfasst werden kann, ohne mit unterschiedlichen sprachabhägigen System Ordnern im TYPO3 arbeiten zu können.

Nach einiger Suche fand ich einen Beitrag auf typo3forum.net in welchem beschrieben wird, wie man tt_address umbauen kann, damit die Adressen mehrsprachig erstellt werden können.

Weil ich kein Fan von Umbauarbeiten an bestehenden *Core* Extensions bin, werde ich in diesem Artikel zeigen, wie man sich eine eigene Extension erstellt, welche die tt_address Extension (2.2.1) mehrsprachig macht.

Minimaler Aufbau der Extension

Als ersten wird der Extension Key festgelegt indem man einen neuen Ordner im typo3conf Verzeichnis anlegt. In diesem Beispiel ist der Key ttaddress_l18n.

Anschliessend wird eine minimale Datei Struktur erstellt.

Datei Struktur innerhalb dem Ordner ttaddress_l18n


xclass/class.ux_tx_ttaddress_pi1.php
ext_emconf.php
ext_localconf.php
ext_tables.php
ext_tables.sql
Diese Dateien im Ordner ttaddress_l18n erstellen
ext_emconf.php

<?php

$EM_CONF[$_EXTKEY] = array(
	'title' => 'Titel der Extension',
	'description' => 'Beschreibung der Extension',
	'category' => 'misc',
	'author' => 'Author', // Name des Authors
	'author_email' => 'demo@extension.ch', // Email von Author
	'shy' => '', // Versteckt
	'dependencies' => 'tt_address', // Abhägig von
	'conflicts' => '', // Probleme mit
	'priority' => 'bottom',
	'module' => '',
	'state' => 'stable', // Status
	'internal' => '',
	'uploadfolder' => 0,
	'createDirs' => '',
	'modify_tables' => 'tt_address', // Welche Tabellen werden verädert
	'clearCacheOnLoad' => 0,
	'lockType' => '',
	'author_company' => '',
	'version' => '0.1.1',
	'constraints' => array(
		'depends' => array(
			'tt_address' => '',
			'php' => '5.2.0-0.0.0',
			'typo3' => '4.3.0-0.0.0',
		),
		'conflicts' => array(
		),
		'suggests' => array(
		),
	),
	'suggests' => array(
	),
	'_md5_values_when_last_written' => '',
);

?>
Die Datei ext_emconf.php
ext_localconf.php

<?php
if (!defined ('TYPO3_MODE')) die ('Access denied.');

// XCLASS
$TYPO3_CONF_VARS['FE']['XCLASS']['ext/tt_address/pi1/class.tx_ttaddress_pi1.php'] = t3lib_extMgm::extPath($_EXTKEY).'xclass/class.ux_tx_ttaddress_pi1.php';

?>
Die Datei ext_localconf.php
ext_tables.php

<?php
if (!defined ('TYPO3_MODE')) 	die ('Access denied.');

$_extConfig = unserialize($GLOBALS["TYPO3_CONF_VARS"]["EXT"]["extConf"][$_EXTKEY]);

t3lib_div::loadTCA("tt_address");

$addCtrlAndOverride = array (
	'sortby'                   => 'sorting',
	'label_alt'                => 'sys_language_uid',
	// Display Language after Label
	'label_alt_force'          => 0,
	'languageField'            => 'sys_language_uid',
	'transOrigPointerField'    => 'l18n_parent',
	'transOrigDiffSourceField' => 'l18n_diffsource'
);

/* add fields to ctrl list */
$TCA['tt_address']['ctrl'] = array_merge($TCA['tt_address']['ctrl'],$addCtrlAndOverride);
/* add fields to feInterface list */
$TCA['tt_address']['feInterface']['fe_admin_fieldList'] .= ',sys_language_uid,l18n_parent,l18n_diffsource';


$addTTAddressColumns = array (
	'sys_language_uid' => array(
		'exclude' => 1,
		'label'   => 'LLL:EXT:lang/locallang_general.xml:LGL.language',
		'config'  => array(
			'type'                => 'select',
			'foreign_table'       => 'sys_language',
			'foreign_table_where' => 'ORDER BY sys_language.title',
			'items'               => array(
				array('LLL:EXT:lang/locallang_general.php:LGL.allLanguages', -1),
				array('LLL:EXT:lang/locallang_general.php:LGL.default_value', 0)
			)
		)
	),
	'l18n_parent' => array(
		'displayCond' => 'FIELD:sys_language_uid:>:0',
		'exclude' => 1,
		'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.l18n_parent',
		'config' => array(
			'type'    => 'select',
			'items'   => array(
					array('', 0),
				),
			'foreign_table' => 'tt_address',
			'foreign_table_where' => 'AND tt_address.pid=###CURRENT_PID### AND tt_address.sys_language_uid IN (-1,0)',
		)
	),
	'l18n_diffsource' => array(
		'config' => array(
			'type' => 'passthrough'
		)
	),
	'addressgroup' => array(
		// Do not show for a Translation
		'l10n_mode' => 'exclude',
		//'l10n_mode' => 'mergeIfNotBlank',
		'exclude' => 1,
		'label' => 'LLL:EXT:tt_address/locallang_tca.xml:tt_address.addressgroup',
		'config' => array(
			'type'          => 'select',
			'form_type'     => 'user',
			'userFunc'      => 'tx_ttaddress_treeview->displayGroupTree',
			'treeView'      => 1,
			'foreign_table' => 'tt_address_group',
			'size'          => 5,
			'autoSizeMax'   => 25,
			'minitems'      => 0,
			'maxitems'      => 50,
			'MM'            => 'tt_address_group_mm',
		)
	)

);

/* add fields to TCA */
t3lib_extMgm::addTCAcolumns('tt_address', $addTTAddressColumns);

?>
Die Datei ext_tables.php
ext_tables.sql

#
# Table structure for table 'tt_address'
#

CREATE TABLE tt_address (
	sorting int(10) DEFAULT '0' NOT NULL,
	sys_language_uid int(11) DEFAULT '0' NOT NULL,
	l18n_parent int(11) DEFAULT '0' NOT NULL,
	l18n_diffsource mediumblob NOT NULL
);
Die Datei ext_tables.sql
xclass/class.ux_tx_ttaddress_pi1.php

<?php

class ux_tx_ttaddress_pi1 extends tx_ttaddress_pi1 {

	/*
	 * override tt_address/pi1/class.tx_ttaddress_pi1.php->checkSorting
	 */
	function checkSorting($sortBy) {
		t3lib_div::loadTCA('tt_address');
		$validSortings = array_keys($GLOBALS['TCA']['tt_address']['columns']);
		$validSortings[] = 'sorting';
		if(!in_array($sortBy, $validSortings)) {
			$sortBy = 'name';
		}
		return $sortBy;
	}

	/*
	 * override tt_address/pi1/class.tx_ttaddress_pi1.php->getSingleRecords
	 */
	function getSingleRecords() {
		$singleRecords = array();
		$uidList = $GLOBALS['TYPO3_DB']->cleanIntList(
			$this->conf['singleSelection']
		);

		if(!empty($uidList) && !empty($this->conf['pidList'])) {

			$select = '*';
			$table = 'tt_address';
			// we try to get the default language entry (normal behaviour) or, if not possible, currently the needed language (fallback if no default language entry is available)
			$where = '(sys_language_uid IN (-1,0) OR (sys_language_uid = ' .$GLOBALS['TSFE']->sys_language_uid. ' AND l18n_parent = 0))';
			$where  .= ' AND uid IN('.$uidList.') AND pid IN('.$this->conf['pidList'].')';
			// always (!) use TYPO3 default function for adding hidden = 0, deleted = 0, group and date statements
			if ($GLOBALS['TSFE']->sys_language_content==0) {
				$where  .= $GLOBALS['TSFE']->sys_page->enableFields($table);
			}
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($select, $table, $where);

			while ($row=$GLOBALS ['TYPO3_DB']->sql_fetch_assoc($res) ){
				if ($GLOBALS['TSFE']->sys_language_content){
					//$row=$GLOBALS['TSFE']->sys_page->getRecordOverlay('tt_address',$row,$GLOBALS['TSFE']->sys_language_content,$GLOBALS['TSFE']->sys_language_contentOL);
					$row=$GLOBALS['TSFE']->sys_page->getRecordOverlay('tt_address',$row,$GLOBALS['TSFE']->sys_language_content,$GLOBALS['TSFE']->sys_language_mode=='strict'?'hideNonTranslated':'');
				}
				$singleRecords[$row['uid']] = $this->getGroupsForAddress($row);
			}

			$GLOBALS['TYPO3_DB']->sql_free_result($res);

		}

		return $singleRecords;
	}

	/*
	 * override tt_address/pi1/class.tx_ttaddress_pi1.php->getRecordsFromGroups
	 */
	function getRecordsFromGroups() {
		$groupRecords = array();

			// similar to t3lib_db::cleanIntList(), but we need the count for AND combination
		$groups    = t3lib_div::intExplode(',',$this->conf['groupSelection']);
		$count     = count($groups);
		$groupList = implode(',', $groups);

		if(!empty($groupList) && !empty($this->conf['pidList'])) {
			if($this->conf['combination'] == 'AND') {
					// AND
				$res = $GLOBALS['TYPO3_DB']->sql_query(
					'SELECT tt_address.*, COUNT(tt_address.uid) AS c '.
					'FROM tt_address '.
					'JOIN tt_address_group_mm AS tta_txagg_mm ON tt_address.uid = tta_txagg_mm.uid_local '.
					'JOIN tt_address_group AS txagg ON txagg.uid = tta_txagg_mm.uid_foreign '.
					'WHERE uid_foreign IN ('.$groupList.') '.
						$GLOBALS['TSFE']->sys_page->enableFields('tt_address').
						' AND tt_address.pid IN('.$this->conf['pidList'].') '.
						// this line added by tt_address_l18n
						' AND (tt_address.sys_language_uid IN (-1,0) OR (tt_address.sys_language_uid = ' .$GLOBALS['TSFE']->sys_language_uid. ' AND tt_address.l18n_parent = 0)) '.
					'GROUP BY tt_address.uid '.
					'HAVING c = '.$count.' '
				);
			} elseif($this->conf['combination'] == 'OR') {
					// OR
				$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
					'DISTINCT tt_address.*',
					'tt_address, tt_address_group_mm, tt_address_group',
					'tt_address_group_mm.uid_foreign IN('.$groupList.
						') AND tt_address.uid = tt_address_group_mm.uid_local '.
						$GLOBALS['TSFE']->sys_page->enableFields('tt_address').
						' AND tt_address.pid IN('.$this->conf['pidList'].')'.
						// this line added by tt_address_l18n
						' AND (tt_address.sys_language_uid IN (-1,0) OR (tt_address.sys_language_uid = ' .$GLOBALS['TSFE']->sys_language_uid. ' AND tt_address.l18n_parent = 0)) '
				);
			}

			while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
				if ($GLOBALS['TSFE']->sys_language_content){
					$row=$GLOBALS['TSFE']->sys_page->getRecordOverlay('tt_address',$row,$GLOBALS['TSFE']->sys_language_content,$GLOBALS['TSFE']->sys_language_mode=='strict'?'hideNonTranslated':'');
				}
				$groupRecords[$row['uid']] = $this->getGroupsForAddress($row);
			}

			$GLOBALS['TYPO3_DB']->sql_free_result($res);
		}

		return $groupRecords;

	}

}
?>
Die Datei xclass/class.ux_tx_ttaddress_pi1.php