Streamcatcher App jetzt auch für Apple IOS

Die Streamcatcher App gibt es nun endlich auch für Appl IOS, so dass ihr auch als Apple Nutzer nun endlich die beliebte Film und Serien Suchmaschine immer dabei haben könnt.


Download IOS APP

Veröffentlicht unter Allgemein, apps, streamcatcher | Hinterlasse einen Kommentar

Streamcatcher APP für Android

Endlich ist sie da: die Streamcatcher APP für Android.
Jetzt ist die Film und Seriensuche noch einfacher, dank der bewährten Streamcatcher Filter.
Egal ob aktuelle Blockbuster, die angesagtesten Serien oder alte Filmklassiker, mit der Streamcatcher APP habt ihr immer einen Überblick, bei welchem Anbieter ihr eure Lieblingsfilme zum besten Preis findet.
Die IOS App folgt in den nächsten Wochen.

Hier geht es direkt zur kostenlosten APP.

Veröffentlicht unter Allgemein | Hinterlasse einen Kommentar

Co-Working im Denkwerk in Herford

Der Co-Working Trend scheint aktuell ungebrochen zu sein und so ist es nicht verwunderlich, dass in den Großstädten neue Co-Working Spaces wie Pilze aus dem Boden schießen.
Für viele Freiberufler und Selbständige bieten Co-Working Spaces eine flexible Möglichkeit in einen Büro zu arbeiten, ohne sich langfristig durch einen Mietvertrag an einen bestimmten Standort zu binden.
Außerdem bieten Co-Working Spaces eine Abwechslung zum Home Office und eine gute Möglichkeit, sein eigenes Netzwerk um interessante Kontakte zu erweitern.

Wer nun aber meint, ausgefallene und schöne Co-Working Space seien nur in Berlin, München oder Hamburg zu finden, der sollte mal einen Abstecher nach Ostwestfalen machen.
Im Denkwerk in Herford hat sich Oliver Flaskämper den Traum vom perfekten Büro erfüllt.
Auf 2.800 qm Nutzfläche hat er nicht nur die Firmen seiner eigenen Firmengruppe (u.a. bitcoin.de, content.de) untergebracht, sondern er hat auch den ersten Co-Working Space Herford mit ca. 25 Arbeitsplätzen eröffnet.
Das Gebäude bietet alles was man im heutigen Büro Arbeitsumfeld so braucht: eine Highspeed Internetanbindung, große lichtdurchflutete Räume mit hohen Decken, einen großen Konferenzbereich, Besprechungsräume, mehrere Küchen, Schalldichte Telefonkabinen und ausreichend Parkplätze.

Co Working im Denkwerk Herforf

Blick in den Co-Working Bereich im Denkwerk Herford

Generell fällt auf, das hier Wert aufs Detail gelegt wurde, ob beim hochwertigen Parketfußboden, dem Lichtdesign, den sehr schönen Echtholzschreibtischen, dem Schmiedeeisernen Treppengelänger im zentralen Treppenhaus, den Bürostühlen der höheren Preiskategorie (der Rücken wird es danken) oder der Musik in den Sanitärbereichen, die automatisch angeht, sobald man den Raum betritt.
Eine besondere Überraschung erwartet die Herren auf dem Gäste WC, hier kann man mittels „ausgeklügelter Steuertechnik“ beim Wasserlassen versuchen, möglichst viele Elfmeter im Tor zu versenken.

Da Bilder mehr sagen als viele Worte, hier ein paar Impressionen:

Kaminzimmer

Kaminzimmer

Tetris Tisch

Tetris Tisch

Die kurzweiligste Herrentoilette Deutschlands

Die kurzweiligste Herrentoilette Deutschlands

Büro oder Hotel ?

Büro oder Hotel ?

Die Sauna und der Massage- und der Fitnessraum sollen Anfang 2016 eröffnet werden, dann gibt es noch ein paar Gründe mehr mal den Co-Working Space im Denkwerk in Herford zu testen.
Dann könnte der Satz „Schatz ich bleibe heute länger im Büro“ eine ganz neue Bedeutung bekommen.

Wer also mal einen Co-Working Space der besonderen Art ausprobieren möchte, der sollte mal hier vorbei schauen:
http://www.denkwerk-herford.de/
Denkwerk Herford Betriebs GmbH
Leopoldstraße 2-8
32051 Herford

Veröffentlicht unter Allgemein | Hinterlasse einen Kommentar

