Zum Inhalt springen

Mehrsprachigkeit bei eigener Extension

Erstellt am 11. Januar 2013 · 7 Antworten · letzte Antwort am 29. Januar 2013

Tags: Frage

dvm ·

Hallo Zusammen

Ich versuche mich schon seit rund 4 Tagen an der Mehrsprachigkeit meiner eigenen Extension. Die Extension war via Kickstarter relativ einfach aufzusetzten und ich habe dabei schon die anderen Sprachen berücksichtigt.

Nun kriege ich es einfach nicht hin, dass der Inhalt der Extension im Frontent auch die Sprache wechselt, wenn die ganze Seite die Sprache wechselt.

Ich habe mich durch unzählige Artikel, Foren, Snippets und Codes durchgeackert und werde einfach nicht schlau daraus.

Gerne poste ich nachstehend den Inhalt des Files: class.tx.references_pi1.php

Kann mir als Noobie jemand vielleicht weiterhelfen?

Besten Dank.

<?php
/***************************************************************
 *  Copyright notice
 *
 *  (c) 2012 Peter Muster <>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
 *  free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  The GNU General Public License can be found at
 *  http://www.gnu.org/copyleft/gpl.html.
 *
 *  This script is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  This copyright notice MUST APPEAR in all copies of the script!
 ***************************************************************/

// require_once(PATH_tslib . 'class.tslib_pibase.php');

/**
 * Plugin 'References' for the 'references' extension.
 *
 * @author    Peter Muster <>
 * @package    TYPO3
 * @subpackage    tx_references
 */
class tx_references_pi1 extends tslib_pibase {
    public $prefixId      = 'tx_references_pi1';        // Same as class name
    public $scriptRelPath = 'pi1/class.tx_references_pi1.php';    // Path to this script relative to the extension dir.
    public $extKey        = 'references';    // The extension key.
    public $pi_checkCHash = TRUE;
    
    /**
     * Main method of your Plugin.
     *
     * @param string $content The content of the Plugin
     * @param array $conf The Plugin Configuration
     * @return string The content that should be displayed on the website
     */
    public function main($content, array $conf) {
        switch ((string)$conf['CMD']) {
            case 'singleView':
                list($t) = explode(':', $this->cObj->currentRecord);
                $this->internal['currentTable'] = $t;
                $this->internal['currentRow'] = $this->cObj->data;
                return $this->pi_wrapInBaseClass($this->singleView($content, $conf));
                break;
            default:
                if (strstr($this->cObj->currentRecord, 'tt_content')) {
                    $conf['pidList'] = $this->cObj->data['pages'];
                    $conf['recursive'] = $this->cObj->data['recursive'];
                }
                return $this->pi_wrapInBaseClass($this->listView($content, $conf));
                break;
        }
    }
    
