[FEATURE] Add translation handling module
authorSebastian fischer <typo3@evoweb.de>
Sun, 19 Aug 2012 12:22:52 +0000 (14:22 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Thu, 30 Aug 2012 14:20:46 +0000 (16:20 +0200)
As the new extension manager for 6.0 does not handle translation
handling a module is needed to select and update translations of
extensions.

This change to the sysext lang extensions ands a module with
which it is possible to both change select available languages
as well update the translation files for extensions.

Change-Id: I2a4f53fa01a1ba157a2ef8093130f80e06b74b72
Resolves: #39963
Releases: 6.0
Reviewed-on: http://review.typo3.org/13925
Reviewed-by: Christian Kuhn
Tested-by: Christian Kuhn
28 files changed:
typo3/sysext/lang/Classes/Controller/LanguageController.php [new file with mode: 0644]
typo3/sysext/lang/Classes/Domain/Model/Extension.php [new file with mode: 0644]
typo3/sysext/lang/Classes/Domain/Model/Language.php [new file with mode: 0644]
typo3/sysext/lang/Classes/Domain/Model/LanguageSelectionForm.php [new file with mode: 0644]
typo3/sysext/lang/Classes/Domain/Model/UpdateTranslationForm.php [new file with mode: 0644]
typo3/sysext/lang/Classes/Domain/Repository/ExtensionRepository.php [new file with mode: 0644]
typo3/sysext/lang/Classes/Domain/Repository/LanguageRepository.php [new file with mode: 0644]
typo3/sysext/lang/Classes/Exception/Lang.php [new file with mode: 0644]
typo3/sysext/lang/Classes/Exception/Ter.php [new file with mode: 0644]
typo3/sysext/lang/Classes/Exception/XmlParser.php [new file with mode: 0644]
typo3/sysext/lang/Classes/LanguageService.php
typo3/sysext/lang/Classes/Utility/Connection/Ter.php [new file with mode: 0644]
typo3/sysext/lang/Resources/Private/.htaccess [new file with mode: 0644]
typo3/sysext/lang/Resources/Private/Language/locallang.xml [new file with mode: 0644]
typo3/sysext/lang/Resources/Private/Language/locallang_mod_language.xml [new file with mode: 0644]
typo3/sysext/lang/Resources/Private/Layouts/DocHeader.html [new file with mode: 0644]
typo3/sysext/lang/Resources/Private/Partials/ExtensionRow.html [new file with mode: 0644]
typo3/sysext/lang/Resources/Private/Partials/TranslationHeaders.html [new file with mode: 0644]
typo3/sysext/lang/Resources/Private/Templates/Language/Index.html [new file with mode: 0644]
typo3/sysext/lang/Resources/Public/Images/moduleicon.gif [new file with mode: 0644]
typo3/sysext/lang/Tests/Domain/Model/ExtensionTest.php [new file with mode: 0644]
typo3/sysext/lang/Tests/Domain/Model/LanguageSelectionFormTest.php [new file with mode: 0644]
typo3/sysext/lang/Tests/Domain/Model/LanguageTest.php [new file with mode: 0644]
typo3/sysext/lang/Tests/Domain/Model/UpdateTranslationFormTest.php [new file with mode: 0644]
typo3/sysext/lang/ext_emconf.php
typo3/sysext/lang/ext_icon.gif [new file with mode: 0644]
typo3/sysext/lang/ext_localconf.php
typo3/sysext/lang/ext_tables.php [new file with mode: 0644]

diff --git a/typo3/sysext/lang/Classes/Controller/LanguageController.php b/typo3/sysext/lang/Classes/Controller/LanguageController.php
new file mode 100644 (file)
index 0000000..d2a8522
--- /dev/null
@@ -0,0 +1,244 @@
+<?php
+namespace TYPO3\CMS\Lang\Controller;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Sebastian Fischer <typo3@evoweb.de>
+ *  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!
+ ***************************************************************/
+
+/**
+ * Language controller handling the selection of available languages and update of extension translations
+ *
+ * @author Sebastian Fischer <typo3@evoweb.de>
+ * @package lang
+ * @subpackage LanguageController
+ */
+class LanguageController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
+
+       /**
+        * @var integer
+        */
+       const TRANSLATION_CHECK_FOR_EXTENSION = 0;
+
+       /**
+        * @var integer
+        */
+       const TRANSLATION_UPDATE_FOR_EXTENSION = 1;
+
+       /**
+        * @var \TYPO3\CMS\Lang\Domain\Repository\LanguageRepository
+        */
+       protected $languageRepository;
+
+       /**
+        * @var \TYPO3\CMS\Lang\Domain\Repository\ExtensionRepository
+        */
+       protected $extensionRepository;
+
+       /**
+        * @var \TYPO3\CMS\Extensionmanager\Utility\Repository\Helper
+        */
+       protected $repositoryHelper;
+
+       /**
+        * @var array
+        */
+       protected $icons = array();
+
+       /**
+        * Inject the language repository
+        *
+        * @param \TYPO3\CMS\Lang\Domain\Repository\LanguageRepository $repository
+        * @return void
+        */
+       public function injectLanguageRepository(\TYPO3\CMS\Lang\Domain\Repository\LanguageRepository $repository) {
+               $this->languageRepository = $repository;
+       }
+
+       /**
+        * Inject the extension repository
+        *
+        * @param \TYPO3\CMS\Lang\Domain\Repository\ExtensionRepository $repository
+        * @return void
+        */
+       public function injectExtensionRepository(\TYPO3\CMS\Lang\Domain\Repository\ExtensionRepository $repository) {
+               $this->extensionRepository = $repository;
+       }
+
+       /**
+        * Inject the repository helper
+        *
+        * @param \TYPO3\CMS\Extensionmanager\Utility\Repository\Helper $repositoryHelper
+        * @return void
+        */
+       public function injectRepositoryHelper(\TYPO3\CMS\Extensionmanager\Utility\Repository\Helper $repositoryHelper) {
+               $this->repositoryHelper = $repositoryHelper;
+       }
+
+       /**
+        * Index action
+        *
+        * @return void
+        */
+       public function indexAction() {
+               $languages = $this->languageRepository->findAll();
+               $selectedLanguages = $this->languageRepository->findSelected();
+               $extensions = $this->extensionRepository->findAll();
+
+               if ($this->request->hasArgument('updateResult')) {
+                       $extensions = $this->mergeUpdateResult($extensions, $this->request->getArgument('updateResult'));
+               }
+
+               $this->view->assign('languages', $languages);
+               $this->view->assign('selectedLanguages', $selectedLanguages);
+               $this->view->assign('extensions', $extensions);
+       }
+
+       /**
+        * Merge update results after translation update into extension models for rendering
+        *
+        * @param array $extensions
+        * @param array $updateResult
+        * @return array
+        */
+       protected function mergeUpdateResult(array $extensions, array $updateResult) {
+               foreach ($updateResult as $key => $messages) {
+                       $extensions[$key]->setUpdateResult($messages);
+               }
+
+               return $extensions;
+       }
+
+       /**
+        * Save selected locale(s)
+        *
+        * @param \TYPO3\CMS\Lang\Domain\Model\LanguageSelectionForm $form
+        * @return void
+        */
+       public function saveSelectedLocaleAction(\TYPO3\CMS\Lang\Domain\Model\LanguageSelectionForm $form) {
+               $selectedLanguages = array();
+               foreach ($form->getLocale() as $locale => $value) {
+                       if ($value) {
+                               $selectedLanguages[] = $locale;
+                       }
+               }
+
+               $this->languageRepository->updateSelectedLanguages($selectedLanguages);
+
+               $this->forward('index');
+       }
+
+       /**
+        * Initializes icons used in the update translation prozess
+        *
+        * @return void
+        */
+       protected function initializeUpdateTranslationAction() {
+               $this->icons = array(
+                       'ok' => \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-status-checked'),
+                       'unavailable' => \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('actions-document-info'),
+                       'failed' => \TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIcon('status-status-permission-denied'),
+               );
+       }
+
+       /**
+        * Update translation(s)
+        *
+        * @param \TYPO3\CMS\Lang\Domain\Model\UpdateTranslationForm $form
+        * @return void
+        */
+       public function updateTranslationAction(\TYPO3\CMS\Lang\Domain\Model\UpdateTranslationForm $form) {
+               $result = array();
+
+               try {
+                       if (count($form->getSelectedLanguages())) {
+                               foreach ($form->getExtensions() as $extension) {
+                                       $result[$extension] = $this->checkTranslationForExtension($form->getSelectedLanguages(), $extension);
+                               }
+                       }
+               } catch (\Exception $exception) {
+                       $flashMessage = $this->objectManager->create(
+                               'TYPO3\CMS\Core\Messaging\FlashMessage',
+                               htmlspecialchars($exception->getMessage()),
+                               '',
+                               \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
+                       );
+                       \TYPO3\CMS\Core\Messaging\FlashMessageQueue::addMessage($flashMessage);
+               }
+
+               $this->forward('index', NULL, NULL, array('updateResult' => $result));
+       }
+
+       /**
+        * Check translation(s) for extension
+        *
+        * @param array $languages
+        * @param string $extensionKey
+        * @return array
+        */
+       public function checkTranslationForExtension($languages, $extensionKey) {
+               $result = array();
+
+               /** @var $terConnection \TYPO3\CMS\Lang\Utility\Connection\Ter */
+               $terConnection = $this->objectManager->create('TYPO3\CMS\Lang\Utility\Connection\Ter');
+               $mirrorUrl = $this->repositoryHelper->getMirrors()->getMirrorUrl();
+
+               $fetch = $terConnection->fetchTranslationStatus($extensionKey, $mirrorUrl);
+               foreach ($languages as $lang) {
+                       if (!isset($fetch[$lang])) {
+                                       // No translation available
+                               $result[$lang] = array(
+                                       'icon' => $this->icons['unavailable'],
+                                       'message' => 'translation_n_a'
+                               );
+                       } else {
+                               $zip = PATH_site . 'typo3temp' . DIRECTORY_SEPARATOR . $extensionKey . '-l10n-' . $lang . '.zip';
+                               $md5OfTranslationFile = '';
+                               if (is_file($zip)) {
+                                       $md5OfTranslationFile = md5_file($zip);
+                               }
+
+                               if ($md5OfTranslationFile !== $fetch[$lang]['md5']) {
+                                       $update = $terConnection->updateTranslation($extensionKey, $lang, $mirrorUrl);
+
+                                       $result[$lang] = $update ?
+                                               array(
+                                                       'icon' => $this->icons['ok'],
+                                                       'message' => 'translation_msg_updated'
+                                               ) :
+                                               array(
+                                                       'icon' => $this->icons['failed'],
+                                                       'message' => 'translation_msg_failed'
+                                               );
+                               } else {
+                                               // Translation is up to date
+                                       $result[$lang] = array(
+                                               'icon' => $this->icons['ok'],
+                                               'message' => 'translation_status_uptodate'
+                                       );
+                               }
+                       }
+               }
+
+               return $result;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Classes/Domain/Model/Extension.php b/typo3/sysext/lang/Classes/Domain/Model/Extension.php
new file mode 100644 (file)
index 0000000..7c1ccbf
--- /dev/null
@@ -0,0 +1,196 @@
+<?php
+namespace TYPO3\CMS\Lang\Domain\Model;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Sebastian Fischer <typo3@evoweb.de>
+ *  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!
+ ***************************************************************/
+
+/**
+ * Extension model
+ *
+ * @author Sebastian Fischer <typo3@evoweb.de>
+ * @package TYPO3
+ * @subpackage lang
+ */
+class Extension extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+       /**
+        * @var string
+        */
+       protected $key = '';
+
+       /**
+        * @var string
+        */
+       protected $title = '';
+
+       /**
+        * @var string
+        */
+       protected $icon = '';
+
+       /**
+        * @var integer
+        */
+       protected $version = '';
+
+       /**
+        * @var string
+        */
+       protected $stateCls = '';
+
+       /**
+        * @var string
+        */
+       protected $versionislower = '';
+
+       /**
+        * @var string
+        */
+       protected $maxversion = '';
+
+       /**
+        * @var array
+        */
+       protected $updateResult = array();
+
+       /**
+        * Construtor of the extension model.
+        *
+        * @param string $key The extension key
+        * @param string $title Title of the extension
+        * @param string $icon Icon representing the extension
+        */
+       public function __construct($key = '', $title= '', $icon = '') {
+               $this->setKey($key);
+               $this->setTitle($title);
+               $this->setIcon($icon);
+       }
+
+       /**
+        * Setter for the icon
+        *
+        * @param string $icon ext_icon path relative to typo3 folder like ../typo3conf/ext/extensionkey/ext_icon.gif
+        * @return void
+        */
+       public function setIcon($icon) {
+               $this->icon = $icon;
+       }
+
+       /**
+        * Getter for the icon
+        *
+        * @return string ext_icon path relative to typo3 folder
+        */
+       public function getIcon() {
+               return $this->icon;
+       }
+
+       /**
+        * Setter for the key
+        *
+        * @param string $key
+        * @return void
+        */
+       public function setKey($key) {
+               $this->key = $key;
+       }
+
+       /**
+        * Getter for the key
+        *
+        * @return string
+        */
+       public function getKey() {
+               return $this->key;
+       }
+
+       /**
+        * Setter for the title
+        *
+        * @param string $title
+        * @return void
+        */
+       public function setTitle($title) {
+               $this->title = $title;
+       }
+
+       /**
+        * Getter for the title
+        *
+        * @return string
+        */
+       public function getTitle() {
+               return $this->title;
+       }
+
+       /**
+        * Setter for the version
+        *
+        * @param integer $version Needs to have a valid version format like 1003007
+        * @return void
+        */
+       public function setVersion($version) {
+               $this->version = $version;
+       }
+
+       /**
+        * Setter for the version from string
+        *
+        * @param string $version Needs to have a format like '1.3.7' and converts it into an integer like 1003007 before setting the version
+        * @see \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger
+        * @return void
+        */
+       public function setVersionFromString($version) {
+               $this->version = \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger($version);
+       }
+
+       /**
+        * Getter for the version
+        *
+        * @return integer interpretion of the extension version
+        */
+       public function getVersion() {
+               return $this->version;
+       }
+
+       /**
+        * Setter for updateResult
+        *
+        * @param array $updateResult Needs to be in a structure like array('icon' => '', 'message' => '')
+        * @return void
+        */
+       public function setUpdateResult($updateResult) {
+               $this->updateResult = (array) $updateResult;
+       }
+
+       /**
+        * Getter for updateResult
+        *
+        * @return array returns the update result as an arry in the structure like array('icon' => '', 'message' => '')
+        */
+       public function getUpdateResult() {
+               return $this->updateResult;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Classes/Domain/Model/Language.php b/typo3/sysext/lang/Classes/Domain/Model/Language.php
new file mode 100644 (file)
index 0000000..6e97553
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+namespace TYPO3\CMS\Lang\Domain\Model;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Sebastian Fischer <typo3@evoweb.de>
+ *  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!
+ ***************************************************************/
+
+/**
+ * Language model
+ *
+ * @author Sebastian Fischer <typo3@evoweb.de>
+ * @package TYPO3
+ * @subpackage lang
+ */
+class Language extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+       /**
+        * @var string
+        */
+       protected $locale = '';
+
+       /**
+        * @var string
+        */
+       protected $language = '';
+
+       /**
+        * @var boolean
+        */
+       protected $selected = FALSE;
+
+       /**
+        * Constructor of the language model
+        *
+        * @param string $locale
+        * @param string $language
+        * @param boolean $selected
+        */
+       public function __construct($locale = '', $language = '', $selected = FALSE) {
+               $this->setLocale($locale);
+               $this->setLanguage($language);
+               $this->setSelected($selected);
+       }
+
+       /**
+        * Setter for the language
+        *
+        * @param string $language the label of the language
+        * @return void
+        */
+       public function setLanguage($language) {
+               $this->language = $language;
+       }
+
+       /**
+        * Getter for the language
+        *
+        * @return string
+        */
+       public function getLanguage() {
+               return $this->language;
+       }
+
+       /**
+        * Setter for the locale
+        *
+        * @param string $locale the locale for the language like da, nl or de
+        * @return void
+        */
+       public function setLocale($locale) {
+               $this->locale = $locale;
+       }
+
+       /**
+        * Getter for the locale
+        *
+        * @return string
+        */
+       public function getLocale() {
+               return $this->locale;
+       }
+
+       /**
+        * Setter for the selected
+        *
+        * @param boolean $selected wether the language is available or not
+        * @return void
+        */
+       public function setSelected($selected) {
+               $this->selected = $selected ? TRUE : FALSE;
+       }
+
+       /**
+        * Getter for the selected
+        *
+        * @return boolean
+        */
+       public function getSelected() {
+               return $this->selected;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Classes/Domain/Model/LanguageSelectionForm.php b/typo3/sysext/lang/Classes/Domain/Model/LanguageSelectionForm.php
new file mode 100644 (file)
index 0000000..2c35afe
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+namespace TYPO3\CMS\Lang\Domain\Model;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Sebastian Fischer <typo3@evoweb.de>
+ *  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!
+ ***************************************************************/
+
+/**
+ * Model to contain all information from the form changing the selection of available languages
+ *
+ * @author Sebastian Fischer <typo3@evoweb.de>
+ * @package TYPO3
+ * @subpackage lang
+ */
+class LanguageSelectionForm extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+       /**
+        * @var array
+        */
+       protected $locale = array();
+
+       /**
+        * Setter for the choosen locale
+        *
+        * @param array $locale all locale that were selected in the form
+        * @return void
+        */
+       public function setLocale(array $locale) {
+               $this->locale = $locale;
+       }
+
+       /**
+        * Getter for the choosen locale
+        *
+        * @return array
+        */
+       public function getLocale() {
+               return $this->locale;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Classes/Domain/Model/UpdateTranslationForm.php b/typo3/sysext/lang/Classes/Domain/Model/UpdateTranslationForm.php
new file mode 100644 (file)
index 0000000..b9a0e71
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+namespace TYPO3\CMS\Lang\Domain\Model;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Sebastian Fischer <typo3@evoweb.de>
+ *  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!
+ ***************************************************************/
+
+/**
+ * Model to contain all information from the form requesting to update translations
+ *
+ * @author Sebastian Fischer <typo3@evoweb.de>
+ * @package TYPO3
+ * @subpackage lang
+ */
+class UpdateTranslationForm extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
+
+       /**
+        * @var array
+        */
+       protected $selectedLanguages = array();
+
+       /**
+        * @var array
+        */
+       protected $extensions = array();
+
+       /**
+        * Setter for the extensions
+        *
+        * @param array $extensions of extensions that were requested
+        * @return void
+        */
+       public function setExtensions(array $extensions) {
+               $this->extensions = $extensions;
+       }
+
+       /**
+        * Getter for the extensions
+        *
+        * @return array
+        */
+       public function getExtensions() {
+               return $this->extensions;
+       }
+
+       /**
+        * Setter for the selected languages
+        *
+        * @param array $selectedLanguages selected languages that were requested
+        * @return void
+        */
+       public function setSelectedLanguages(array $selectedLanguages) {
+               $this->selectedLanguages = $selectedLanguages;
+       }
+
+       /**
+        * Getter for the selected languages
+        *
+        * @return array
+        */
+       public function getSelectedLanguages() {
+               return $this->selectedLanguages;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Classes/Domain/Repository/ExtensionRepository.php b/typo3/sysext/lang/Classes/Domain/Repository/ExtensionRepository.php
new file mode 100644 (file)
index 0000000..c4a542a
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+namespace TYPO3\CMS\Lang\Domain\Repository;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Sebastian Fischer <typo3@evoweb.de>
+ *  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!
+ ***************************************************************/
+
+/**
+ * Extension repository
+ *
+ * @author Sebastian Fischer <typo3@evoweb.de>
+ * @package TYPO3
+ * @subpackage lang
+ */
+class ExtensionRepository {
+       /**
+        * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
+        */
+       protected $objectManager;
+
+       /**
+        * @var \TYPO3\CMS\Extensionmanager\Utility\ListUtility
+        */
+       protected $listUtility;
+
+       /**
+        * @var array
+        */
+       protected $extensions = array();
+
+       /**
+        * Injects the object manager
+        *
+        * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager
+        * @return void
+        */
+       public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager) {
+               $this->objectManager = $objectManager;
+       }
+
+       /**
+        * Inject the list utility
+        *
+        * @param \TYPO3\CMS\Extensionmanager\Utility\ListUtility $listUtility
+        * @return void
+        */
+       public function injectListUtility(\TYPO3\CMS\Extensionmanager\Utility\ListUtility $listUtility) {
+               $this->listUtility = $listUtility;
+       }
+
+       /**
+        * Returns all objects of this repository.
+        *
+        * @return array
+        */
+       public function findAll() {
+               if (!count($this->extensions)) {
+                       $availableExtensions = $this->listUtility->getAvailableExtensions();
+                       $availableAndInstalledExtensions = $this->listUtility->getAvailableAndInstalledExtensions($availableExtensions);
+                       $availableAndInstalledExtensions = $this->listUtility->enrichExtensionsWithEmConfAndTerInformation(
+                               $availableAndInstalledExtensions
+                       );
+
+                       foreach ($availableAndInstalledExtensions as $entry) {
+                               /** @var $extension \TYPO3\CMS\Lang\Domain\Model\Extension */
+                               $extension = $this->objectManager->create(
+                                       'TYPO3\CMS\Lang\Domain\Model\Extension',
+                                       $entry['key'],
+                                       $entry['title'],
+                                       $this->getExtensionIconWithPath($entry)
+                               );
+                               $extension->setVersionFromString($entry['version']);
+                               $this->extensions[$entry['key']] = $extension;
+                       }
+
+                               // Sort the list by extension key
+                       ksort($this->extensions);
+               }
+
+               return $this->extensions;
+       }
+
+       /**
+        * @param array $extensionEntry
+        * @return string
+        */
+       protected function getExtensionIconWithPath($extensionEntry) {
+               $extensionIcon = $GLOBALS['TYPO3_LOADED_EXT'][$extensionEntry['key']]['ext_icon'];
+               if (empty($extensionIcon)) {
+                       $extensionIcon = \TYPO3\CMS\Core\Extension\ExtensionManager::getExtensionIcon(PATH_site . $extensionEntry['siteRelPath'] . '/');
+               }
+
+               if (empty($extensionIcon)) {
+                       $extensionIcon = '/typo3/clear.gif';
+               } else {
+                       $extensionIcon = '../' . $extensionEntry['siteRelPath'] . '/' . $extensionIcon;
+               }
+
+               return $extensionIcon;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Classes/Domain/Repository/LanguageRepository.php b/typo3/sysext/lang/Classes/Domain/Repository/LanguageRepository.php
new file mode 100644 (file)
index 0000000..450b582
--- /dev/null
@@ -0,0 +1,184 @@
+<?php
+namespace TYPO3\CMS\Lang\Domain\Repository;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Sebastian Fischer <typo3@evoweb.de>
+ *  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!
+ ***************************************************************/
+
+/**
+ * Language repository
+ *
+ * @author Sebastian Fischer <typo3@evoweb.de>
+ * @package lang
+ * @subpackage LanguageRepository
+ */
+class LanguageRepository {
+
+       /**
+        * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
+        */
+       protected $objectManager;
+
+       /**
+        * @var array
+        */
+       protected $selectedLanguages = array();
+
+       /**
+        * @var \TYPO3\CMS\Core\Localization\Locales
+        */
+       protected $locales;
+
+       /**
+        * @var array
+        */
+       protected $languages = array();
+
+       /**
+        * @var string
+        */
+       protected $configurationPath = 'EXTCONF/lang';
+
+       /**
+        * Constructor of the language repository
+        */
+       public function __construct() {
+               try {
+                       $globalSettings = \TYPO3\CMS\Core\Configuration\ConfigurationManager::getLocalConfigurationValueByPath($this->configurationPath);
+                       $this->selectedLanguages = (array) $globalSettings['availableLanguages'];
+               } catch (\Exception $e) {
+                       \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath(
+                               $this->configurationPath,
+                               array('availableLanguages' => array())
+                       );
+               }
+       }
+
+       /**
+        * Injects the object manager
+        *
+        * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager
+        * @return void
+        */
+       public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager) {
+               $this->objectManager = $objectManager;
+       }
+
+       /**
+        * Injects the locales
+        *
+        * @param \TYPO3\CMS\Core\Localization\Locales $locales
+        * @return void
+        */
+       public function injectLocales(\TYPO3\CMS\Core\Localization\Locales $locales) {
+               $this->locales = $locales;
+       }
+
+       /**
+        * Returns all objects of this repository.
+        *
+        * @return array
+        */
+       public function findAll() {
+               if (!count($this->languages)) {
+                       $languages = $this->locales->getLanguages();
+                       array_shift($languages);
+
+                       foreach ($languages as $locale => $language) {
+                               $label = htmlspecialchars($GLOBALS['LANG']->sL('LLL:EXT:setup/mod/locallang.xml:lang_' . $locale));
+                               if ($label === '') {
+                                       $label = htmlspecialchars($language);
+                               }
+
+                               $this->languages[$locale] = $this->objectManager->create(
+                                       'TYPO3\CMS\Lang\Domain\Model\Language',
+                                       $locale,
+                                       $label,
+                                       in_array($locale, $this->selectedLanguages)
+                               );
+                       }
+
+                       usort($this->languages, function($a, $b) {
+                               /** @var $a \TYPO3\CMS\Lang\Domain\Model\Language */
+                               /** @var $b \TYPO3\CMS\Lang\Domain\Model\Language */
+                               if ($a->getLanguage() == $b->getLanguage()) {
+                                       return 0;
+                               }
+                               return $a->getLanguage() < $b->getLanguage() ? -1 : 1;
+                       });
+               }
+
+               return $this->languages;
+       }
+
+       /**
+        * Find selected languages
+        *
+        * @return array
+        */
+       public function findSelected() {
+               $languages = $this->findAll();
+
+               $result = array();
+               /** @var $language \TYPO3\CMS\Lang\Domain\Model\Language */
+               foreach ($languages as $language) {
+                       if ($language->getSelected()) {
+                               $result[] = $language;
+                       }
+               }
+
+               return $result;
+       }
+
+       /**
+        * Update selected languages
+        *
+        * @param array $languages
+        * @return array
+        */
+       public function updateSelectedLanguages($languages) {
+                       // Add possible dependencies for selected languages
+               $dependencies = array();
+               foreach ($languages as $language) {
+                       $dependencies = array_merge($dependencies, $this->locales->getLocaleDependencies($language));
+               }
+               if (count($dependencies)) {
+                       $languages = array_unique(array_merge($languages, $dependencies));
+               }
+
+               $dir = count($languages) - count($this->selectedLanguages);
+               $diff = $dir < 0 ? array_diff($this->selectedLanguages, $languages) : array_diff($languages, $this->selectedLanguages);
+
+               \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath(
+                       $this->configurationPath,
+                       array('availableLanguages' => $languages)
+               );
+
+               return array(
+                       'success' => count($diff) > 0,
+                       'dir' => $dir,
+                       'diff' => array_values($diff),
+                       'languages' => $languages
+               );
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Classes/Exception/Lang.php b/typo3/sysext/lang/Classes/Exception/Lang.php
new file mode 100644 (file)
index 0000000..644a87e
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+namespace TYPO3\CMS\Lang\Exception;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Sebastian Fischer <typo3@evoweb.de>
+ *  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!
+ ***************************************************************/
+
+/**
+ * An exception when something is wrong within the lang
+ *
+ * @author Sebastian Fischer <typo3@evoweb.de>
+ * @package TYPO3
+ * @subpackage lang
+ */
+class Lang extends \TYPO3\CMS\Core\Exception {
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Classes/Exception/Ter.php b/typo3/sysext/lang/Classes/Exception/Ter.php
new file mode 100644 (file)
index 0000000..8c5ef97
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+namespace TYPO3\CMS\Lang\Exception;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Sebastian Fischer <typo3@evoweb.de>
+ *  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!
+ ***************************************************************/
+
+/**
+ * An exception when something is wrong within the lang
+ *
+ * @author Sebastian Fischer <typo3@evoweb.de>
+ * @package TYPO3
+ * @subpackage lang
+ */
+class Ter extends \TYPO3\CMS\Core\Exception {
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Classes/Exception/XmlParser.php b/typo3/sysext/lang/Classes/Exception/XmlParser.php
new file mode 100644 (file)
index 0000000..7e98f2e
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+namespace TYPO3\CMS\Lang\Exception;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Sebastian Fischer <typo3@evoweb.de>
+ *  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!
+ ***************************************************************/
+
+/**
+ * An exception when something is wrong within parsing the xml
+ *
+ * @author Sebastian Fischer <typo3@evoweb.de>
+ * @package TYPO3
+ * @subpackage lang
+ */
+class XmlParser extends \TYPO3\CMS\Core\Exception {
+}
+
+?>
\ No newline at end of file
index d0445f8..3b9e58c 100644 (file)
@@ -1,42 +1,29 @@
 <?php
 namespace TYPO3\CMS\Lang;
-
 /***************************************************************
  *  Copyright notice
- *
  *  (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
  *  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.
  *  A copy is found in the textfile GPL.txt and important notices to the license
  *  from the author is found in LICENSE.txt distributed with these scripts.
- *
- *
  *  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!
  ***************************************************************/
+
 /**
  * Contains the TYPO3 Backend Language class
- *
- * @author Kasper Skårhøj <kasperYYYY@typo3.com>
- */
-/**
- * Contains the TYPO3 Backend Language class
- *
  * For detailed information about how localization is handled,
- * please refer to the 'Inside TYPO3' document which descibes this.
- *
+ * please refer to the 'Inside TYPO3' document which describes this.
  * This class is normally instantiated as the global variable $LANG in typo3/template.php
  * It's only available in the backend and under certain circumstances in the frontend
  *
@@ -63,7 +50,7 @@ class LanguageService {
 
        /**
         * Array with alternative charsets for other languages.
-        * Moved to t3lib_cs, set internally from csConvObj!
+        * Moved to \TYPO3\CMS\Core\Charset\CharsetConverter, set internally from csConvObj!
         *
         * @var array
         */
@@ -85,7 +72,7 @@ class LanguageService {
 
        /**
         * Can contain labels and image references from the backend modules.
-        * Relies on t3lib_loadmodules to initialize modules after a global instance of $LANG has been created.
+        * Relies on \TYPO3\CMS\Backend\Module\ModuleLoader to initialize modules after a global instance of $LANG has been created.
         *
         * @var array
         */
@@ -106,7 +93,7 @@ class LanguageService {
        public $LL_labels_cache = array();
 
        /**
-        * instance of the "t3lib_cs" class. May be used by any application.
+        * instance of the "\TYPO3\CMS\Core\Charset\CharsetConverter" class. May be used by any application.
         *
         * @var \TYPO3\CMS\Core\Charset\CharsetConverter
         */
@@ -121,7 +108,7 @@ class LanguageService {
 
        /**
         * List of language dependencies for actual language. This is used for local variants of a language
-        * that depend on their "main" language, like Brazilian Portugese or Canadian French.
+        * that depend on their "main" language, like Brazilian Portuguese or Canadian French.
         *
         * @var array
         */
@@ -130,9 +117,8 @@ class LanguageService {
        /**
         * Initializes the backend language.
         * This is for example done in typo3/template.php with lines like these:
-        *
         * require (PATH_typo3 . 'sysext/lang/lang.php');
-        * $LANG = t3lib_div::makeInstance('language');
+        * $LANG = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('language');
         * $LANG->init($GLOBALS['BE_USER']->uc['lang']);
         *
         * @throws \RuntimeException
@@ -141,14 +127,14 @@ class LanguageService {
         */
        public function init($lang) {
                // Initialize the conversion object:
-               $this->csConvObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Charset\\CharsetConverter');
+               $this->csConvObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Core\Charset\CharsetConverter');
                $this->charSetArray = $this->csConvObj->charSetArray;
                // Initialize the parser factory object
-               $this->parserFactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Localization\\LocalizationFactory');
-               // Finding the requested language in this list based
+               $this->parserFactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Core\Localization\LocalizationFactory');
+               // Find the requested language in this list based
                // on the $lang key being inputted to this function.
                /** @var $locales \TYPO3\CMS\Core\Localization\Locales */
-               $locales = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Localization\\Locales');
+               $locales = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Core\Localization\Locales');
                // Language is found. Configure it:
                if (in_array($lang, $locales->getLocales())) {
                        // The current language key
@@ -175,10 +161,10 @@ class LanguageService {
        /**
         * Adds labels and image references from the backend modules to the internal moduleLabels array
         *
-        * @param array $arr Array with references to module labels, keys: ['labels']['tablabel'],
+        * @param array $arr Array with references to module labels, keys: ['labels']['table'],
         * @param string $prefix Module name prefix
         * @return void
-        * @see t3lib_loadModules
+        * @see \TYPO3\CMS\Backend\Module\ModuleLoader
         */
        public function addModuleLabels($arr, $prefix) {
                if (is_array($arr)) {
@@ -206,10 +192,9 @@ class LanguageService {
         *
         * @param string $str Input string
         * @return string Output string
-        * @access public
         */
        public function makeEntities($str) {
-               // Convert string back again, but using the full entity conversion:
+                       // Convert string back again, but using the full entity conversion:
                return $this->csConvObj->utf8_to_entities($str);
        }
 
@@ -223,10 +208,9 @@ class LanguageService {
         *
         * @param string $str Input string, encoded with UTF-8
         * @return string Output string, a JavaScript function: "String.fromCharCode(......)
-        * @access public
         */
        public function JScharCode($str) {
-               // Convert the UTF-8 string into a array of char numbers:
+                       // Convert the UTF-8 string into a array of char numbers:
                $nArr = $this->csConvObj->utf8_to_numberarray($str);
                return ('String.fromCharCode(' . implode(',', $nArr)) . ')';
        }
@@ -234,7 +218,7 @@ class LanguageService {
        /**
         * Debugs localization key.
         *
-        * @param $value Value to debug
+        * @param string $value value to debug
         * @return string
         */
        public function debugLL($value) {
@@ -248,10 +232,9 @@ class LanguageService {
         * @param string $index Label key
         * @param boolean $hsc If set, the return value is htmlspecialchar'ed
         * @return string
-        * @access public
         */
        public function getLL($index, $hsc = FALSE) {
-               // Get Local Language
+                       // Get Local Language
                if (isset($GLOBALS['LOCAL_LANG'][$this->lang][$index][0]['target'])) {
                        $output = $GLOBALS['LOCAL_LANG'][$this->lang][$index][0]['target'];
                } else {
@@ -271,15 +254,18 @@ class LanguageService {
         * @param array $localLanguage $LOCAL_LANG array to get label key from
         * @param boolean $hsc If set, the return value is htmlspecialchar'ed
         * @return string
-        * @access public
         */
        public function getLLL($index, $localLanguage, $hsc = FALSE) {
-               // Get Local Language. Special handling for all extensions that
-               // read PHP LL files and pass arrays here directly.
-               $value = is_string($localLanguage[$this->lang][$index]) ? $localLanguage[$this->lang][$index] : $localLanguage[$this->lang][$index][0]['target'];
-               // Fallback to default language
+                       // Get Local Language. Special handling for all extensions that
+                       // read PHP LL files and pass arrays here directly.
+               $value = is_string($localLanguage[$this->lang][$index]) ?
+                       $localLanguage[$this->lang][$index] :
+                       $localLanguage[$this->lang][$index][0]['target'];
+                       // Fallback to default language
                if (trim($value) === '') {
-                       $value = is_string($localLanguage['default'][$index]) ? $localLanguage['default'][$index] : $localLanguage['default'][$index][0]['target'];
+                       $value = is_string($localLanguage['default'][$index]) ?
+                               $localLanguage['default'][$index] :
+                               $localLanguage['default'][$index][0]['target'];
                }
                if ($hsc) {
                        $value = htmlspecialchars($value);
@@ -300,24 +286,23 @@ class LanguageService {
         * @param string $input Label key/reference
         * @param boolean $hsc If set, the return value is htmlspecialchar'ed
         * @return string
-        * @access public
         */
        public function sL($input, $hsc = FALSE) {
-               // If cached label
+                       // If cached label
                if (!isset($this->LL_labels_cache[$this->lang][$input]) && substr($input, 0, 4) === 'LLL:') {
                        $restStr = trim(substr($input, 4));
                        $extPrfx = '';
-                       // ll-file refered to is found in an extension.
+                               // ll-file refered to is found in an extension.
                        if (!strcmp(substr($restStr, 0, 4), 'EXT:')) {
                                $restStr = trim(substr($restStr, 4));
                                $extPrfx = 'EXT:';
                        }
                        $parts = explode(':', $restStr);
                        $parts[0] = $extPrfx . $parts[0];
-                       // Getting data if not cached
+                               // Getting data if not cached
                        if (!isset($this->LL_files_cache[$parts[0]])) {
                                $this->LL_files_cache[$parts[0]] = $this->readLLfile($parts[0]);
-                               // If the current language is found in another file, load that as well:
+                                       // If the current language is found in another file, load that as well:
                                $lFileRef = $this->localizedFileRef($parts[0]);
                                if (($lFileRef && is_string($this->LL_files_cache[$parts[0]][$this->lang])) && $this->LL_files_cache[$parts[0]][$this->lang] == 'EXT') {
                                        $tempLL = $this->readLLfile($lFileRef);
@@ -326,12 +311,12 @@ class LanguageService {
                        }
                        $this->LL_labels_cache[$this->lang][$input] = $this->getLLL($parts[1], $this->LL_files_cache[$parts[0]]);
                }
-               // For the cached output charset conversion has already happened!
-               // So perform HSC right here.
+                       // For the cached output charset conversion has already happened!
+                       // So perform HSC right here.
                if (isset($this->LL_labels_cache[$this->lang][$input])) {
                        $output = $this->LL_labels_cache[$this->lang][$input];
                } else {
-                       // Use a constant non-localizable label
+                               // Use a constant non-localizable label
                        $output = $input;
                }
                if ($hsc) {
@@ -347,37 +332,36 @@ class LanguageService {
         *
         * @param string $table Table name found as key in global array $TCA_DESCR
         * @return void
-        * @access public
         */
        public function loadSingleTableDescription($table) {
-               // First the 'table' cannot already be loaded in [columns]
-               // and secondly there must be a references to locallang files available in [refs]
+                       // First the 'table' cannot already be loaded in [columns]
+                       // and secondly there must be a references to locallang files available in [refs]
                if ((is_array($GLOBALS['TCA_DESCR'][$table]) && !isset($GLOBALS['TCA_DESCR'][$table]['columns'])) && is_array($GLOBALS['TCA_DESCR'][$table]['refs'])) {
-                       // Init $TCA_DESCR for $table-key
+                               // Init $TCA_DESCR for $table-key
                        $GLOBALS['TCA_DESCR'][$table]['columns'] = array();
-                       // Get local-lang for each file in $TCA_DESCR[$table]['refs'] as they are ordered.
+                               // Get local-lang for each file in $TCA_DESCR[$table]['refs'] as they are ordered.
                        foreach ($GLOBALS['TCA_DESCR'][$table]['refs'] as $llfile) {
                                $localLanguage = $this->includeLLFile($llfile, 0, 1);
-                               // Traverse all keys
+                                       // Traverse all keys
                                if (is_array($localLanguage['default'])) {
                                        foreach ($localLanguage['default'] as $lkey => $lVal) {
-                                               $type = '';
-                                               $fieldName = '';
-                                               // Exploding by '.':
-                                               // 0-n => fieldname,
-                                               // n+1 => type from (alttitle, description, details, syntax, image_descr,image,seeAlso),
-                                               // n+2 => special instruction, if any
+                                                       // Exploding by '.':
+                                                       // 0-n => fieldname,
+                                                       // n+1 => type from (alttitle, description, details, syntax, image_descr,image,seeAlso),
+                                                       // n+2 => special instruction, if any
                                                $keyParts = explode('.', $lkey);
                                                $keyPartsCount = count($keyParts);
-                                               // Check if last part is special instruction
-                                               // Only "+" is currently supported
-                                               $specialInstruction = $keyParts[$keyPartsCount - 1] == '+' ? TRUE : FALSE;
+                                                       // Check if last part is special instruction
+                                                       // Only "+" is currently supported
+                                               $specialInstruction = $keyParts[$keyPartsCount - 1] == '+' ?
+                                                       TRUE :
+                                                       FALSE;
                                                if ($specialInstruction) {
                                                        array_pop($keyParts);
                                                }
-                                               // If there are more than 2 parts, get the type from the last part
-                                               // and merge back the other parts with a dot (.)
-                                               // Otherwise just get type and field name straightaway
+                                                       // If there are more than 2 parts, get the type from the last part
+                                                       // and merge back the other parts with a dot (.)
+                                                       // Otherwise just get type and field name straightaway
                                                if ($keyPartsCount > 2) {
                                                        $type = array_pop($keyParts);
                                                        $fieldName = implode('.', $keyParts);
@@ -385,19 +369,20 @@ class LanguageService {
                                                        $fieldName = $keyParts[0];
                                                        $type = $keyParts[1];
                                                }
-                                               // Detecting 'hidden' labels, converting to normal fieldname
+                                                       // Detecting 'hidden' labels, converting to normal fieldname
                                                if ($fieldName == '_') {
                                                        $fieldName = '';
                                                }
                                                if (substr($fieldName, 0, 1) == '_') {
                                                        $fieldName = substr($fieldName, 1);
                                                }
-                                               // Append label
-                                               $label = $lVal[0]['target'] ?: $lVal[0]['source'];
+                                                       // Append label
+                                               $label = $lVal[0]['target'] ? :
+                                                       $lVal[0]['source'];
                                                if ($specialInstruction) {
                                                        $GLOBALS['TCA_DESCR'][$table]['columns'][$fieldName][$type] .= LF . $label;
                                                } else {
-                                                       // Substitute label
+                                                               // Substitute label
                                                        $GLOBALS['TCA_DESCR'][$table]['columns'][$fieldName][$type] = $label;
                                                }
                                        }
@@ -410,38 +395,37 @@ class LanguageService {
         * Includes locallang file (and possibly additional localized version if configured for)
         * Read language labels will be merged with $LOCAL_LANG (if $setGlobal = TRUE).
         *
-        * @param string $fileRef $fileRef is a file-reference (see t3lib_div::getFileAbsFileName)
+        * @param string $fileRef $fileRef is a file-reference
         * @param boolean $setGlobal Setting in global variable $LOCAL_LANG (or returning the variable)
-        * @param boolean $mergeLocalOntoDefault If $mergeLocalOntoDefault is set the local part of the $LOCAL_LANG array is merged onto the default part (if the local part exists) and the local part is unset.
-        * @return mixed If $setGlobal is TRUE the LL-files will set the $LOCAL_LANG in the global scope. Otherwise the $LOCAL_LANG array is returned from function
-        * @access public
+        * @param boolean $mergeLocalOntoDefault
+        * @return mixed if $setGlobal===TRUE, LL-files set $LOCAL_LANG in global scope, or array is returned from function
         */
        public function includeLLFile($fileRef, $setGlobal = TRUE, $mergeLocalOntoDefault = FALSE) {
                $globalLanguage = array();
-               // Get default file
+                       // Get default file
                $localLanguage = $this->readLLfile($fileRef);
                if (is_array($localLanguage) && count($localLanguage)) {
-                       // it depends on, whether we should return the result or set it in the global $LOCAL_LANG array
+                               // it depends on, whether we should return the result or set it in the global $LOCAL_LANG array
                        if ($setGlobal) {
                                $globalLanguage = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule((array) $GLOBALS['LOCAL_LANG'], $localLanguage);
                        } else {
                                $globalLanguage = $localLanguage;
                        }
-                       // Localized addition?
+                               // Localized addition?
                        $lFileRef = $this->localizedFileRef($fileRef);
                        if ($lFileRef && (string) $globalLanguage[$this->lang] == 'EXT') {
                                $localLanguage = $this->readLLfile($lFileRef);
                                $globalLanguage = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($globalLanguage, $localLanguage);
                        }
-                       // Merge local onto default
+                               // Merge local onto default
                        if ((($mergeLocalOntoDefault && $this->lang !== 'default') && is_array($globalLanguage[$this->lang])) && is_array($globalLanguage['default'])) {
-                               // array_merge can be used so far the keys are not
-                               // numeric - which we assume they are not...
+                                       // array_merge can be used so far the keys are not
+                                       // numeric - which we assume they are not...
                                $globalLanguage['default'] = array_merge($globalLanguage['default'], $globalLanguage[$this->lang]);
                                unset($globalLanguage[$this->lang]);
                        }
                }
-               // Return value if not global is set.
+                       // Return value if not global is set.
                if (!$setGlobal) {
                        return $globalLanguage;
                } else {
@@ -452,9 +436,8 @@ class LanguageService {
        /**
         * Includes a locallang file and returns the $LOCAL_LANG array found inside.
         *
-        * @param string $fileRef Input is a file-reference (see t3lib_div::getFileAbsFileName) which, if exists, is included. That file is expected to be a 'local_lang' file containing a $LOCAL_LANG array.
-        * @return array Value of $LOCAL_LANG found in the included file. If that array is found it's returned. Otherwise an empty array
-        * @access private
+        * @param string $fileRef Input is a file-reference to be a 'local_lang' file containing a $LOCAL_LANG array
+        * @return array value of $LOCAL_LANG found in the included file, empty if non found
         */
        protected function readLLfile($fileRef) {
                if ($this->lang !== 'default') {
@@ -470,8 +453,8 @@ class LanguageService {
                                $localLanguage[$this->lang] = $localLanguage['default'];
                        }
                        if ($this->lang !== 'default' && isset($tempLL[$language])) {
-                               // Merge current language labels onto labels from previous language
-                               // This way we have a labels with fall back applied
+                                       // Merge current language labels onto labels from previous language
+                                       // This way we have a labels with fall back applied
                                $localLanguage[$this->lang] = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($localLanguage[$this->lang], $tempLL[$language], FALSE, FALSE);
                        }
                }
@@ -483,7 +466,6 @@ class LanguageService {
         *
         * @param string $fileRef Filename/path of a 'locallang.php' file
         * @return string Input filename with a '.[lang-key].php' ending added if $this->lang is not 'default'
-        * @access private
         */
        protected function localizedFileRef($fileRef) {
                if ($this->lang != 'default' && substr($fileRef, -4) == '.php') {
@@ -508,8 +490,6 @@ class LanguageService {
                        $GLOBALS['LOCAL_LANG']['default'][$index][0]['target'] = $value;
                }
        }
-
 }
 
-
 ?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Classes/Utility/Connection/Ter.php b/typo3/sysext/lang/Classes/Utility/Connection/Ter.php
new file mode 100644 (file)
index 0000000..fb5e420
--- /dev/null
@@ -0,0 +1,224 @@
+<?php
+namespace TYPO3\CMS\Lang\Utility\Connection;
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2012 Sebastian Fischer <typo3@evoweb.de>
+ *  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!
+ ***************************************************************/
+
+/**
+ * Extends of extensionmanager ter connection to enrich with translation related methods
+ *
+ * @author Sebastian Fischer <typo3@evoweb.de>
+ * @package TYPO3
+ * @subpackage lang
+ */
+class Ter extends \TYPO3\CMS\Extensionmanager\Utility\Connection\TerUtility {
+
+       /**
+        * Fetches extensions translation status
+        *
+        * @param string $extensionKey Extension Key
+        * @param string $mirrorUrl URL of mirror to use
+        * @return mixed
+        */
+       public function fetchTranslationStatus($extensionKey, $mirrorUrl) {
+               $result = FALSE;
+               $extPath = \TYPO3\CMS\Core\Utility\GeneralUtility::strtolower($extensionKey);
+               $mirrorUrl .= $extPath{0} . '/' . $extPath{1} . '/' . $extPath . '-l10n/' . $extPath . '-l10n.xml';
+               $remote = \TYPO3\CMS\Core\Utility\GeneralUtility::getURL($mirrorUrl, 0, array(TYPO3_user_agent));
+
+               if ($remote !== FALSE) {
+                       $parsed = $this->parseL10nXML($remote);
+                       $result = $parsed['languagePackIndex'];
+               }
+
+               return $result;
+       }
+
+       /**
+        * Parses content of *-l10n.xml into a suitable array
+        *
+        * @param string $string: XML data to parse
+        * @throws \TYPO3\CMS\Lang\Exception\XmlParser
+        * @return array Array representation of XML data
+        */
+       protected function parseL10nXML($string) {
+                       // Create parser:
+               $parser = xml_parser_create();
+               $values = array();
+               $index = array();
+
+               xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
+               xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
+
+                       // Parse content
+               xml_parse_into_struct($parser, $string, $values, $index);
+
+                       // If error, return error message
+               if (xml_get_error_code($parser)) {
+                       $line = xml_get_current_line_number($parser);
+                       $error = xml_error_string(xml_get_error_code($parser));
+                       xml_parser_free($parser);
+                       throw new \TYPO3\CMS\Lang\Exception\XmlParser('Error in XML parser while decoding l10n XML file. Line ' . $line . ': ' . $error, 1345736517);
+               } else {
+                               // Init vars
+                       $stack = array(array());
+                       $stacktop = 0;
+                       $current = array();
+                       $tagName = '';
+                       $documentTag = '';
+
+                               // Traverse the parsed XML structure:
+                       foreach ($values as $val) {
+                                       // First, process the tag-name (which is used in both cases, whether "complete" or "close")
+                               $tagName = ($val['tag'] == 'languagepack' && $val['type'] == 'open') ? $val['attributes']['language'] : $val['tag'];
+                               if (!$documentTag) {
+                                       $documentTag = $tagName;
+                               }
+
+                                       // Setting tag-values, manage stack:
+                               switch ($val['type']) {
+                                               // If open tag it means there is an array stored in sub-elements.
+                                               // Therefore increase the stackpointer and reset the accumulation array
+                                       case 'open':
+                                                       // Setting blank place holder
+                                               $current[$tagName] = array();
+                                               $stack[$stacktop++] = $current;
+                                               $current = array();
+                                               break;
+                                               // If the tag is "close" then it is an array which is closing and we decrease the stack pointer.
+                                       case 'close':
+                                               $oldCurrent = $current;
+                                               $current = $stack[--$stacktop];
+                                                       // Going to the end of array to get placeholder key, key($current), and fill in array next
+                                               end($current);
+                                               $current[key($current)] = $oldCurrent;
+                                               unset($oldCurrent);
+                                               break;
+                                               // If "complete", then it's a value. If the attribute "base64" is set, then decode the value, otherwise just set it.
+                                       case 'complete':
+                                                       // Had to cast it as a string - otherwise it would be evaluate FALSE if tested with isset()!!
+                                               $current[$tagName] = (string) $val['value'];
+                                               break;
+                               }
+                       }
+                       $result = $current[$tagName];
+               }
+
+               return $result;
+       }
+
+       /**
+        * Install translations for all selected languages for an extension
+        *
+        * @param string $extensionKey The extension key to install the translations for
+        * @param string $language Language code of translation to fetch
+        * @param string $mirrorUrl Mirror URL to fetch data from
+        * @return boolean TRUE on success, error string on fauilure
+        */
+       public function updateTranslation($extensionKey, $language, $mirrorUrl) {
+               $result = FALSE;
+               try {
+                       $l10n = $this->fetchTranslation($extensionKey, $language, $mirrorUrl);
+                       if (is_array($l10n)) {
+                               $file = PATH_site . 'typo3temp' . DIRECTORY_SEPARATOR . $extensionKey . '-l10n-' . $language . '.zip';
+                               $path = 'l10n' . DIRECTORY_SEPARATOR . $language . DIRECTORY_SEPARATOR . $extensionKey . DIRECTORY_SEPARATOR;
+                               if (!is_dir(PATH_typo3conf . $path)) {
+                                       \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir_deep(PATH_typo3conf, $path);
+                               }
+                               \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile($file, $l10n[0]);
+
+                               \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir(PATH_typo3conf . $path . $extensionKey, TRUE);
+
+                               if ($this->unzipTranslationFile($file, PATH_typo3conf . $path)) {
+                                       $result = TRUE;
+                               }
+                       }
+               } catch (\TYPO3\CMS\Core\Exception $exception) {
+                       // @todo logging
+               }
+               return $result;
+       }
+
+       /**
+        * Fetches an extensions l10n file from the given mirror
+        *
+        * @param string $extensionKey Extension Key
+        * @param string $language The language code of the translation to fetch
+        * @param string $mirrorUrl URL of mirror to use
+        * @throws \TYPO3\CMS\Lang\Exception\XmlParser
+        * @return array Array containing l10n data
+        */
+       protected function fetchTranslation($extensionKey, $language, $mirrorUrl) {
+               $extensionPath = \TYPO3\CMS\Core\Utility\GeneralUtility::strtolower($extensionKey);
+               $mirrorUrl .= $extensionPath{0} . '/' . $extensionPath{1} . '/' . $extensionPath .
+                       '-l10n/' . $extensionPath . '-l10n-' . $language . '.zip';
+               $l10nResponse = \TYPO3\CMS\Core\Utility\GeneralUtility::getURL($mirrorUrl, 0, array(TYPO3_user_agent));
+
+               if ($l10nResponse === FALSE) {
+                       throw new \TYPO3\CMS\Lang\Exception\XmlParser('Error: Translation could not be fetched.', 1345736785);
+               } else {
+                       return array($l10nResponse);
+               }
+       }
+
+       /**
+        * Unzip an language.zip.
+        *
+        * @param string $file path to zip file
+        * @param string $path path to extract to
+        * @throws \TYPO3\CMS\Lang\Exception\Lang
+        * @return boolean
+        */
+       protected function unzipTranslationFile($file, $path) {
+               $zip = zip_open($file);
+               if (is_resource($zip)) {
+                       $result = TRUE;
+
+                       if (!is_dir($path)) {
+                               \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir_deep($path);
+                       }
+
+                       while (($zipEntry = zip_read($zip)) !== FALSE) {
+                               if (strpos(zip_entry_name($zipEntry), DIRECTORY_SEPARATOR) !== FALSE) {
+                                       $file = substr(zip_entry_name($zipEntry), strrpos(zip_entry_name($zipEntry), DIRECTORY_SEPARATOR) + 1);
+                                       if (strlen(trim($file)) > 0) {
+                                               $return = \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile(
+                                                       $path . '/' . $file, zip_entry_read($zipEntry, zip_entry_filesize($zipEntry))
+                                               );
+                                               if ($return === FALSE) {
+                                                       throw new \TYPO3\CMS\Lang\Exception\Lang('Could not write file ' . $file, 1345304560);
+                                               }
+                                       }
+                               } else {
+                                       $result = FALSE;
+                                       \TYPO3\CMS\Core\Utility\GeneralUtility::writeFile($path . zip_entry_name($zipEntry), zip_entry_read($zipEntry, zip_entry_filesize($zipEntry)));
+                               }
+                       }
+               } else {
+                       throw new \TYPO3\CMS\Lang\Exception\Lang('Unable to open zip file ' . $file, 1345304561);
+               }
+
+               return $result;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Resources/Private/.htaccess b/typo3/sysext/lang/Resources/Private/.htaccess
new file mode 100644 (file)
index 0000000..3418e55
--- /dev/null
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/typo3/sysext/lang/Resources/Private/Language/locallang.xml b/typo3/sysext/lang/Resources/Private/Language/locallang.xml
new file mode 100644 (file)
index 0000000..af65296
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<T3locallang>
+       <meta type="array">
+               <type>module</type>
+               <description>Language labels for module &quot;lang&quot; - in modul</description>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+                       <label index="not_checked">not checked</label>
+
+                       <label index="translation_n_a">translation not available</label>
+                       <label index="translation_msg_failed">Failed</label>
+                       <label index="translation_msg_updated">Updated</label>
+                       <label index="translation_status_uptodate">up to date</label>
+                       <label index="button_save">Save</label>
+                       <label index="button_update">Update from repository</label>
+               </languageKey>
+       </data>
+</T3locallang>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Resources/Private/Language/locallang_mod_language.xml b/typo3/sysext/lang/Resources/Private/Language/locallang_mod_language.xml
new file mode 100644 (file)
index 0000000..52119ca
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<T3locallang>
+       <meta type="array">
+               <type>module</type>
+               <description>Language labels for module &quot;lang&quot; - header, description</description>
+       </meta>
+       <data type="array">
+               <languageKey index="default" type="array">
+                       <label index="mlang_labels_tablabel">Language</label>
+                       <label index="mlang_labels_tabdescr">Select language to be available for backend and frontend. Provide update of chosen languages.</label>
+                       <label index="mlang_tabs_tab">Language</label>
+               </languageKey>
+       </data>
+</T3locallang>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Resources/Private/Layouts/DocHeader.html b/typo3/sysext/lang/Resources/Private/Layouts/DocHeader.html
new file mode 100644 (file)
index 0000000..4a1da71
--- /dev/null
@@ -0,0 +1,18 @@
+<f:be.container loadExtJs="1">
+       <div class="typo3-fullDoc">
+               <div id="typo3-docheader">
+                       <div id="typo3-docheader-functions">&nbsp;</div>
+                       <div id="typo3-docheader-buttons">
+                               <div class="right">
+                                       <f:be.buttons.shortcut />
+                               </div>
+                       </div>
+               </div>
+
+               <div id="typo3-docbody">
+                       <div id="typo3-inner-docbody">
+                               <f:render section="Content" />
+                       </div>
+               </div>
+       </div>
+</f:be.container>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Resources/Private/Partials/ExtensionRow.html b/typo3/sysext/lang/Resources/Private/Partials/ExtensionRow.html
new file mode 100644 (file)
index 0000000..1e8f353
--- /dev/null
@@ -0,0 +1,37 @@
+<f:for each="{extensions}" as="extension">
+       <div class="x-grid3-row x-grid3-row-first" style="width:370px;">
+               <table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="width:370px;">
+                       <tbody>
+                       <tr>
+                               <td class="x-grid3-col x-grid3-cell x-grid3-td-0 x-grid3-cell-first  extLangTitleWithIcon" style="width: 200px;" tabindex="0">
+                                       <div class="x-grid3-cell-inner x-grid3-col-0" unselectable="on">
+                                               <f:format.html parseFuncTSPath="">
+                                                       <f:image src="{extension.icon}" alt="{extension.key}"/> <strong>{extension.key}</strong>
+                                               </f:format.html>
+                                       </div>
+                               </td>
+                               <f:for each="{selectedLanguages}" as="language">
+                               <td class="x-grid3-col x-grid3-cell x-grid3-td-de x-grid3-cell-last "
+                                       style="cursor:pointer;width: 170px;" tabindex="0">
+                                       <div class="x-grid3-cell-inner x-grid3-col-de" unselectable="on">
+                                               <f:if condition="{extension.updateResult}">
+                                                       <f:then>
+                                                               <f:for each="{extension.updateResult}" as="result" key="key">
+                                                                       <f:if condition="{0: language.locale} == {0: key}">
+                                                                               <f:format.html parseFuncTSPath="">{result.icon}</f:format.html>
+                                                                               <f:translate key="{result.message}"/>
+                                                                       </f:if>
+                                                               </f:for>
+                                                       </f:then>
+                                                       <f:else>
+                                                               <f:translate key="not_checked"/>
+                                                       </f:else>
+                                               </f:if>
+                                       </div>
+                               </td>
+                               </f:for>
+                       </tr>
+                       </tbody>
+               </table>
+       </div>
+</f:for>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Resources/Private/Partials/TranslationHeaders.html b/typo3/sysext/lang/Resources/Private/Partials/TranslationHeaders.html
new file mode 100644 (file)
index 0000000..b75310e
--- /dev/null
@@ -0,0 +1,16 @@
+<f:for each="{languages}" as="language">
+       <f:if condition="{language.selected}">
+               <f:then>
+                       <td class="x-grid3-hd x-grid3-cell x-grid3-td-de x-grid3-cell-last"
+                               style="width: 170px;">
+                               <div ext:qtip="Click to update this language for this extension only"
+                                        class="x-grid3-hd-inner x-grid3-hd-de"
+                                        unselectable="on" style=""><span
+                                               class="">&nbsp;</span>{language.language}<img
+                                               alt="" class="x-grid3-sort-icon"
+                                               src="http://dev60.dev/typo3/gfx/clear.gif">
+                               </div>
+                       </td>
+               </f:then>
+       </f:if>
+</f:for>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Resources/Private/Templates/Language/Index.html b/typo3/sysext/lang/Resources/Private/Templates/Language/Index.html
new file mode 100644 (file)
index 0000000..2fec1be
--- /dev/null
@@ -0,0 +1,246 @@
+<f:layout name="DocHeader"/>
+
+<f:section name="Content">
+       <f:flashMessages renderMode="div" />
+
+<!-- values needed to be replaced by javascript 415px, 401px, 390px 361px 337px -->
+
+<div id="em-translations" class=" x-panel x-panel-noborder">
+<div class="x-panel-bwrap" id="ext-gen40">
+<div class="x-box-inner" id="ext-gen42" style="width: 1299px; height: 415px; ">
+<div id="ext-comp-1098" class=" x-panel x-panel-noborder x-box-item" style="width: 250px; left: 0px; top: 0px; ">
+    <div class="x-panel-bwrap" id="ext-gen43">
+        <div class="x-panel-body x-panel-body-noheader x-panel-body-noborder" id="ext-gen44"
+             style="width: 250px; height: 415px; ">
+            <div id="em-languagegrid" class="x-panel x-grid-panel" style="width: 250px; ">
+                <div class="x-panel-bwrap" id="ext-gen49">
+                    <div class="x-panel-body x-panel-body-noheader" id="ext-gen50"
+                         style="width: 250px; height: 415px; ">
+                        <div class="x-grid3" hidefocus="true" id="ext-gen52"
+                             style="width: 250px; height: 415px; ">
+                            <div class="x-grid3-viewport" id="ext-gen53">
+                                <div class="x-grid3-header" id="ext-gen54">
+                                    <div class="x-grid3-header-inner" id="ext-gen56" style="width: 250px; ">
+                                        <div class="x-grid3-header-offset" style="width: 249px; ">
+                                            <table border="0" cellspacing="0" cellpadding="0"
+                                                   style="width: 232px; ">
+                                                <thead>
+                                                <tr class="x-grid3-hd-row">
+                                                    <td class="x-grid3-hd x-grid3-cell x-grid3-td-checker x-grid3-cell-first"
+                                                        style="width: 20px;">
+                                                        <div class="x-grid3-hd-inner x-grid3-hd-checker"
+                                                             unselectable="on" style=""><a
+                                                                class="x-grid3-hd-btn" href="#"></a><img
+                                                                alt="" class="x-grid3-sort-icon"
+                                                                src="clear.gif">
+                                                        </div>
+                                                    </td>
+                                                    <td class="x-grid3-hd x-grid3-cell x-grid3-td-lang-label sort-asc"
+                                                        style="width: 106px;">
+                                                        <div class="x-grid3-hd-inner x-grid3-hd-lang-label"
+                                                             unselectable="on" style=""><a
+                                                                class="x-grid3-hd-btn"
+                                                                href="#"></a>Language<img alt=""
+                                                                                          class="x-grid3-sort-icon"
+                                                                                          src="clear.gif">
+                                                        </div>
+                                                    </td>
+                                                    <td class="x-grid3-hd x-grid3-cell x-grid3-td-lang-key x-grid3-cell-last"
+                                                        style="width: 106px;">
+                                                        <div class="x-grid3-hd-inner x-grid3-hd-lang-key"
+                                                             unselectable="on" style=""><a
+                                                                class="x-grid3-hd-btn" href="#"></a>Short<img
+                                                                alt="" class="x-grid3-sort-icon"
+                                                                src="clear.gif">
+                                                        </div>
+                                                    </td>
+                                                </tr>
+                                                </thead>
+                                            </table>
+                                        </div>
+                                    </div>
+                                    <div class="x-clear"></div>
+                                </div>
+                                <div class="x-grid3-scroller" id="ext-gen55"
+                                     style="overflow-x: hidden; width: 250px; height: 390px; ">
+                                    <div class="x-grid3-body" style="width: 232px; " id="ext-gen57">
+
+                                        <f:form action="saveSelectedLocale" name="form" object="{form}">
+                                            <f:form.submit value="{f:translate(key:'button_save')}"/>
+                                            <f:for each="{languages}" as="language" iteration="iteration">
+                                                <div class="x-grid3-row x-grid3-row-first" style="width: 232px;">
+                                                    <table class="x-grid3-row-table" border="0" cellspacing="0"
+                                                           cellpadding="0" style="width:232px;">
+                                                        <tbody>
+                                                        <tr>
+                                                            <td class="x-grid3-col x-grid3-cell x-grid3-td-checker x-grid3-cell-first "
+                                                                style="width: 20px;" tabindex="0">
+                                                                <f:form.checkbox name="form[locale][{language.locale}]"
+                                                                                 value="1"
+                                                                                 checked="{language.selected}"/>
+                                                            </td>
+                                                            <td class="x-grid3-col x-grid3-cell x-grid3-td-lang-label"
+                                                                style="width: 106px;" tabindex="0">
+                                                                <div class="x-grid3-cell-inner x-grid3-col-lang-label"
+                                                                     unselectable="on">
+                                                                    <span class="">&nbsp;</span>{language.language}
+                                                                </div>
+                                                            </td>
+                                                            <td class="x-grid3-col x-grid3-cell x-grid3-td-lang-key x-grid3-cell-last"
+                                                                style="width: 106px;" tabindex="0">
+                                                                <div class="x-grid3-cell-inner x-grid3-col-lang-key"
+                                                                     unselectable="on">{language.locale}
+                                                                </div>
+                                                            </td>
+                                                        </tr>
+                                                        </tbody>
+                                                    </table>
+                                                </div>
+                                            </f:for>
+                                        </f:form>
+
+                                    </div>
+                                    <a href="#" class="x-grid3-focus" tabindex="-1" id="ext-gen58"
+                                       style="left: 0px; top: 0px; "></a></div>
+                            </div>
+                            <div class="x-grid3-resize-marker" id="ext-gen59">&nbsp;</div>
+                            <div class="x-grid3-resize-proxy" id="ext-gen60">&nbsp;</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<div id="ext-comp-1099" class=" x-panel x-panel-noborder x-box-item" style="width: 1049px; left: 250px; top: 0px; ">
+    <div class="x-panel-bwrap" id="ext-gen46">
+        <div class="x-panel-body x-panel-body-noheader x-panel-body-noborder" id="ext-gen47"
+             style="width: 1049px; height: 415px; ">
+
+            <f:form action="updateTranslation" name="form" object="{form}">
+                <fieldset style="display: none;">
+                    <f:for each="{selectedLanguages}" as="language">
+                        <f:form.hidden name="form[selectedLanguages][]" value="{language.locale}"/>
+                    </f:for>
+                </fieldset>
+
+                <fieldset style="display: none;">
+                    <f:for each="{extensions}" as="extension">
+                        <f:form.hidden name="form[extensions][]" value="{extension.key}"/>
+                    </f:for>
+                </fieldset>
+
+                <fieldset id="ext-comp-1100" class=" x-fieldset x-form-label-left" style="width: 1029px; ">
+                    <div class="x-fieldset-bwrap" id="ext-gen62">
+                        <div class="x-fieldset-body x-fieldset-body-noheader" id="ext-gen63"
+                             style="width: 1029px; height: 401px; ">
+                            <div id="LanguagesActionPanel" style="height: 40px; width: 1029px; "
+                                 class=" x-box-layout-ct">
+                                <div class="x-box-inner" id="ext-gen84" style="width: 1029px; height: 40px; ">
+                                    <table id="lang-updatebutton" cellspacing="0"
+                                           class="x-btn x-btn-noicon x-box-item"
+                                           style="width: 200px; height: 28px; left: 0px; top: 0px; ">
+                                        <tbody class="x-btn-small x-btn-icon-small-left">
+                                        <tr>
+                                            <td class="x-btn-tl"><i>&nbsp;</i></td>
+                                            <td class="x-btn-tc"></td>
+                                            <td class="x-btn-tr"><i>&nbsp;</i></td>
+                                        </tr>
+                                        <tr>
+                                            <td class="x-btn-ml"><i>&nbsp;</i></td>
+                                            <td class="x-btn-mc"><em class="" unselectable="on">
+                                                <f:form.submit value="{f:translate(key:'button_update')}"/>
+                                            </em></td>
+                                            <td class="x-btn-mr"><i>&nbsp;</i></td>
+                                        </tr>
+                                        <tr>
+                                            <td class="x-btn-bl"><i>&nbsp;</i></td>
+                                            <td class="x-btn-bc"></td>
+                                            <td class="x-btn-br"><i>&nbsp;</i></td>
+                                        </tr>
+                                        </tbody>
+                                    </table>
+                                </div>
+                            </div>
+
+                            <div class="x-progress-wrap left-align x-hide-display" id="langpb"
+                                 style="margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 0px; width: auto; height: 18px; ">
+                                <div class="x-progress-inner">
+                                    <div class="x-progress-bar" id="ext-gen67" style="height: 16px; ">
+                                        <div class="x-progress-text x-hidden" id="ext-gen68" style="z-index: 99; ">
+                                            <div id="ext-gen70" style="width: 522px; height: 18px; ">&nbsp;</div>
+                                        </div>
+                                    </div>
+                                    <div class="x-progress-text x-progress-text-back" id="ext-gen69">
+                                        <div id="ext-gen71" style="width: 522px; height: 18px; ">&nbsp;</div>
+                                    </div>
+                                </div>
+                            </div>
+
+                            <div id="em-extlanguagegrid" class=" x-panel x-grid-panel" style="width: 1029px; ">
+                                <div class="x-panel-bwrap" id="ext-gen72">
+                                    <div class="x-panel-body x-panel-body-noheader" id="ext-gen73"
+                                         style="width: 1029px; height: 361px; ">
+                                        <div class="x-grid3" hidefocus="true" id="ext-gen74"
+                                             style="width: 1029px; height: 361px; ">
+                                            <div class="x-grid3-viewport" id="ext-gen75">
+                                                <div class="x-grid3-header" id="ext-gen76">
+                                                    <div class="x-grid3-header-inner" id="ext-gen78"
+                                                         style="width: 1029px; ">
+                                                        <div class="x-grid3-header-offset" style="width: 387px; ">
+                                                            <table border="0" cellspacing="0" cellpadding="0"
+                                                                   style="width: 370px; ">
+                                                                <thead>
+                                                                <tr class="x-grid3-hd-row">
+                                                                    <td class="x-grid3-hd x-grid3-cell x-grid3-td-0 x-grid3-cell-first"
+                                                                        style="width: 200px;">
+                                                                        <div class="x-grid3-hd-inner x-grid3-hd-0"
+                                                                             unselectable="on" style="">
+                                                                            Extension<img alt=""
+                                                                                          class="x-grid3-sort-icon"
+                                                                                          src="clear.gif">
+                                                                        </div>
+                                                                    </td>
+
+                                                                    <f:render partial="TranslationHeaders"
+                                                                              arguments="{languages: languages}"/>
+                                                                </tr>
+                                                                </thead>
+                                                            </table>
+                                                        </div>
+                                                    </div>
+                                                    <div class="x-clear"></div>
+                                                </div>
+
+                                                <div class="x-grid3-scroller" id="ext-gen77"
+                                                     style="width: 1029px; height: 337px; ">
+                                                    <div class="x-grid3-body" style="width: 370px; " id="ext-gen79">
+
+                                                        <f:render partial="ExtensionRow"
+                                                                  arguments="{languages: languages, selectedLanguages: selectedLanguages, extensions: extensions}"/>
+
+                                                    </div>
+                                                    <a href="#" class="x-grid3-focus" tabindex="-1" id="ext-gen80"
+                                                       style="left: 0px; top: 0px; "></a></div>
+                                            </div>
+                                            <div class="x-grid3-resize-marker" id="ext-gen81">&nbsp;</div>
+                                            <div class="x-grid3-resize-proxy" id="ext-gen82">&nbsp;</div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </fieldset>
+
+            </f:form>
+
+        </div>
+    </div>
+</div>
+</div>
+</div>
+</div>
+
+</f:section>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Resources/Public/Images/moduleicon.gif b/typo3/sysext/lang/Resources/Public/Images/moduleicon.gif
new file mode 100644 (file)
index 0000000..fc0e8f2
Binary files /dev/null and b/typo3/sysext/lang/Resources/Public/Images/moduleicon.gif differ
diff --git a/typo3/sysext/lang/Tests/Domain/Model/ExtensionTest.php b/typo3/sysext/lang/Tests/Domain/Model/ExtensionTest.php
new file mode 100644 (file)
index 0000000..d662e4b
--- /dev/null
@@ -0,0 +1,224 @@
+<?php\r
+namespace TYPO3\CMS\Lang\Tests\Unit\Domain\Model;\r
+/***************************************************************\r
+ *  Copyright notice\r
+ *\r
+ *  (c) 2012 Wouter Wolters <typo3@wouterwolters.nl>\r
+ *  All rights reserved\r
+ *\r
+ *  This script is part of the TYPO3 project. The TYPO3 project is\r
+ *  free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  The GNU General Public License can be found at\r
+ *  http://www.gnu.org/copyleft/gpl.html.\r
+ *  A copy is found in the textfile GPL.txt and important notices to the license\r
+ *  from the author is found in LICENSE.txt distributed with these scripts.\r
+ *\r
+ *  This script is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  This copyright notice MUST APPEAR in all copies of the script!\r
+ ***************************************************************/\r
+\r
+/**\r
+ * Test case for class \TYPO3\CMS\Lang\Domain\Model\Extension\r
+ *\r
+ * @author Wouter Wolters <typo3@wouterwolters.nl>\r
+ * @package TYPO3\r
+ * @subpackage lang\r
+ */\r
+class ExtensionTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {\r
+\r
+       /**\r
+        * @var \TYPO3\CMS\Lang\Domain\Model\Extension\r
+        */\r
+       protected $fixture = NULL;\r
+\r
+       public function setUp() {\r
+               $this->fixture = new \TYPO3\CMS\Lang\Domain\Model\Extension();\r
+       }\r
+\r
+       public function tearDown() {\r
+               unset($this->fixture);\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getKeyInitiallyReturnsEmptyString() {\r
+               $this->assertSame(\r
+                       '',\r
+                       $this->fixture->getKey()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getKeyInitiallyReturnsGivenKeyFromConstruct() {\r
+               $key = 'foo bar';\r
+               $this->fixture = new \TYPO3\CMS\Lang\Domain\Model\Extension($key);\r
+\r
+               $this->assertSame(\r
+                       $key,\r
+                       $this->fixture->getKey()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setKeySetsKey() {\r
+               $key = 'foo bar';\r
+               $this->fixture->setKey($key);\r
+\r
+               $this->assertSame(\r
+                       $key,\r
+                       $this->fixture->getKey()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getTitleInitiallyReturnsEmptyString() {\r
+               $this->assertSame(\r
+                       '',\r
+                       $this->fixture->getTitle()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getTitleInitiallyReturnsGivenTitleFromConstruct() {\r
+               $title = 'foo bar';\r
+               $this->fixture = new \TYPO3\CMS\Lang\Domain\Model\Extension('', $title);\r
+\r
+               $this->assertSame(\r
+                       $title,\r
+                       $this->fixture->getTitle()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setTitleSetsTitle() {\r
+               $title = 'foo bar';\r
+               $this->fixture->setTitle($title);\r
+\r
+               $this->assertSame(\r
+                       $title,\r
+                       $this->fixture->getTitle()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getIconInitiallyReturnsEmptyString() {\r
+               $this->assertSame(\r
+                       '',\r
+                       $this->fixture->getIcon()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getIconInitiallyReturnsGivenIconFromConstruct() {\r
+               $icon = 'foo bar';\r
+               $this->fixture = new \TYPO3\CMS\Lang\Domain\Model\Extension('', '', $icon);\r
+\r
+               $this->assertSame(\r
+                       $icon,\r
+                       $this->fixture->getIcon()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setIconSetsIcon() {\r
+               $icon = 'foo bar';\r
+               $this->fixture->setIcon($icon);\r
+\r
+               $this->assertSame(\r
+                       $icon,\r
+                       $this->fixture->getIcon()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getVersionInitiallyReturnsEmptyString() {\r
+               $this->assertSame(\r
+                       '',\r
+                       $this->fixture->getVersion()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setVersionSetsVersion() {\r
+               $version = 10;\r
+               $this->fixture->setVersion($version);\r
+\r
+               $this->assertSame(\r
+                       $version,\r
+                       $this->fixture->getVersion()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setVersionSetsVersionFromString() {\r
+               $version = 4012003;\r
+               $this->fixture->setVersionFromString('4.12.3');\r
+\r
+               $this->assertSame(\r
+                       $version,\r
+                       $this->fixture->getVersion()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getUpdateResultInitiallyReturnsEmptyArray() {\r
+               $this->assertSame(\r
+                       array(),\r
+                       $this->fixture->getUpdateResult()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setUpdateResultSetsUpdateResult() {\r
+               $updateResult = array(\r
+                       'nl' => array(\r
+                               'icon' => '<span class="t3-icon t3-icon-actions t3-icon-actions-document t3-icon-document-info">&nbsp;</span>',\r
+                               'message' => 'translation_n_a'\r
+                       ),\r
+               );\r
+\r
+               $this->fixture->setUpdateResult($updateResult);\r
+\r
+               $this->assertSame(\r
+                       $updateResult,\r
+                       $this->fixture->getUpdateResult()\r
+               );\r
+       }\r
+\r
+}\r
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Tests/Domain/Model/LanguageSelectionFormTest.php b/typo3/sysext/lang/Tests/Domain/Model/LanguageSelectionFormTest.php
new file mode 100644 (file)
index 0000000..fda3518
--- /dev/null
@@ -0,0 +1,76 @@
+<?php\r
+namespace TYPO3\CMS\Lang\Tests\Unit\Domain\Model;\r
+/***************************************************************\r
+ *  Copyright notice\r
+ *\r
+ *  (c) 2012 Wouter Wolters <typo3@wouterwolters.nl>\r
+ *  All rights reserved\r
+ *\r
+ *  This script is part of the TYPO3 project. The TYPO3 project is\r
+ *  free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  The GNU General Public License can be found at\r
+ *  http://www.gnu.org/copyleft/gpl.html.\r
+ *  A copy is found in the textfile GPL.txt and important notices to the license\r
+ *  from the author is found in LICENSE.txt distributed with these scripts.\r
+ *\r
+ *  This script is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  This copyright notice MUST APPEAR in all copies of the script!\r
+ ***************************************************************/\r
+\r
+/**\r
+ * Test case for class \TYPO3\CMS\Lang\Domain\Model\LanguageSelectionForm\r
+ *\r
+ * @author Wouter Wolters <typo3@wouterwolters.nl>\r
+ * @package TYPO3\r
+ * @subpackage lang\r
+ */\r
+class LanguageSelectionFormTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {\r
+\r
+       /**\r
+        * @var \TYPO3\CMS\Lang\Domain\Model\LanguageSelectionForm\r
+        */\r
+       protected $fixture = NULL;\r
+\r
+       public function setUp() {\r
+               $this->fixture = new \TYPO3\CMS\Lang\Domain\Model\LanguageSelectionForm();\r
+       }\r
+\r
+       public function tearDown() {\r
+               unset($this->fixture);\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getLocaleInitiallyReturnsEmptyArray() {\r
+               $this->assertSame(\r
+                       array(),\r
+                       $this->fixture->getLocale()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setLocaleSetsLocale() {\r
+               $locale = array(\r
+                       'nl' => '1',\r
+                       'de' => '0',\r
+               );\r
+               $this->fixture->setLocale($locale);\r
+\r
+               $this->assertSame(\r
+                       $locale,\r
+                       $this->fixture->getLocale()\r
+               );\r
+       }\r
+}\r
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Tests/Domain/Model/LanguageTest.php b/typo3/sysext/lang/Tests/Domain/Model/LanguageTest.php
new file mode 100644 (file)
index 0000000..19be416
--- /dev/null
@@ -0,0 +1,159 @@
+<?php\r
+namespace TYPO3\CMS\Lang\Tests\Unit\Domain\Model;\r
+/***************************************************************\r
+ *  Copyright notice\r
+ *\r
+ *  (c) 2012 Wouter Wolters <typo3@wouterwolters.nl>\r
+ *  All rights reserved\r
+ *\r
+ *  This script is part of the TYPO3 project. The TYPO3 project is\r
+ *  free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  The GNU General Public License can be found at\r
+ *  http://www.gnu.org/copyleft/gpl.html.\r
+ *  A copy is found in the textfile GPL.txt and important notices to the license\r
+ *  from the author is found in LICENSE.txt distributed with these scripts.\r
+ *\r
+ *  This script is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  This copyright notice MUST APPEAR in all copies of the script!\r
+ ***************************************************************/\r
+\r
+/**\r
+ * Test case for class \TYPO3\CMS\Lang\Domain\Model\Language\r
+ *\r
+ * @author Wouter Wolters <typo3@wouterwolters.nl>\r
+ * @package TYPO3\r
+ * @subpackage lang\r
+ */\r
+class LanguageTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {\r
+\r
+       /**\r
+        * @var \TYPO3\CMS\Lang\Domain\Model\Language\r
+        */\r
+       protected $fixture = NULL;\r
+\r
+       public function setUp() {\r
+               $this->fixture = new \TYPO3\CMS\Lang\Domain\Model\Language();\r
+       }\r
+\r
+       public function tearDown() {\r
+               unset($this->fixture);\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getLocaleInitiallyReturnsEmptyString() {\r
+               $this->assertSame(\r
+                       '',\r
+                       $this->fixture->getLocale()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getLocaleInitiallyReturnsGivenLocaleFromConstruct() {\r
+               $locale = 'nl';\r
+               $this->fixture = new \TYPO3\CMS\Lang\Domain\Model\Language($locale);\r
+\r
+               $this->assertSame(\r
+                       $locale,\r
+                       $this->fixture->getLocale()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setLocaleSetsLocale() {\r
+               $locale = 'nl';\r
+               $this->fixture->setLocale($locale);\r
+\r
+               $this->assertSame(\r
+                       $locale,\r
+                       $this->fixture->getLocale()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getLanguageInitiallyReturnsEmptyString() {\r
+               $this->assertSame(\r
+                       '',\r
+                       $this->fixture->getLanguage()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getLanguageInitiallyReturnsGivenLanguageFromConstruct() {\r
+               $language = 'nl';\r
+               $this->fixture = new \TYPO3\CMS\Lang\Domain\Model\Language('', $language);\r
+\r
+               $this->assertSame(\r
+                       $language,\r
+                       $this->fixture->getLanguage()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setLanguageSetsLanguage() {\r
+               $language = 'nl';\r
+               $this->fixture->setLanguage($language);\r
+\r
+               $this->assertSame(\r
+                       $language,\r
+                       $this->fixture->getLanguage()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getSelectedInitiallyReturnsFalse() {\r
+               $this->assertSame(\r
+                       FALSE,\r
+                       $this->fixture->getSelected()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getSelectedInitiallyReturnsGivenSelectedFromConstruct() {\r
+               $selected = FALSE;\r
+               $this->fixture = new \TYPO3\CMS\Lang\Domain\Model\Language('', '', FALSE);\r
+\r
+               $this->assertSame(\r
+                       $selected,\r
+                       $this->fixture->getSelected()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setSelectedSetsSelected() {\r
+               $selected = TRUE;\r
+               $this->fixture->setSelected($selected);\r
+\r
+               $this->assertSame(\r
+                       $selected,\r
+                       $this->fixture->getSelected()\r
+               );\r
+       }\r
+\r
+}\r
+?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/Tests/Domain/Model/UpdateTranslationFormTest.php b/typo3/sysext/lang/Tests/Domain/Model/UpdateTranslationFormTest.php
new file mode 100644 (file)
index 0000000..cf78fc1
--- /dev/null
@@ -0,0 +1,103 @@
+<?php\r
+namespace TYPO3\CMS\Lang\Tests\Unit\Domain\Model;\r
+/***************************************************************\r
+ *  Copyright notice\r
+ *\r
+ *  (c) 2012 Wouter Wolters <typo3@wouterwolters.nl>\r
+ *  All rights reserved\r
+ *\r
+ *  This script is part of the TYPO3 project. The TYPO3 project is\r
+ *  free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  The GNU General Public License can be found at\r
+ *  http://www.gnu.org/copyleft/gpl.html.\r
+ *  A copy is found in the textfile GPL.txt and important notices to the license\r
+ *  from the author is found in LICENSE.txt distributed with these scripts.\r
+ *\r
+ *  This script is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  This copyright notice MUST APPEAR in all copies of the script!\r
+ ***************************************************************/\r
+\r
+/**\r
+ * Test case for class \TYPO3\CMS\Lang\Domain\Model\UpdateTranslationForm\r
+ *\r
+ * @author Wouter Wolters <typo3@wouterwolters.nl>\r
+ * @package TYPO3\r
+ * @subpackage lang\r
+ */\r
+class UpdateTranslationFormTest extends \TYPO3\CMS\Extbase\Tests\Unit\BaseTestCase {\r
+\r
+       /**\r
+        * @var \TYPO3\CMS\Lang\Domain\Model\UpdateTranslationForm\r
+        */\r
+       protected $fixture = NULL;\r
+\r
+       public function setUp() {\r
+               $this->fixture = new \TYPO3\CMS\Lang\Domain\Model\UpdateTranslationForm();\r
+       }\r
+\r
+       public function tearDown() {\r
+               unset($this->fixture);\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getSelectedLanguagesInitiallyReturnsEmptyArray() {\r
+               $this->assertSame(\r
+                       array(),\r
+                       $this->fixture->getSelectedLanguages()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setSelectedLanguagesSetsSelectedLanguages() {\r
+               $languages = array(\r
+                       'nl',\r
+                       'de',\r
+               );\r
+               $this->fixture->setSelectedLanguages($languages);\r
+\r
+               $this->assertSame(\r
+                       $languages,\r
+                       $this->fixture->getSelectedLanguages()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function getExtensionsInitiallyReturnsEmptyArray() {\r
+               $this->assertSame(\r
+                       array(),\r
+                       $this->fixture->getExtensions()\r
+               );\r
+       }\r
+\r
+       /**\r
+        * @test\r
+        */\r
+       public function setExtensionsSetsExtensions() {\r
+               $extensions = array(\r
+                       1 => 'about',\r
+                       2 => 'aboutmodules',\r
+                       3 => 'adodb',\r
+               );\r
+               $this->fixture->setExtensions($extensions);\r
+\r
+               $this->assertSame(\r
+                       $extensions,\r
+                       $this->fixture->getExtensions()\r
+               );\r
+       }\r
+}\r
+?>
\ No newline at end of file
index 98df351..ff583ce 100755 (executable)
@@ -35,7 +35,8 @@ $EM_CONF[$_EXTKEY] = array(
        'constraints' => array(
                'depends' => array(
                        'php' => '5.3.0-0.0.0',
-                       'typo3' => '4.6.0-0.0.0'
+                       'typo3' => '6.0.0-0.0.0',
+                       'extensionmanager' => '4.8.0-0.0.0',
                ),
                'conflicts' => array(),
                'suggests' => array()
diff --git a/typo3/sysext/lang/ext_icon.gif b/typo3/sysext/lang/ext_icon.gif
new file mode 100644 (file)
index 0000000..fc0e8f2
Binary files /dev/null and b/typo3/sysext/lang/ext_icon.gif differ
index 219f14f..c3903a6 100644 (file)
@@ -7,15 +7,15 @@ if (!is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations
        $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['t3lib_l10n'] = array();
 }
 if (!isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['t3lib_l10n']['backend'])) {
-       $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['t3lib_l10n']['backend'] = 'TYPO3\\CMS\\Core\\Cache\\Backend\\FileBackend';
+       $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['t3lib_l10n']['backend'] = 'TYPO3\CMS\Core\Cache\Backend\FileBackend';
 }
 if (isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['lang']['cache']['clear_menu']) && $GLOBALS['TYPO3_CONF_VARS']['SYS']['lang']['cache']['clear_menu']) {
        // Register Clear Cache Menu hook
-       $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['additionalBackendItems']['cacheActions']['clearLangCache'] = 'EXT:lang/hooks/clearcache/class.tx_lang_clearcachemenu.php:&TYPO3\\CMS\\Lang\\ClearLanguageCacheMenuItem';
+       $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['additionalBackendItems']['cacheActions']['clearLangCache'] = 'TYPO3\CMS\Lang\ClearLanguageCacheMenuItem';
 } else {
        // Clear l10n cache when the user clears all caches
-       $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc']['clearLangCache'] = 'EXT:lang/hooks/clearcache/class.tx_lang_clearcache.php:TYPO3\\CMS\\Lang\\LanguageCacheClearer->clearCache';
+       $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['clearCachePostProc']['clearLangCache'] = 'TYPO3\CMS\Lang\ClearLanguageCacheMenuItem->clearCache';
 }
 // Register Ajax call
-$GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX']['lang::clearCache'] = 'EXT:lang/hooks/clearcache/class.tx_lang_clearcache.php:TYPO3\\CMS\\Lang\\LanguageCacheClearer->clearCache';
+$GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX']['lang::clearCache'] = 'TYPO3\CMS\Lang\LanguageCacheClearer->clearCache';
 ?>
\ No newline at end of file
diff --git a/typo3/sysext/lang/ext_tables.php b/typo3/sysext/lang/ext_tables.php
new file mode 100644 (file)
index 0000000..1f82c9c
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+if (!defined('TYPO3_MODE')) {
+       die('Access denied.');
+}
+
+if (TYPO3_MODE == 'BE' && !(TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_INSTALL)) {
+               // Registers a Backend Module
+       \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
+               'TYPO3.CMS.' . $_EXTKEY,
+               'tools', // Make module a submodule of 'tools'
+               'language', // Submodule key
+               'after:extensionmanager', // Position
+               array(
+                               // An array holding the controller-action-combinations that are accessible
+                       'Language' => 'index, saveSelectedLocale, updateTranslation'
+               ),
+               array(
+                       'access' => 'admin',
+                       'icon' => 'EXT:' . $_EXTKEY . '/Resources/Public/Images/moduleicon.gif',
+                       'labels' => 'LLL:EXT:' . $_EXTKEY . '/Resources/Private/Language/locallang_mod_language.xml',
+               )
+       );
+}
+
+?>
\ No newline at end of file