Symfony Live 2015

Am 15. und 16.10.2015 lud Sensio Labs wieder zur Symfony Live Konferenz in Berlin ein.
Das ganze fand diesmal im Golden Tulip Hotel in Tiergarten statt und stand ganz im Zeichen des 10 jährigen Symfony Jubiläums.
Die Vorträge fanden parallel in zwei Konferenzsälen statt, so dass es bei den vielen interessanten Themen nicht immer ganz einfach war, sich für einen Vortrag zu entscheiden.
Neben zahlreichen Vorträgen rund um den Einsatz von Symfony (hier gehts zum gesammten Programm) gab es auch sehr interessante Vorträge zu allgemeineren Themen (z.B. was ist neu in PHP7, welche Änderungen erwarten uns mit HTTP 2.0, Einsatz von Microservices, Global Design Principles).

Nach den offiziellen Vorträgen gab es dann im Anschuss noch jeweils zehnminütige Lightning Talks, die natürlich erfahrungsgemäß auch gerne mal in Werbepräsentationen ausarten.

DSC_0007

Diverse Aussteller und Sponsoren präsentierten sich mit kleineren Ständen, verschenkten die üblichen goodies und hielten Ausschau nach potentiellen neuen Mitarbeitern.
Es gab sogar ein kleines schwarzes Brett mit Stellenanzeigen.

Natürlich hatte auch Sensio Labs einen eigenen Stand, so dass man sich direkt z.B. über aktuelle Schulungsmöglichkeiten informieren konnte.

Insgesamt eine sehr gelungene Veranstaltung mit sehr interessanten Vorträgen.
Dass Catering war ebenfalls spitzenmäßig, angefangen beim Frühstück, über kleine Snacks zwischendurch bis zum reichhaltigen Mittagsbüffet war für jeden etwas dabei.

Eine kleiner Kritikpunkt noch zum Schluss, ich fand die Location etwas ungünstig ausgewählt.
Die nächste U Bahn Station (Wittenberplatz) ist ca. 10 Minuten entfernt, was bei ströhmendem Dauerregen doch etwas ungünstig war. Außerdem fand ich es unpraktisch, das ein Konferenzsaal im Erdgeschoss war und der andere in der 11. Etage, so dass man des öfteren an den (für eine Veranstaltung dieser Größe zu kleinen) Fahrstühlen anstehen musste.
Dafür wurde man dann allerdings in der 11. Etage mit der Aussicht über Berlin entschädigt.

Veröffentlicht unter Allgemein, PHP, Symfony2 | Hinterlasse einen Kommentar

Google Trends zu aktuellen Frameworks

Anbei mal wieder eine interessante Grafik von Google Trends zum Vergleich der Suchanfragen für die Frameworks Phalcon, Zend Framework 2 und Symfony 2.
Wie man sehr schön erkennen kann, hat Phalcon ganz schön aufgeholt und wird immer beliebter.
Erst kürzlich wurde Phalcon 2 veröffentlicht.
Es bleibt also spannend auf dem Framework Markt und der Abwartstrend beim Zend Framework schein weiterzugehen.

Bildschirmfoto 2015-08-11 um 11.22.27

Veröffentlicht unter Allgemein, Phalcon, Symfony2 | Hinterlasse einen Kommentar

Phalcon – Validierung und Filterung von Formularwerten

Da die offizielle Phalcon Dokumentation zum Thema „automatische Filterung von Formularwerten“ noch recht lückenhaft ist, folgt hier eine kurze Beschreibung zur Vorgehensweise.