    /**
     * Shows a list of database entries.
     *
     * @param string $content content of the Plugin
     * @param array $conf Plugin Configuration
     * @return string HTML list of table entries
     */
    protected function listView($content, array $conf) {
        $this->conf = $conf;        // Setting the TypoScript passed to this function in $this->conf
        $this->pi_setPiVarDefaults();
        $this->pi_loadLL();        // Loading the LOCAL_LANG values
        
        $lConf = $this->conf['listView.'];    // Local settings for the listView function
    
        if (is_numeric($this->piVars['showUid'])) {    // If a single element should be displayed:
            $this->internal['currentTable'] = 'tx_references_list';
            $this->internal['currentRow'] = $this->pi_getRecord('tx_references_list', $this->piVars['showUid']);
    
            $content = $this->singleView($content, $conf);
            return $content;
        } else {
            /*$items = array(
                '1' => $this->pi_getLL('list_mode_1', 'Mode 1'),
                '2' => $this->pi_getLL('list_mode_2', 'Mode 2'),
                '3' => $this->pi_getLL('list_mode_3', 'Mode 3'),
            );*/
            if (!isset($this->piVars['pointer'])) $this->piVars['pointer'] = 0;
            if (!isset($this->piVars['mode'])) $this->piVars['mode'] = 1;
    
                // Initializing the query parameters:
            list($this->internal['orderBy'],$this->internal['descFlag']) = explode(':', $this->piVars['sort']);
            $version = class_exists('t3lib_utility_VersionNumber')
                    ? t3lib_utility_VersionNumber::convertVersionNumberToInteger(TYPO3_version)
                    : t3lib_div::int_from_ver(TYPO3_version);
            if ($version < 4006000) {
                $this->internal['results_at_a_time'] = t3lib_div::intInRange($lConf['results_at_a_time'], 0, 1000, 3);        // Number of results to show in a listing.
                $this->internal['maxPages'] = t3lib_div::intInRange($lConf['maxPages'], 0, 1000, 2);;        // The maximum number of "pages" in the browse-box: "Page 1", "Page 2", etc.
            } else {
                $this->internal['results_at_a_time'] = t3lib_utility_Math::forceIntegerInRange($lConf['results_at_a_time'], 0, 1000, 3);        // Number of results to show in a listing.
                $this->internal['maxPages'] = t3lib_utility_Math::forceIntegerInRange($lConf['maxPages'], 0, 1000, 2);;        // The maximum number of "pages" in the browse-box: "Page 1", "Page 2", etc.
            }
            $this->internal['searchFieldList'] = 'title,besch,auftrag,bauzeit,bausumme,leistungen,angaben';
            $this->internal['orderByList'] = 'uid,title,besch,auftrag,bauzeit,bausumme,leistungen';
    
                // Get number of records:
            $res = $this->pi_exec_query('tx_references_list', 1);
            list($this->internal['res_count']) = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
    
                // Make listing query, pass query to SQL database:
            $res = $this->pi_exec_query('tx_references_list');
            $this->internal['currentTable'] = 'tx_references_list';
    
                // Put the whole list together:
            $fullTable = '';    // Clear var;
            // $fullTable .= t3lib_div::view_array($this->piVars);    // DEBUG: Output the content of $this->piVars for debug purposes. REMEMBER to comment out the IP-lock in the debug() function in t3lib/config_default.php if nothing happens when you un-comment this line!
    
                // Adds the mode selector.
            //$fullTable .= $this->pi_list_modeSelector($items);
    
                // Adds the whole list table
            $fullTable .= $this->makeList($res);
    
                // Adds the search box:
            //$fullTable .= $this->pi_list_searchBox();
    
                // Adds the result browser:
            //$fullTable .= $this->pi_list_browseresults();
    
                // Returns the content from the plugin.
            return $fullTable;
        }
    }
    /**
     * Creates a list from a database query.
     *
     * @param resource $res A database result resource
     * @return string A HTML list if result items
     */
    protected function makeList($res) {
        $items = array();
            // Make list table rows
        while (($this->internal['currentRow'] = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) !== FALSE) {
            $items[] = $this->makeListItem();
        }
                                    
        $out = '<div' . $this->pi_classParam('listrow') . '>
            ' . implode(chr(10), $items) . '
            </div>';
        return $out;
    }
    