Als Beispiel dient eine einfache Formularklasse mit einem Formularfeld.
Mit den Funktionen „addFilter“ und „addValidator“ werden die Filter und die Validatoren für das Formularfeld definiert.
In diesem Fall werden der ’striptag‘ Filter (Entfernt HTML Tags) und ‚trim‘ Filter (entfernt Leerzeichen) definiert.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class ExampleForm extends BaseForm
{
    public function getForm()
    {
       $this->add($this->getExampleFormField());
       ...
       // weitere Formularfelder einfügen	
    }
    protected function getExampleFormField()
    {
        $field = (new Text('exampleField'))
            ->setAttribute('id', 'exampleFieldId')
            ->setAttribute('name', 'exampleFieldName')
            ->addFilter('trim')
            ->addFilter('striptags')
            ->addValidator(new PresenceOf(array(
  		  'message' => 'The exampleField is required'
	    )));
        ;
        return $field;
    }

Im Controller wird das Formular erstellt und falls es per Post abgeschickt wurde, verarbeitet.
Wichtig für die automatische Filterung ist dabei, dass man beim Erstellen der Formularklasse das zugehörige Entity Model übergibt und das die Post Werte per „bind“ an das Formular übergeben werden.
Durch die „bind“ Funktion werden die gefilterten Werte automatisch an das Entity Model übergeben, so dass man im einfachsten Fall das Entity Model dann direkt speichern kann, sofern das Formalar erfolgreich validiert wurde.

1
2
3
4
5
6
7
8
9
$modelEntity = ModelEntity::findFirst('id = ' . $exampleId);
$form = (new ExampleForm($modelEntity))->getForm();
if ($this->request->isPost() {
   $form->bind($$this->request->getPost(), $form->getEntity());
   if ($form->isValid($this->request->getPost())) {
     if ($modelEntity->save() === false) {
        $this->flashSession->error('Error saving data: ' . implode(',' , $modelEntity->getErrorMessages()));
     }
}

Wenn man die Filter vernünftig konfiguriert und einsetzt, kann man z.B. die Gefahr verringern, dass man schädlichen Javscript Code ungefiltert in der Datenbank speichert.

Veröffentlicht unter Phalcon | Verschlagwortet mit , , | Hinterlasse einen Kommentar

Symfony2 – In Repository Klasse auf Service Container zugreifen

In Symfony2 haben Repository Klassen normalerweise keinen Zugriff auf den Service Container.
Das kann jedoch durchaus sinnvoll sein, damit man in der Repository Klasse z.B. auf Konfigurationsparameter zugreifen kann.
Um dies zu ermöglichen, kann man eine eigene Parent Klasse für die Repository Klassen implementieren, die die Klasse EntityRepository erweitert.
Die jeweilige Repository Klasse, die auf den Service Container zugreifen können soll, muss dann diese Klasse erweitern, als Service definiert und als Service geladen werden, damit das ganze funktioniert.

Die Parent Klasse:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
namespace MyNamespace\lib\Symfony;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
class ContainerAwareRepository extends EntityRepository implements ContainerAwareInterface
{
    protected $container;
    /**
     * Sets the Container.
     * @param ContainerInterface|null $container A ContainerInterface instance or null
     */
    public function setContainer(ContainerInterface $container=null)
    {
        $this->container = $container;
    }
}

Die Repository Klasse muss als Service definiert werden.
Beispiel im Yaml Format:

1
2
3
4
5
6
7
8
  myservices.nameOfRepositoryClass:
    class: MyNamespace\ExampleBundle\Entity\ExampleRepository
    factory_service: doctrine.orm.entity_manager
    factory_method:  getRepository
    arguments:
        - "ExampleNamespaceExampleBundle:ExampleEntity"
    calls:
        - [ setContainer, [ @service_container ] ]

Die Repository Klasse muss die oben definierte Parent Klasse erweitern

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
namespace MyNamespace\ExampleBundle\Entity;
 
use Doctrine\ORM\EntityRepository;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use MyNamespace\lib\Symfony\ContainerAwareRepository;
use MyNamespace\ExampleBundle\Entity\ExampleEntity;
 
class ExampleRepository extends ContainerAwareRepository
{
    public function exampleFunction()
    {
        ...
        // jetzt ist der Zugriff auf den Service Container möglich
        $this->container->getParameter('parametername')
        ...
    }
}

Dann muss die Repository im Controller als Klasse als Service geladen werden und bekommt im Konstruktor per Dependency Injection den Service Container als Parameter übergeben.
Somit kann man in der Repository Klasse auf den Service Container zugreifen.

1
$oRepository = $this->getContainer()->get('myservices.nameOfRepositoryClass');
Veröffentlicht unter Symfony2 | Verschlagwortet mit , , , | Hinterlasse einen Kommentar

Symfony2 – Application Pfade ändern

Symfony2 gilt als sehr flexibles und relativ einfach anzupassendes Framework.
So es ist kein Problem die Pfade für z.B. die Cachefiles oder die Logfiles zu ändern.
Das macht natürlich nicht nur in der Liveumgebung Sinn, wo man in der Regel mit einer Cluster Umgebung arbeitet und die Logfiles und die Cachefiles zentral halten möchten.
Aber auch in der Entwicklungsumgebung macht es durchaus Sinn, wenn diese Ordner nicht im Projektordner liegen, da sie ansonsten in der Regel von der IDE auch indiziert werden, was bei Suchvorgängen oder beim Starten der IDE zu Performance Einbußen führen kann.

Um die Pfade also bei Symfony2 zu ändern, muss man einfach nur in der Klasse AppKernel die jeweiligen Funktionen der Parent Klasse überschreiben:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
class AppKernel extends Kernel
{
    ...
    public function getCacheDir()
    {
        return '/tmp/symfony2cache/';
    }
 
    public function getLogDir()
    {
        return '/tmp/symfony2logs_'.$this->environment;
    }
    ...
}
Veröffentlicht unter Symfony2 | Verschlagwortet mit , , , | Hinterlasse einen Kommentar

Nützliche Codeschnipsel – Arbeitstage zwischen zwei Datumsangaben mit Zend_Date berechnen

Hier mal eine eine kleine Klasse, um die Anzahl zwischen zwei Datumsangaben zu berechnen.
Es werden allerdings nur bundesweite Feiertage berücksichtigt. Wenn man auch Feiertage in einzelnen Bundesländern berücksichtigen möchte, kann man einfach die Variable $_nationalHolidays entsprechend anpassen.
Achtung: Die Klasse setzt eine Umgebung voraus, in der das Zend Framework per Autoload geladen werden kann.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
class MyCalenderUtils
{
 
    const DATE_FORMAT_DAY = 'dd.MM';
 
    /**
     * @var array
     */
    protected $_holidays = array();
 
    /**
     * @var array
     */
    protected $_nationalHolidays = array(
        '01.01', // Neujahr
        '01.05', // 1. Mai
        '03.10', // Tag der Einheit
        '25.12', // Weihnachten
        '26.12', // Weihnachten
    );
 
    /**
     * @param $year
     * @return $this
     */
    public function setHolidays($year)
    {
        $this->_holidays[$year] = array_merge($this->_nationalHolidays, $this->getEasterDays($year));
        return $this;
    }
 
    /**
     * @param $year
     * @return array
     */
    public function getHolidays($year)
    {
        if (!isset($this->_holidays[$year])) {
            $this->setHolidays($year);
        }
        return $this->_holidays[$year];
    }
 
    /**
     * @param $year
     * @return array
     */
    public function getEasterDays($year)
    {
        // ab PHP 5.3. könnte man auch die DateTime API von PHP nutzen
        $eastern          = new Zend_Date(easter_date($year));
        $a_eastern_days   = array();
        $a_eastern_days[] = $eastern->copyPart(null)->subDay(2)->toString(self::DATE_FORMAT_DAY); // Karfreitag
        $a_eastern_days[] = $eastern->copyPart(null)->addDay(1)->toString(self::DATE_FORMAT_DAY); // Ostermontag
        $a_eastern_days[] = $eastern->copyPart(null)->addDay(39)->toString(self::DATE_FORMAT_DAY); // Himmelfahrt
        $a_eastern_days[] = $eastern->copyPart(null)->addDay(50)->toString(self::DATE_FORMAT_DAY); // Pfingstmontag
        return $a_eastern_days;
    }
 
    /**
     * @param Zend_Date $date
     * @return bool
     */
    public function isHoliday(Zend_Date $date)
    {
        if (in_array($date->toString(self::DATE_FORMAT_DAY), $this->getHolidays($date->toString(Zend_Date::YEAR)))) {
            return true;
        }
        return false;
    }
 
    /**
     * @param $date
     * @return bool
     */
    public function isWeekend($date)
    {
        // nur Samstag und Sonntag beginnen mit einen 'S' ;-)
        if ($date->toString(Zend_Date::WEEKDAY_NARROW) == 'S')
        {
            return true;
        }
        return false;
    }
 
    /**
     * @param Zend_Date $date
     * @return bool
     */
    public function isWorkday(Zend_Date $date)
    {
        // prüfen ob Wochenende oder Feiertag
        if ($this->isWeekend($date) || $this->isHoliday($date)) {
            return false;
        }
        return true;
    }
}

Beispiel für die praktische Anwendung der Klasse:

1
2
3
4
5
6
7
8
9
10
$dateFrom = new Zend_Date('2014-03-10');
$dateTo   = new Zend_Date('2014-04-30');
$dayCounter = 0;
$myCalenderUtils = new MyCalenderUtils();
while ($dateTo->isLater($dateFrom->addDay(1))) {
    if ($myCalenderUtils->isWorkday($dateFrom)) {
       $dayCounter++;
    }
};
print "Arbeitstage: " . $dayCounter . "\n";
Veröffentlicht unter PHP | Verschlagwortet mit , , , , | Hinterlasse einen Kommentar

Magento – fehlende Übersetzungen im Developer Mode

In Magento gibt es das Problem/Feature, das bei eingeschaltetem Developer Mode einige Übersetzungen nicht funktionieren (das ist natürlich nur relevant, sofern man keinen englischsprachigen Shop betreibt).
Den Developer Mode kann man aktivieren, in dem man z.B. beim Apache in der Vhost Datei die Environment Variable wie folgt setzt:

1
SetEnv MAGE_IS_DEVELOPER_MODE "1"

Wenn der Developer Mode eingeschaltet ist, werden z.B. die Exceptions nicht geloggt, sondern direkt „geworfen“, da Magento einen eigenen Error Handler definiert hat.
Siehe Datei: app/code/core/Mage/Core/functions.php

1
2
3
4
5
6
$errorMessage .= ": {$errstr}  in {$errfile} on line {$errline}";
if (Mage::getIsDeveloperMode()) {
   throw new Exception($errorMessage);
} else {
   Mage::log($errorMessage, Zend_Log::ERR);
}

Beim Entwickeln ist es natürlich von Vorteil, wenn man Fehler direkt sieht und nicht immer erst im Logfile nachschauen muss.
Wer wissen möchte welche Auswirkungen der Devolper Mode noch hat, sollte einfach mal im Magento Code nach „Mage::getIsDeveloperMode“ suchen.

Allerdings führt das Einschalten des Developer Modes auch zu einem unschönen Nebeneffekt, und zwar werden selbst definierte Übersetzungstexte nicht mehr angezeigt, sofern sie bereits in einem anderen Modul definiert wurden.

Funktionsweise des Translation Moduls

Magento speichert alle Übersetzungstexte im Model Mage_Core_Model_Translate. Das Einlesen der CSV Files mit den Übersetzungen für die einzelnen Module funktioniert wird folgt:
Beim Laden der Module wird in der Init Funktion der Klasse Mage_Core_Model_Translate die Funktion _loadModuleTranslation aufgerufen.
Siehe: Mage_Core_Model_Translate

1
2
3
4
5
6
7
8
9
10
11
public function init($area, $forceReload = false)
{
    ...
    $this->_data = array();
 
    foreach ($this->getModulesConfig() as $moduleName=>$info) {
        $info = $info->asArray();
        $this->_loadModuleTranslation($moduleName, $info['files'], $forceReload);
    }
    ...
}

In dieser Funktion wird dann das jeweilige CSV File eingelesen

1
2
3
4
5
6
7
8
protected function _loadModuleTranslation($moduleName, $files, $forceReload=false)
{
    foreach ($files as $file) {
        $file = $this->_getModuleFilePath($moduleName, $file);
        $this->_addData($this->_getFileData($file), $moduleName, $forceReload);
    }
    return $this;
}

In der Funktion _addData werden alle Übersetzungstexte aus dem unterschiedlichen Quellen (CSV, Files, Datenbank, XML Files) als Array in der Variable $_data gespeichert.
In $data werden die zu übersetzenden Texte als Array übergeben, Scope enthält standardmäßig den Namespace und den Namen des Moduls (Namespace_Modulename).
Siehe Datei: app/code/core/Mage/Core/Model/Translate.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
protected function _addData($data, $scope, $forceReload=false)
{
	foreach ($data as $key => $value) {
	    if ($key === $value) {
		continue;
	    }
	    $key    = $this->_prepareDataString($key);
	    $value  = $this->_prepareDataString($value);
 
	    if ($scope && isset($this->_dataScope[$key]) && !$forceReload ) {
		/**
		 * Checking previos value
		 */
		$scopeKey = $this->_dataScope[$key] . self::SCOPE_SEPARATOR . $key;
		if (!isset($this->_data[$scopeKey])) {
		    if (isset($this->_data[$key])) {
		        $this->_data[$scopeKey] = $this->_data[$key];
		        /**
		         * Not allow use translation not related to module
                         */
		        if (Mage::getIsDeveloperMode()) {
		            unset($this->_data[$key]);
		        }
		    }
		}
		$scopeKey = $scope . self::SCOPE_SEPARATOR . $key;
		$this->_data[$scopeKey] = $value;
	    }
	    else {
		$this->_data[$key]     = $value;
		$this->_dataScope[$key]= $scope;
	    }
	}
	return $this;
}

Die Übersetzungen in den Templates werden über die Funktion Mage_Core_Block_Abstract::__() geladen:
Mage_Core_Block_Abstract

1
2
3
4
5
6
7
public function __()
{
    $args = func_get_args();
    $expr = new Mage_Core_Model_Translate_Expr(array_shift($args), $this->getModuleName());
    array_unshift($args, $expr);
    return Mage::app()->getTranslator()->translate($args);
}

Mage_Core_Model_Translate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected function _getTranslatedString($text, $code)
{
    $translated = '';
    if (array_key_exists($code, $this->getData())) {
        $translated = $this->_data[$code];
    }
    elseif (array_key_exists($text, $this->getData())) {
        $translated = $this->_data[$text];
    }
    else {
        $translated = $text;
    }
    return $translated;
}

Das Problem mit der fehlenden Übersetzung

Das oben beschriebene Problem tritt bei den Übersetzungsvariablen auf, die in mehrere Modulen definiert sind.
Das heißt im Developer Mode werden die Übersetzungen von Texten, die in mehreren CSV Files von unterschiedlichen Modulen enthalten sind, unter einem anderen Namensraum (Scope) gespeichert.
Beim Parsen der CSV Datei des ersten gefundenen Moduls wird der Wert im Array $_data gespeichert. Beim Verarbeiten der CSV Datei des zweiten Moduls wird der Wert wieder gelöscht:

if (Mage::getIsDeveloperMode()) {
   unset($this->_data[$key]);
}

Anschließend wird es mit unter einem anderen Scope im Array $_data gespeichert.

$scopeKey = $scope . self::SCOPE_SEPARATOR . $key;
$this->_data[$scopeKey] = $value;

Beispiel:

Um das Ganze mal zu verdeutlichen, hier mal ein Beispiel anhand des Textes „Loading next step…“, der sowohl in einem Core Modul, als auch in einem eigenen Modul übersetzt wurde:

1. Aufruf der Funktion Mage_Core_Model_Translate::_addData beim Laden des Core Moduls Mage_Checkout
Übersetzungfile: „/var/www/VaaTrunk/app/locale/de_DE/Mage_Checkout.csv“
Wert der einzelnen Variablen in der Funktion _addData

$key:      "Loading next step..."		
$scope:    "Mage_Checkout"
$value:    "Nächster Schritt wird geladen ..."

Nach dem Speichern im Translation Array

$scopeKey: "Mage_Checkout::Loading next step..."
$this->_data["Loading next step..."]  = "Nächster Schritt wird geladen ...";
$this->_dataScope["Loading next step..."]= "Mage_Checkout";

2. Aufruf der Funktion Mage_Core_Model_Translate::_addData beim Laden des eigenen Moduls Namespace_Modulname
Übersetzungfile: „/var/www/VaaTrunk/app/locale/de_DE/Namespace_Modulname.csv“

$key:      "Loading next step..."		
$scope:    "Namespace_Modulname"
$scopeKey: "Mage_Checkout::Loading next step..."

Da der Wert bereits unter einen anderen Scope vorhanden ist, wird er wieder gelöscht:

unset($this->_data["Loading next step..."]);

Werte nach dem Löschen

$scopeKey: "Namespace_Modulname::Loading next step..."
$value:    "Lade nächsten Schritt..."

Anschließend wird der Wert mit dem neuen Scope Key im Übersetzungs Array gespeichert

$this->_data["Mage_Checkout::Loading next step..."] = "Lade nächsten Schritt...";

Wenn man jetzt also im Template den String mit der Übersetzungsfunktion $this->__(‚Loading next step…‘) laden will, kann die Übersetzung nicht geladen werden, da der Text ja jetzt mit dem Scope Key „Namespace_Modulname::Loading next step…“ gespeichert ist.
Wird ein Wert im _data Array nicht gefunden, so wird der original String, der an die Übersetzungfunktion übergeben wurde, verwendet.
Mann müsste ihn also wie folgt laden, damit es funktioniert:

$this->__('Namespace_Modulname::Loading next step...')

Ob das jetzt ein Bug oder ein Feature ist, muss jeder selbst entscheiden.

Veröffentlicht unter Magento | Verschlagwortet mit , , , | Hinterlasse einen Kommentar