    /**
     * Implodes a single row from a database to a single line.
     *
     * @return string Imploded column values
     */
    protected function makeListItem() {
        $GLOBALS['TSFE']->ATagParams = ' class="info"';
        $out = '
                <div class="view">
                <img src="/uploads/tx_references/' . $this->getFieldContent('mainimage') . ' />
                <div class="mask"><h2>' . $this->getFieldContent('title') . '</h2>
                <p>' . $this->getFieldContent('besch') . '</p>
                ' . $this->pi_list_linkSingle('Details', $this->internal['currentRow']['uid'], 1) . '
                </div>
                </div>
            ';
        return $out;
    }
    /**
     * Display a single item from the database
     *
     * @param string $content The Plugin content
     * @param array $conf The Plugin configuration
     * @return string HTML of a single database entry
     */
    protected function singleView($content, array $conf) {
        $this->conf = $conf;
        $this->pi_setPiVarDefaults();
        $this->pi_loadLL();
        
    
            // This sets the title of the page for use in indexed search results:
        if ($this->internal['currentRow']['title'])    {
            $GLOBALS['TSFE']->indexedDocTitle = $this->internal['currentRow']['title'];
        }
            
        $content = '<div class="singelview">
                <h2>' . $this->getFieldContent('title') . '</h2>
                <p><strong>' . $this->getFieldContent('besch') . '</strong></p>
                <div class="singlecon">
                <div class="singleviewleft">
                <p><strong>' . $this->getFieldHeader('auftrag') . ':</strong> </p>
                <p><strong>' . $this->getFieldHeader('bauzeit') . ':</strong> </p>
                <p><strong>' . $this->getFieldHeader('bausumme') . ':</strong> </p>
                <p><strong>' . $this->getFieldHeader('leistungen') . ':</strong> </p>
                <p><strong>' . $this->getFieldHeader('angaben') . ':</strong> </p>
                </div>
                <div class="singleviewright">
                <p>' . $this->getFieldContent('auftrag') . ' </p>
                <p>' . $this->getFieldContent('bauzeit') . ' </p>
                <p>' . $this->getFieldContent('bausumme') . ' </p>
                <p>' . $this->getFieldContent('leistungen') . ' </p>
                <p>' . $this->getFieldContent('angaben') . ' </p>
                </div>
                </div>
                <div class="view">
                    <a href="#image-1"><img src="/uploads/tx_references/' . $this->getFieldContent('mainimage') . '" alt="image01" />
                    <div class="mask"><h2>View</h2></div></a>
                    <div class="lb-overlay" id="image-1">
                        <img src="/uploads/tx_references/full/' . $this->getFieldContent('mainimage') . '" alt="image01" />
                        <div>
                            <a href="#image-4" class="lb-prev">Prev</a>
                            <a href="#image-2" class="lb-next">Next</a>
                        </div>
                        <a href="#page" class="lb-close">Close</a>
                    </div>
                </div>
                <div class="view">
                    <a href="#image-2"><img src="/uploads/tx_references/' . $this->getFieldContent('image2') . '" alt="image02" />
                    <div class="mask"><h2>View</h2></div></a>
                    <div class="lb-overlay" id="image-2">
                        <img src="/uploads/tx_references/full/' . $this->getFieldContent('image2') . '" alt="image02" />
                        <div>
                            <a href="#image-1" class="lb-prev">Prev</a>
                            <a href="#image-3" class="lb-next">Next</a>
                        </div>
                        <a href="#page" class="lb-close">Close</a>
                    </div>
                </div>
                <div class="view">
                    <a href="#image-3"><img src="/uploads/tx_references/' . $this->getFieldContent('image3') . '" alt="image03" />
                    <div class="mask"><h2>View</h2></div></a>
                    <div class="lb-overlay" id="image-3">
                        <img src="/uploads/tx_references/full/' . $this->getFieldContent('image3') . '" alt="image03" />
                        <div>
                            <a href="#image-2" class="lb-prev">Prev</a>
                            <a href="#image-4" class="lb-next">Next</a>
                        </div>
                        <a href="#page" class="lb-close">Close</a>
                    </div>
                </div>
                <div class="view">
                    <a href="#image-4"><img src="/uploads/tx_references/' . $this->getFieldContent('image4') . '" alt="image04" />
                    <div class="mask"><h2>View</h2></div></a>
                    <div class="lb-overlay" id="image-4">
                        <img src="/uploads/tx_references/full/' . $this->getFieldContent('image4') . '" alt="image04" />
                        <div>
                            <a href="#image-3" class="lb-prev">Prev</a>
                            <a href="#image-1" class="lb-next">Next</a>
                        </div>
                        <a href="#page" class="lb-close">Close</a>
                    </div>
                </div>
                            
                <div class="singleviewdown">
                
                </div>
                
        <p>' . $this->pi_list_linkSingle($this->pi_getLL('back', 'Back'), 0) . '</p></div>' .
        $this->pi_getEditPanel();
    
        return $content;
    }
    /**
     * Returns the content of a given field
     *
     * @param string $fN Name of table field
     * @return string Value of the field
     */
    protected function getFieldContent($fN) {
        switch($fN) {
            case 'uid':
                return $this->pi_list_linkSingle($this->internal['currentRow'][$fN], $this->internal['currentRow']['uid'], 1);    // The "1" means that the display of single items is CACHED! Set to zero to disable caching.
                break;
            //case "title":
                    // This will wrap the title in a link.
                //return $this->pi_list_linkSingle($this->internal['currentRow']['title'], $this->internal['currentRow']['uid'], 1);
                //break;
            default:
                return $this->internal['currentRow'][$fN];
                break;
        }
    }
    /**
     * Returns the label for a field name from local language array.
     *
     * @param string $fN Name of table field
     * @return string
     */
    protected function getFieldHeader($fN) {
        switch ($fN) {
            case "title":
                return $this->pi_getLL('listFieldHeader_title', '<em>title</em>');
                break;
            default:
                return $this->pi_getLL('listFieldHeader_' . $fN, '[' . $fN . ']');
                break;
        }
    }
    
    /**
     * Returns a sorting link for a column header.
     *
     * @param string $fN Name of table field
     * @return string The field label wrapped in link that contains sorting vars
     */
    protected function getFieldHeader_sortLink($fN) {
        return $this->pi_linkTP_keepPIvars(
            $this->getFieldHeader($fN),
            array(
                'sort' => $fN . ' : ' . ($this->internal['descFlag'] ? 0 : 1),
            )
        );
    }
}



if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/references/pi1/class.tx_references_pi1.php'])) {
    include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/references/pi1/class.tx_references_pi1.php']);
}

?>
horge20 ·

Hi dvm,

die Sprachversionen werden in die locallang XMLs ausgelagert. Der Kickstarter legt zwei XML Dateien an. Eine in der Wurzel der extension (locallang_db.xml) und eine in pi1 (locallang.xml).

Die locallang_db.xml ist für das Backend. Wenn Du also einen BE USer (Redakteur) in bspw. Frankreich sitzen hast und dem auch die entsprechende Sprache zugeordnet hast, sieht der Deine Formularfelder - so denn übersetzt - in französisch. Um eine Übersetzung außerhalb anzulegen einfach Langauge Key kopieren und weiter unten anfügen:

<languageKey index="default" type="array">
   <label index="tx_[DEIN EXTENSION]_analysis">Prozessanalyse</label>
   ...
</languageKey>

und in französisch

<languageKey index="fr" type="array">
   <label index="tx_[DEIN EXTENSION]_analysis">Analyse proces</label>
   ...
</languageKey>

Für's Frontend gilt das gleiche ... hier in der locallang.xml in der pi1.

TIPP: Solltest Du einen Editor nutzen, dann stelle vorher UTF-8 ein, sonst gibt's einen Fehler.

Damit man das dann auch im Frontend sieht, muss testweise die Sprache im template eingestellt werden.

config.language = fr
config.locale_all = fr_FR

Abschließend:

1. Cache löschen
2. im Extension Manager noch die Sprachdateien updaten

dvm ·

HI horge20

Besten Dank für Deinen Input. Das habe ich soweit auch schon gemacht.

Zum Verständnis. Meine Extension ist eine Art Referenzliste, bei welcher jede Referenz eine Detailansicht mit Bildern hat. Darin sind diverse Zelleninhalte aufgelistet. Die Datensätze dafür muss ich im Listentool als Datensatz anlegen. Dort kann ich diese dann auch in den anderen Sprachen anlegen.

Bei der Ausgabe im Frontend werden jedoch stets alle Datensätze, auch die der Fremdspachen, aufgelistet, was ja keinen Sinn macht. Stelle ich auf English oder auf Französich um, werden trotzdem alle Datensätz (DE, EN, FR) aufgelistet. Ich kriege es einfach nicht hin, dass nur die Datensätze der jeweiligen Sprache im Frontend aufgelistet werden. Ich meine damit nicht die Labels sondern die effektiven Zelleninhalte. In der Tabelle werden alle Datensätze mit den jeweiligen sys_language_uid abgespeichert. Beim Auslesen werden dann aber die sys_language_uid-Werte ignoriert und einfach alle angezeigt. Evtl. mach ich in meinem PHP-Code was falsch, ich seh leider nur nicht was.

Ich muss dazu sagen, ich bin auch nicht der PHP-Spezialist und habe so meine Mühe mit den Abfragen.

Evtl. sieht jemand von Euch, was ich falsch mache. Ich habe schon viele Wege ausprobiert. Leider alle ohne Erfolg.

Besten Dank

dvm

horge20 ·

OK ... eine Lösung ist es die unterschiedlichen Datensätze in eigene Sysfolder zu packen. Also einen mit den deutschen, einen mit den französischen, etc.

Der Kickstarter gibt nicht mehr per default einen Startpunkt an, wo die Datensätze liegen (früher ging das). Egal.

In der ext_tables.php Deiner extension gibt es folgende Zeile:

$TCA['tt_content']['types']['list']['subtypes_excludelist'][$_EXTKEY.'_pi1'] ='layout,select_key,pages';

Ersetze diese mit:

$TCA['tt_content']['types']['list']['subtypes_excludelist'][$_EXTKEY.'_pi1'] ='layout,select_key';

und schon bekommst Du über "Seite" in Deinem Plugin in einem der Reiter (das variiert je nach Typo3 Version) ein Auswahlfeld, wo Du den Sysordner zuordnest.

dvm ·

Perfect horge20

Hat super funktioniert. Darauf wäre ich jetzt nicht gekommen.
Jetzt muss ich einfach für jede Seite auf der ich das Plugin setze (mit jeweils anderen Datensätzen) auch entsprechende SysFolders pro Sprache anlegen. Ok. Jetzt wo ich das weiss. Kein Problem.

Ein Problem habe ich jetzt trotzdem noch. Die Labels werden im Frontend nicht übersetzt, obwohl ich diese in den locallang entsprechend übersetzt habe.

Besten Dank für Deine Hilfe.

dvm

horge20 ·

Hast Du denn im Template schon die Globals conditions zugeordnet? Klappt das Umschalten über den L Parameter?

dvm ·

Habe es wie folgt im Template eingetragen:

config {
  language = de
  locale_all = de_DE.UTF-8	
  }
[globalVar = GP:L = 5]
Französisch
config.sys_language_uid = 5
config.language = fr
config.locale_all = fr_FR.UTF8
[globalVar = GP:L = 4]
English
config.sys_language_uid = 4
config.language = en
config.locale_all = en_EN.UTF8

Das Umschalten über den L Parameter funktioniert. Der ordentliche Inhalt, sowie der Tabelleninhalt meiner Extension wird schön übersetzt. Nur die Labels des Tabelleninhaltes meiner Extension werden nicht übersetzt. Dies obwohl ich in den locallang Files die Übersetzung vorgenommen habe. Vgl. die Dateien aus meiner Extension, welche ich Dir zugestellt habe.