├── .travis.yml ├── README.MD ├── app ├── code │ └── community │ │ └── MKleine │ │ └── LanguageRoutes │ │ ├── Block │ │ ├── Adminhtml │ │ │ ├── Languageroute.php │ │ │ └── Languageroute │ │ │ │ ├── Edit.php │ │ │ │ ├── Edit │ │ │ │ ├── Form.php │ │ │ │ ├── Form │ │ │ │ │ └── Renderer │ │ │ │ │ │ └── Fieldset │ │ │ │ │ │ └── Languageroute.php │ │ │ │ ├── Tab │ │ │ │ │ └── Form.php │ │ │ │ └── Tabs.php │ │ │ │ └── Grid.php │ │ └── Translate │ │ │ └── Uri.php │ │ ├── Controller │ │ └── Varien │ │ │ └── Router │ │ │ └── Standard.php │ │ ├── Helper │ │ └── Data.php │ │ ├── Model │ │ ├── Config │ │ │ └── Source │ │ │ │ └── Routetypes.php │ │ ├── Core │ │ │ └── Url.php │ │ ├── Languageroute.php │ │ ├── Observer.php │ │ ├── Resource │ │ │ ├── Languageroute.php │ │ │ └── Languageroute │ │ │ │ └── Collection.php │ │ └── Translation.php │ │ ├── Test │ │ ├── Config │ │ │ └── Main.php │ │ ├── Controller │ │ │ └── Router.php │ │ ├── Helper │ │ │ └── Data.php │ │ └── Model │ │ │ ├── Config │ │ │ └── Source │ │ │ │ └── Routetypes.php │ │ │ └── Translation.php │ │ ├── controllers │ │ ├── Adminhtml │ │ │ └── LanguagerouteController.php │ │ └── TranslationController.php │ │ ├── etc │ │ ├── adminhtml.xml │ │ ├── config.xml │ │ └── system.xml │ │ └── sql │ │ └── languageroutes_setup │ │ └── mysql4-install-0.1.0.php ├── design │ ├── adminhtml │ │ └── default │ │ │ └── default │ │ │ └── layout │ │ │ └── mk_languageroutes.xml │ └── frontend │ │ └── base │ │ └── default │ │ └── template │ │ └── mkleine │ │ └── languageroutes │ │ └── translate │ │ └── uri.phtml ├── etc │ └── modules │ │ └── MKleine_LanguageRoutes.xml └── locale │ ├── de_DE │ └── MKleine_LanguageRoutes.csv │ ├── en_US │ └── MKleine_LanguageRoutes.csv │ └── it_IT │ └── MKleine_LanguageRoutes.csv ├── composer.json ├── modman ├── phpunit.xml.dist └── screenshots ├── Backend-Form.png ├── Backend-Grid.png └── Inline-Translation.png /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 5.3 4 | env: 5 | - MAGENTO_VERSION=magento-ce-1.9.1.0 6 | script: 7 | - curl -sSL https://raw.githubusercontent.com/webguys-de/MageTestStand/master/setup.sh | bash 8 | addons: 9 | code_climate: 10 | repo_token: 03942e903cbb5b61f64625e1e18d98949cd802db4d4e422858ed5ac98e995afc 11 | notifications: 12 | email: 13 | recipients: 14 | - dev@mkleine.de 15 | on_success: always 16 | on_failure: always 17 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # Magento Language Routes 2 | 3 | [![Build Status](https://travis-ci.org/klein0r/magento-language-routes.svg?branch=master)](https://travis-ci.org/klein0r/magento-language-routes) [![Code Climate](https://codeclimate.com/github/klein0r/magento-language-routes/badges/gpa.svg)](https://codeclimate.com/github/klein0r/magento-language-routes) [![Latest Stable Version](https://poser.pugx.org/mkleine/magento-language-routes/v/stable)](https://packagist.org/packages/mkleine/magento-language-routes) [![Total Downloads](https://poser.pugx.org/mkleine/magento-language-routes/downloads)](https://packagist.org/packages/mkleine/magento-language-routes) [![Latest Unstable Version](https://poser.pugx.org/mkleine/magento-language-routes/v/unstable)](https://packagist.org/packages/mkleine/magento-language-routes) [![License](https://poser.pugx.org/mkleine/magento-language-routes/license)](https://packagist.org/packages/mkleine/magento-language-routes) 4 | 5 | 6 | ## Features 7 | 8 | - Translate all URLs for each store (e.g. /customer/account/create -> /kunde/konto/erstellen) 9 | - Easy translation without development skills by using the backend 10 | - Translate third party extensions out of the box 11 | - Ability to translate URLs to CMS pages, too 12 | - Extension uses the **Magento Cache** to avoid performance issues 13 | - **Manage permissions** for translations by roles 14 | - Old URLs are still working (even if they translated) 15 | - **Inline-Translation of URLs** 16 | 17 | ## Configuration 18 | 19 | You can enable the translation module for each store in configuration: 20 | 21 | - System / Configuration / Web / Url Options / Enable route translation (**default: Yes**) 22 | 23 | It is possible to forward the user automatically to the translated URL: 24 | 25 | - System / Configuration / Web / Url Options / Forward to translated route (**default: No**) 26 | 27 | ## Usage 28 | 29 | **It is recommended, to install and test this extension in a test environment.** 30 | 31 | Example: You want translate "/customer/account/login" to "/kunde/konto/anmelden" 32 | 33 | ### By using the Backend 34 | 35 | *This is recommended when adding translations in production environments* 36 | 37 | 1. Go to System / Language Routes 38 | 2. Click Add 39 | 3. Choose your store 40 | 4. Select a route part 41 | - Route: **customer** is the route in this url 42 | - Controller: **account** is the controller 43 | - Action: **login** is the action 44 | 5. Enter a translation 45 | 6. Save 46 | 7. Check the changes in Frontend 47 | 48 | ### By using inline translation 49 | 50 | *This is recommended when adding translations in staging / development environments* 51 | 52 | 1. Go to System / Configuration 53 | 2. Open the Developer menu 54 | 3. Navigate to "Translate inline" 55 | 4. Enabled for Frontend -> Yes 56 | 5. Clear caches 57 | 6. Open the frontend and translate every url step by step 58 | 59 | ## Screenshots 60 | 61 | ![Backend Grid](/screenshots/Backend-Grid.png) 62 | 63 | ![Backend Grid](/screenshots/Backend-Form.png) 64 | 65 | ![Backend Grid](/screenshots/Inline-Translation.png) 66 | 67 | ## Dev 68 | 69 | If you need an url which is not translated, you can add the parameter _notranslate (set it to true) 70 | This is the same behavior, as requesting secure urls by adding _secure. 71 | 72 | This package is also available at [Packagist](https://packagist.org/packages/mkleine/magento-language-routes) 73 | 74 | ## Requirements 75 | 76 | - PHP >= 5.3.0 77 | - Magento 1.6, 1.7, 1.8, 1.9 78 | 79 | ## Contributors 80 | 81 | - Matthias Kleine - [Magento Certified Developer](http://www.magentocommerce.com/certification/directory/dev/878053/) 82 | 83 | Copyright (c) 2014 Matthias Kleine 84 | 85 | Permission is hereby granted, free of charge, to any person obtaining a copy 86 | of this software and associated documentation files (the "Software"), to deal 87 | in the Software without restriction, including without limitation the rights 88 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 89 | copies of the Software, and to permit persons to whom the Software is 90 | furnished to do so, subject to the following conditions: 91 | 92 | The above copyright notice and this permission notice shall be included in 93 | all copies or substantial portions of the Software. 94 | 95 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 96 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 97 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 98 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 99 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 100 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 101 | THE SOFTWARE. 102 | -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Block/Adminhtml/Languageroute.php: -------------------------------------------------------------------------------- 1 | _controller = 'adminhtml_languageroute'; 41 | $this->_blockGroup = 'mk_languageroutes'; 42 | $this->_headerText = $helper->__('Language Route'); 43 | $this->_addButtonLabel = $helper->__('Add Translation'); 44 | 45 | parent::__construct(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Block/Adminhtml/Languageroute/Edit.php: -------------------------------------------------------------------------------- 1 | _objectId = 'id'; 40 | $this->_blockGroup = 'mk_languageroutes'; 41 | $this->_controller = 'adminhtml_languageroute'; 42 | 43 | $this->_updateButton('save', 'label', $this->__('Save Translation')); 44 | $this->_updateButton('delete', 'label', $this->__('Delete Translation')); 45 | 46 | $this->_addButton('saveandcontinue', array( 47 | 'label' => $this->__('Save And Continue Edit'), 48 | 'onclick' => 'saveAndContinueEdit()', 49 | 'class' => 'save', 50 | ), -100); 51 | 52 | $this->_formScripts[] = " 53 | function saveAndContinueEdit(){ 54 | editForm.submit($('edit_form').action+'back/edit/'); 55 | } 56 | "; 57 | } 58 | 59 | public function getHeaderText() 60 | { 61 | if( Mage::registry('languageroute_data') && Mage::registry('languageroute_data')->getId() ) { 62 | /** @var $route MKleine_LanguageRoutes_Model_Languageroute */ 63 | $route = Mage::registry('languageroute_data'); 64 | 65 | return $this->__("%s -> %s", $this->escapeHtml($route->getValue()), $this->escapeHtml($route->getTranslation())); 66 | } else { 67 | return $this->__('Add Translation'); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Block/Adminhtml/Languageroute/Edit/Form.php: -------------------------------------------------------------------------------- 1 | 'edit_form', 40 | 'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))), 41 | 'method' => 'post', 42 | 'enctype' => 'multipart/form-data' 43 | ) 44 | ); 45 | 46 | $form->setUseContainer(true); 47 | $this->setForm($form); 48 | return parent::_prepareForm(); 49 | } 50 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Block/Adminhtml/Languageroute/Edit/Form/Renderer/Fieldset/Languageroute.php: -------------------------------------------------------------------------------- 1 | getHtmlId().'\').value = this.value;" id="'.$this->getHtmlId().'-suggest" name="'.$this->getName().'-suggest" '.$this->serialize($this->getHtmlAttributes()).' style="margin-bottom: 10px;">'."\n"; 12 | 13 | // All routes 14 | $html .= ''; 15 | foreach ($helper->getAvailableRoutes() as $route) { 16 | $html .= ''; 17 | } 18 | $html .= ''."\n"; 19 | 20 | // All controllers 21 | $html .= ''; 22 | foreach ($helper->getAvailableControllers() as $controller) { 23 | $html .= ''; 24 | } 25 | $html .= ''."\n"; 26 | 27 | $html.= ''."\n"; 28 | $html .= parent::getElementHtml(); 29 | 30 | return $html; 31 | } 32 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Block/Adminhtml/Languageroute/Edit/Tab/Form.php: -------------------------------------------------------------------------------- 1 | __('Translation'); 40 | } 41 | 42 | public function getTabTitle() 43 | { 44 | return $this->__('Translation'); 45 | } 46 | 47 | public function canShowTab() 48 | { 49 | return true; 50 | } 51 | 52 | public function isHidden() 53 | { 54 | return false; 55 | } 56 | 57 | /** 58 | * Check permission for passed action 59 | * 60 | * @param string $action 61 | * @return bool 62 | */ 63 | protected function _isAllowedAction($action) 64 | { 65 | return Mage::getSingleton('admin/session')->isAllowed('cms/page/' . $action); 66 | } 67 | 68 | protected function _prepareForm() 69 | { 70 | /* 71 | * Checking if user have permissions to save information 72 | */ 73 | if ($this->_isAllowedAction('save')) { 74 | $isElementDisabled = false; 75 | } else { 76 | $isElementDisabled = true; 77 | } 78 | 79 | $form = new Varien_Data_Form(); 80 | $this->setForm($form); 81 | $fieldset = $form->addFieldset( 82 | 'languageroute_form', 83 | array( 84 | 'legend' => Mage::helper('mk_languageroutes')->__('Settings') 85 | ) 86 | ); 87 | 88 | $fieldset->addType('languageroute', 'MKleine_LanguageRoutes_Block_Adminhtml_Languageroute_Edit_Form_Renderer_Fieldset_Languageroute'); 89 | 90 | /** 91 | * Check is single store mode 92 | */ 93 | if (!Mage::app()->isSingleStoreMode()) { 94 | $field = $fieldset->addField( 95 | 'store_id', 96 | 'select', 97 | array( 98 | 'label' => Mage::helper('cms')->__('Store View'), 99 | 'title' => Mage::helper('cms')->__('Store View'), 100 | 'required' => true, 101 | 'values' => Mage::getSingleton('adminhtml/system_store')->getStoreValuesForForm(false, false), 102 | 'disabled' => $isElementDisabled, 103 | 'name' => 'store_id', 104 | ) 105 | ); 106 | $renderer = $this->getLayout()->createBlock('adminhtml/store_switcher_form_renderer_fieldset_element'); 107 | $field->setRenderer($renderer); 108 | } else { 109 | $fieldset->addField( 110 | 'store_id', 111 | 'hidden', 112 | array( 113 | 'value' => Mage::app()->getStore(true)->getId() 114 | ) 115 | ); 116 | } 117 | 118 | $fieldset->addField( 119 | 'type_id', 120 | 'select', 121 | array( 122 | 'label' => $this->__('Route Part'), 123 | 'required' => true, 124 | 'name' => 'type_id', 125 | 'values' => Mage::getSingleton('mk_languageroutes/config_source_routetypes')->toOptionArray() 126 | ) 127 | ); 128 | 129 | $fieldset->addField( 130 | 'value', 131 | 'languageroute', 132 | array( 133 | 'label' => $this->__('Original Value'), 134 | 'required' => true, 135 | 'name' => 'value' 136 | ) 137 | ); 138 | 139 | $fieldset->addField( 140 | 'translation', 141 | 'text', 142 | array( 143 | 'label' => $this->__('Translation'), 144 | 'required' => true, 145 | 'name' => 'translation' 146 | ) 147 | ); 148 | 149 | $fieldset->addField( 150 | 'is_active', 151 | 'select', 152 | array( 153 | 'label' => $this->__('Is Active'), 154 | 'required' => true, 155 | 'name' => 'is_active', 156 | 'values' => Mage::getSingleton('adminhtml/system_config_source_yesno')->toOptionArray() 157 | ) 158 | ); 159 | 160 | Mage::dispatchEvent('languageroute_adminhtml_form_edit', array( 161 | 'form' => $this 162 | )); 163 | 164 | if (Mage::getSingleton('adminhtml/session')->getLanguagerouteData()) { 165 | $form->setValues(Mage::getSingleton('adminhtml/session')->getLanguagerouteData()); 166 | Mage::getSingleton('adminhtml/session')->setLanguagerouteData(null); 167 | } elseif (Mage::registry('languageroute_data')) { 168 | $form->setValues(Mage::registry('languageroute_data')->getData()); 169 | } 170 | 171 | return parent::_prepareForm(); 172 | } 173 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Block/Adminhtml/Languageroute/Edit/Tabs.php: -------------------------------------------------------------------------------- 1 | setId('languageroute_tabs'); 39 | $this->setDestElementId('edit_form'); 40 | $this->setTitle(Mage::helper('mk_languageroutes')->__('Language route')); 41 | } 42 | 43 | protected function _beforeToHtml() 44 | { 45 | $this->addTab('form_section', array( 46 | 'label' => Mage::helper('mk_languageroutes')->__('Language route'), 47 | 'title' => Mage::helper('mk_languageroutes')->__('Language route'), 48 | 'content' => $this->getLayout()->createBlock('mk_languageroutes/adminhtml_languageroute_edit_tab_form')->toHtml(), 49 | )); 50 | 51 | return parent::_beforeToHtml(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Block/Adminhtml/Languageroute/Grid.php: -------------------------------------------------------------------------------- 1 | setId('languagerouteGrid'); 40 | $this->setSaveParametersInSession(true); 41 | } 42 | 43 | protected function _prepareCollection() 44 | { 45 | $collection = Mage::getModel('mk_languageroutes/languageroute')->getCollection(); 46 | $this->setCollection($collection); 47 | 48 | return parent::_prepareCollection(); 49 | } 50 | 51 | protected function _prepareColumns() 52 | { 53 | $this->addColumn( 54 | 'entity_id', 55 | array( 56 | 'header' => $this->__('ID'), 57 | 'align' => 'right', 58 | 'width' => '50px', 59 | 'index' => 'entity_id', 60 | ) 61 | ); 62 | 63 | $this->addColumn( 64 | 'store_id', 65 | array( 66 | 'header' => $this->__('Store'), 67 | 'align' => 'left', 68 | 'index' => 'store_id', 69 | 'type' => 'store', 70 | 'sortable' => true 71 | ) 72 | ); 73 | 74 | $this->addColumn( 75 | 'type_id', 76 | array( 77 | 'header' => $this->__('Type'), 78 | 'align' => 'left', 79 | 'index' => 'type_id', 80 | 'type' => 'options', 81 | 'sortable' => true, 82 | 'options' => Mage::getSingleton('mk_languageroutes/config_source_routetypes')->toArray() 83 | ) 84 | ); 85 | 86 | $this->addColumn( 87 | 'value', 88 | array( 89 | 'header' => $this->__('Value'), 90 | 'align' => 'left', 91 | 'index' => 'value', 92 | ) 93 | ); 94 | 95 | $this->addColumn( 96 | 'translation', 97 | array( 98 | 'header' => $this->__('Translation'), 99 | 'align' => 'left', 100 | 'index' => 'translation', 101 | ) 102 | ); 103 | 104 | $this->addColumn( 105 | 'is_active', 106 | array( 107 | 'header' => $this->__('Is Active'), 108 | 'align' => 'left', 109 | 'index' => 'is_active', 110 | 'type' => 'options', 111 | 'sortable' => true, 112 | 'options' => Mage::getSingleton('adminhtml/system_config_source_yesno')->toArray() 113 | ) 114 | ); 115 | 116 | $this->addColumn( 117 | 'action', 118 | array( 119 | 'header' => $this->__('Action'), 120 | 'width' => '100', 121 | 'type' => 'action', 122 | 'getter' => 'getId', 123 | 'actions' => array( 124 | array( 125 | 'caption' => $this->__('Edit'), 126 | 'url' => array('base' => '*/*/edit'), 127 | 'field' => 'id' 128 | ) 129 | ), 130 | 'filter' => false, 131 | 'sortable' => false, 132 | 'index' => 'stores', 133 | 'is_system' => true, 134 | ) 135 | ); 136 | 137 | return parent::_prepareColumns(); 138 | } 139 | 140 | protected function _prepareMassaction() 141 | { 142 | $this->setMassactionIdField('languageroute_id'); 143 | $this->getMassactionBlock()->setFormFieldName('languageroute'); 144 | 145 | $this->getMassactionBlock()->addItem( 146 | 'delete', 147 | array( 148 | 'label' => Mage::helper('mk_languageroutes')->__('Delete'), 149 | 'url' => $this->getUrl('*/*/massDelete'), 150 | 'confirm' => Mage::helper('mk_languageroutes')->__('Are you sure?') 151 | ) 152 | ); 153 | 154 | return $this; 155 | } 156 | 157 | public function getRowUrl($row) 158 | { 159 | return $this->getUrl('*/*/edit', array('id' => $row->getId())); 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Block/Translate/Uri.php: -------------------------------------------------------------------------------- 1 | setTemplate('mkleine/languageroutes/translate/uri.phtml'); 9 | } 10 | 11 | /** 12 | * Returns the action to the admin form controller 13 | * 14 | * @return string 15 | */ 16 | public function getFormAction() 17 | { 18 | return Mage::getUrl('languageroute/translation/saveinline'); 19 | } 20 | 21 | public function getFormKey() 22 | { 23 | $appEmulation = Mage::getSingleton('core/app_emulation'); 24 | $initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation(Mage_Core_Model_App::ADMIN_STORE_ID); 25 | 26 | $formKey = Mage::getSingleton('core/session')->getFormKey(); 27 | 28 | $appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo); 29 | 30 | return $formKey; 31 | } 32 | 33 | /** 34 | * Checks, if the current user is allowed to translate the current url 35 | * 36 | * @return bool 37 | */ 38 | public function isAllowed() 39 | { 40 | return Mage::helper('mk_languageroutes')->isInlineTranslationEnabled(); 41 | } 42 | 43 | /** 44 | * @param bool $translate 45 | * @return MKleine_LanguageRoutes_Model_Core_Url 46 | */ 47 | protected function getUrlModel($translate = true) 48 | { 49 | return Mage::getModel('core/url') 50 | ->setRoutePath('*/*/*') 51 | ->setNoTranslate(!$translate); 52 | } 53 | 54 | /** 55 | * Returns the translation of the current route 56 | * @return string 57 | */ 58 | public function getValueRoute() 59 | { 60 | $value = $this->getUrlModel()->getRouteFrontName(); 61 | return ($value != $this->getUntranslatedRoute()) ? $value : ''; 62 | } 63 | 64 | public function getUntranslatedRoute() 65 | { 66 | return $this->getUrlModel(false)->getRouteFrontName(); 67 | } 68 | 69 | /** 70 | * Returns the translation of the current controller 71 | * @return string 72 | */ 73 | public function getValueController() 74 | { 75 | $value = $this->getUrlModel()->getControllerName(); 76 | return ($value != $this->getUntranslatedController()) ? $value : ''; 77 | } 78 | 79 | public function getUntranslatedController() 80 | { 81 | return $this->getUrlModel(false)->getControllerName(); 82 | } 83 | 84 | /** 85 | * Returns the translation of the current action 86 | * @return string 87 | */ 88 | public function getValueAction() 89 | { 90 | $value = $this->getUrlModel()->getActionName(); 91 | return ($value != $this->getUntranslatedAction()) ? $value : ''; 92 | } 93 | 94 | public function getUntranslatedAction() 95 | { 96 | return $this->getUrlModel(false)->getActionName(); 97 | } 98 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Controller/Varien/Router/Standard.php: -------------------------------------------------------------------------------- 1 | isUriTranslatable($request->getPathInfo())) { 51 | 52 | /** @var $translationModel MKleine_LanguageRoutes_Model_Translation */ 53 | $translationModel = Mage::getSingleton('mk_languageroutes/translation'); 54 | $translationModel->setRequest($request); 55 | 56 | Mage::dispatchEvent('languageroute_set_path_info_before', array( 57 | 'translation_model' => $translationModel 58 | )); 59 | 60 | if ($internalRoute = $translationModel->getTranslatedPath()) { 61 | 62 | Mage::register('languageroute_information', new Varien_Object(array( 63 | 'original' => trim($request->getPathInfo(), '/'), 64 | 'internal' => trim($internalRoute, '/') 65 | ))); 66 | 67 | $request->setPathInfo($internalRoute); 68 | } 69 | } 70 | return parent::match($request); 71 | } 72 | 73 | public function getFrontNames() 74 | { 75 | return array_unique(array_keys($this->_modules)); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Helper/Data.php: -------------------------------------------------------------------------------- 1 | isTranslationEnabled() && strpos($url, '.html') === false); 40 | } 41 | 42 | /** 43 | * @return bool Check if extension is enabled 44 | */ 45 | public function isTranslationEnabled() 46 | { 47 | return (bool)Mage::getStoreConfig('web/url/enable_route_translation'); 48 | } 49 | 50 | /** 51 | * @return bool 52 | */ 53 | public function isInlineTranslationEnabled() 54 | { 55 | /** @var $translate Mage_Core_Model_Translate_Inline */ 56 | $translate = Mage::getSingleton('core/translate_inline'); 57 | return $translate->isAllowed() && $this->isTranslationEnabled(); 58 | } 59 | 60 | /** 61 | * Will create a new router to collect all standard routes 62 | * 63 | * @return array 64 | */ 65 | public function getAvailableRoutes() 66 | { 67 | $router = new MKleine_LanguageRoutes_Controller_Varien_Router_Standard(); 68 | $router->collectRoutes(Mage_Core_Model_App_Area::AREA_FRONTEND, 'standard'); 69 | return $router->getFrontNames(); 70 | } 71 | 72 | /** 73 | * Clears the cache of all translated routes 74 | */ 75 | public function clearTranslationCache() 76 | { 77 | /** @var $translationModel MKleine_LanguageRoutes_Model_Translation */ 78 | $translationModel = Mage::getSingleton('mk_languageroutes/translation'); 79 | $translationModel->clearCache(); 80 | } 81 | 82 | /** 83 | * Collects all controllers which can be used for frontend 84 | * 85 | * @return array 86 | */ 87 | public function getAvailableControllers() 88 | { 89 | $allModules = Mage::getConfig()->getNode('modules')->children(); 90 | 91 | $controllers = array(); 92 | foreach ($allModules as $moduleName => $moduleSettings) { 93 | if (Mage::helper('core')->isModuleEnabled($moduleName)) 94 | { 95 | foreach (glob(Mage::getModuleDir('controllers', $moduleName). DS . '*') as $controller) { 96 | if (is_file($controller) && strpos($controller, 'Adminhtml') === false) { 97 | $controllers[] = strtolower(str_replace('Controller.php', '', basename($controller))); 98 | } 99 | } 100 | } 101 | } 102 | 103 | return array_unique($controllers); 104 | } 105 | 106 | public function getAvailableActions() 107 | { 108 | // TODO: Try to get a list of available options 109 | return array(); 110 | } 111 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Model/Config/Source/Routetypes.php: -------------------------------------------------------------------------------- 1 | MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ROUTER, 44 | 'label' => Mage::helper('mk_languageroutes')->__('Route') 45 | ), 46 | array( 47 | 'value' => MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_CONTROLLER, 48 | 'label' => Mage::helper('mk_languageroutes')->__('Controller') 49 | ), 50 | array( 51 | 'value' => MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ACTION, 52 | 'label' => Mage::helper('mk_languageroutes')->__('Action') 53 | ), 54 | ); 55 | } 56 | 57 | /** 58 | * Get options in "key-value" format 59 | * 60 | * @return array 61 | */ 62 | public function toArray() 63 | { 64 | return array( 65 | MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ROUTER => Mage::helper('mk_languageroutes')->__('Route'), 66 | MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_CONTROLLER => Mage::helper('mk_languageroutes')->__('Controller'), 67 | MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ACTION => Mage::helper('mk_languageroutes')->__('Action'), 68 | ); 69 | } 70 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Model/Core/Url.php: -------------------------------------------------------------------------------- 1 | getNoTranslate() !== true); 52 | } 53 | 54 | public function setRouteParams(array $data, $unsetOldParams = true) 55 | { 56 | if (isset($data['_notranslate'])) { 57 | $this->setNoTranslate($data['_notranslate']); 58 | unset($data['_notranslate']); 59 | } 60 | 61 | parent::setRouteParams($data, $unsetOldParams); 62 | } 63 | 64 | /** 65 | * Translates the route part before delivered to frontend 66 | * 67 | * @return false|mixed|string 68 | */ 69 | public function getRouteFrontName() 70 | { 71 | if (!$this->translationEnabled()) { 72 | return parent::getRouteFrontName(); 73 | } 74 | 75 | return $this->getTranslationModel()->translateRouteToFront(parent::getRouteFrontName()); 76 | } 77 | 78 | /** 79 | * Translates the controller part before delivered to frontend 80 | * 81 | * @return false|mixed|null|string 82 | */ 83 | public function getControllerName() 84 | { 85 | if (!$this->translationEnabled()) { 86 | return parent::getControllerName(); 87 | } 88 | 89 | return $this->getTranslationModel()->translateControllerToFront(parent::getControllerName()); 90 | } 91 | 92 | /** 93 | * Translates the action part before delivered to frontend 94 | * 95 | * @return false|mixed|null|string 96 | */ 97 | public function getActionName() 98 | { 99 | if (!$this->translationEnabled()) { 100 | return parent::getActionName(); 101 | } 102 | 103 | return $this->getTranslationModel()->translateActionToFront(parent::getActionName()); 104 | } 105 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Model/Languageroute.php: -------------------------------------------------------------------------------- 1 | _init('mk_languageroutes/languageroute'); 60 | } 61 | 62 | protected function _beforeSave() 63 | { 64 | $timestamp = Mage::getModel('core/date')->timestamp(); 65 | $this->setUpdatedAt($timestamp); 66 | 67 | if (!$this->getId()) { 68 | $this->setCreatedAt($timestamp); 69 | } 70 | 71 | return parent::_beforeSave(); 72 | } 73 | 74 | /** 75 | * Get languageroute created at date timestamp 76 | * 77 | * @return int|null 78 | */ 79 | public function getCreatedAtTimestamp() 80 | { 81 | $date = $this->getCreatedAt(); 82 | if ($date) { 83 | return Varien_Date::toTimestamp($date); 84 | } 85 | return null; 86 | } 87 | 88 | /** 89 | * Get the timestamp of the latest update 90 | * 91 | * @return int|null 92 | */ 93 | public function getUpdatedAtTimestamp() 94 | { 95 | $date = $this->getUpdatedAt(); 96 | if ($date) { 97 | return Varien_Date::toTimestamp($date); 98 | } 99 | return null; 100 | } 101 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Model/Observer.php: -------------------------------------------------------------------------------- 1 | clearTranslationCache(); 42 | } 43 | 44 | /** 45 | * Will add a canonical link to the non translated version of the url 46 | * 47 | * @param $observer Varien_Event_Observer 48 | */ 49 | public function controllerActionLayoutRenderBefore($observer) 50 | { 51 | if ($routeInfo = Mage::registry('languageroute_information')) { 52 | if ($routeInfo->getOriginal() != $routeInfo->getInternal()) { 53 | /** @var $headBlock Mage_Page_Block_Html_Head */ 54 | $headBlock = Mage::app()->getLayout()->getBlock('head'); 55 | $headBlock->addLinkRel('canonical', Mage::getUrl($routeInfo->getInternal(), array('_notranslate' => true))); 56 | } 57 | } 58 | } 59 | 60 | /** 61 | * Adds translation block for current url when inline translation is enabled 62 | * and module has been activated 63 | * 64 | * @param $observer Varien_Event_Observer 65 | */ 66 | public function controllerActionLayoutGenerateBlocksAfter($observer) 67 | { 68 | if (Mage::helper('mk_languageroutes')->isInlineTranslationEnabled()) { 69 | /** @var $layout Mage_Core_Model_Layout */ 70 | $layout = $observer->getLayout(); 71 | 72 | if ($contentBlock = $layout->getBlock('content')) { 73 | $translateBlock = $layout->createBlock( 74 | 'mk_languageroutes/translate_uri', 75 | 'languageroutes_inline_translate_uri' 76 | ); 77 | 78 | $contentBlock->append($translateBlock); 79 | } 80 | } 81 | } 82 | 83 | /** 84 | * Forward the client to the translated url if configured 85 | * 86 | * @param $observer Varien_Event_Observer 87 | */ 88 | public function controllerActionPredispatch($observer) 89 | { 90 | if ($redirectCode = (int)Mage::getStoreConfig('web/url/forward_to_translated')) { 91 | if ($redirectCode != 301) { 92 | $redirectCode = 302; 93 | } 94 | 95 | /** @var $controllerAction Mage_Core_Controller_Front_Action */ 96 | $controllerAction = $observer->getControllerAction(); 97 | $pathInfo = trim($controllerAction->getRequest()->getOriginalPathInfo(), '/'); 98 | $translatedPathInfo = trim(str_replace(Mage::getBaseUrl(), '', Mage::getUrl($pathInfo)), '/'); 99 | 100 | // Check if a translated version of the path exists 101 | if ($pathInfo != $translatedPathInfo) { 102 | $controllerAction->getResponse() 103 | ->setRedirect(Mage::getUrl($pathInfo), $redirectCode) 104 | ->sendResponse(); 105 | exit; 106 | } 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Model/Resource/Languageroute.php: -------------------------------------------------------------------------------- 1 | _init('mk_languageroutes/languageroute', 'entity_id'); 38 | } 39 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Model/Resource/Languageroute/Collection.php: -------------------------------------------------------------------------------- 1 | _init('mk_languageroutes/languageroute'); 39 | } 40 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Model/Translation.php: -------------------------------------------------------------------------------- 1 | hasData('store_id')) { 46 | $this->setData('store_id', $storeId = Mage::app()->getStore()->getId()); 47 | } 48 | return $this->getData('store_id'); 49 | } 50 | 51 | public function getTranslatedPath() 52 | { 53 | /** @var $request Zend_Controller_Request_Http */ 54 | if ($request = $this->getRequest()) { 55 | $pathInfo = explode('/', $request->getPathInfo(), 5); 56 | 57 | // Route 58 | if (isset($pathInfo[1])) { 59 | $pathInfo[1] = $this->translateRouteToMage($pathInfo[1]); 60 | } 61 | 62 | // Controller 63 | if (isset($pathInfo[2])) { 64 | $pathInfo[2] = $this->translateControllerToMage($pathInfo[2]); 65 | } 66 | 67 | // Action 68 | if (isset($pathInfo[3])) { 69 | $pathInfo[3] = $this->translateActionToMage($pathInfo[3]); 70 | } 71 | 72 | return join('/', $pathInfo); 73 | } 74 | 75 | return false; 76 | } 77 | 78 | public function translateRouteToMage($route) 79 | { 80 | return $this->translateToMage( 81 | $route, 82 | MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ROUTER 83 | ); 84 | } 85 | 86 | public function translateRouteToFront($route) 87 | { 88 | return $this->translateToFront( 89 | $route, 90 | MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ROUTER 91 | ); 92 | } 93 | 94 | public function translateControllerToMage($controller) 95 | { 96 | return $this->translateToMage( 97 | $controller, 98 | MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_CONTROLLER 99 | ); 100 | } 101 | 102 | public function translateControllerToFront($controller) 103 | { 104 | return $this->translateToFront( 105 | $controller, 106 | MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_CONTROLLER 107 | ); 108 | } 109 | 110 | public function translateActionToMage($action) 111 | { 112 | return $this->translateToMage( 113 | $action, 114 | MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ACTION 115 | ); 116 | } 117 | 118 | public function translateActionToFront($action) 119 | { 120 | return $this->translateToFront( 121 | $action, 122 | MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ACTION 123 | ); 124 | } 125 | 126 | protected function translateToFront($value, $typeId) 127 | { 128 | /** @var $collection MKleine_LanguageRoutes_Model_Resource_Languageroute_Collection */ 129 | $collection = $this->getRouteCollection($typeId) 130 | ->addFieldToFilter('value', $value); 131 | 132 | $cacheKey = sprintf('language_route_front_%d_%d_%s', $this->getStoreId(), $typeId, $value); 133 | return $this->getValueOfCollection('translation', $collection, $value, $cacheKey); 134 | } 135 | 136 | protected function translateToMage($translation, $typeId) 137 | { 138 | $collection = $this->getRouteCollection($typeId) 139 | ->addFieldToFilter('translation', $translation); 140 | 141 | $cacheKey = sprintf('language_route_mage_%d_%d_%s', $this->getStoreId(), $typeId, $translation); 142 | return $this->getValueOfCollection('value', $collection, $translation, $cacheKey); 143 | } 144 | 145 | /** 146 | * @return MKleine_LanguageRoutes_Model_Resource_Languageroute_Collection 147 | */ 148 | protected function getRouteCollection($typeId) 149 | { 150 | return Mage::getModel('mk_languageroutes/languageroute')->getCollection() 151 | ->addFieldToFilter('store_id', $this->getStoreId()) 152 | ->addFieldToFilter('type_id', $typeId) 153 | ->addFieldToFilter('is_active', 1); 154 | } 155 | 156 | protected function getValueOfCollection($value, $collection, $fallback, $cacheKey) 157 | { 158 | /* @var $cache Varien_Cache_Core */ 159 | $cache = Mage::app()->getCache(); 160 | 161 | if ($cache && $cache->test($cacheKey)) { 162 | return $cache->load($cacheKey); 163 | } 164 | 165 | if ($collection->getSize() > 0) { 166 | $firstItem = $collection->getFirstItem(); 167 | $return = $firstItem->getData($value); 168 | 169 | if ($cache) { 170 | $cache->save($return, $cacheKey, array(self::LANGUAGEROUTE_CACHE_TAG)); 171 | } 172 | 173 | return $return; 174 | } 175 | 176 | return $fallback; 177 | } 178 | 179 | public function clearCache() 180 | { 181 | /* @var $cache Varien_Cache_Core */ 182 | $cache = Mage::app()->getCache(); 183 | if ($cache) { 184 | $cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array(self::LANGUAGEROUTE_CACHE_TAG)); 185 | } 186 | } 187 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Test/Config/Main.php: -------------------------------------------------------------------------------- 1 | assertModuleCodePool('community'); 41 | } 42 | 43 | /** 44 | * @test 45 | */ 46 | public function testHelpers() 47 | { 48 | $this->assertHelperAlias('mk_languageroutes', 'MKleine_LanguageRoutes_Helper_Data'); 49 | $this->assertHelperAlias('mk_languageroutes/data', 'MKleine_LanguageRoutes_Helper_Data'); 50 | } 51 | 52 | /** 53 | * @test 54 | */ 55 | public function testModels() 56 | { 57 | $this->assertModelAlias('mk_languageroutes/translation', 'MKleine_LanguageRoutes_Model_Translation'); 58 | $this->assertModelAlias('mk_languageroutes/languageroute', 'MKleine_LanguageRoutes_Model_Languageroute'); 59 | } 60 | 61 | /** 62 | * @test 63 | */ 64 | public function testRewrites() 65 | { 66 | $this->assertModelAlias('core/url', 'MKleine_LanguageRoutes_Model_Core_Url'); 67 | } 68 | 69 | /** 70 | * @test 71 | */ 72 | public function testObserverRegistrations() 73 | { 74 | // Frontend 75 | $this->assertEventObserverDefined( 76 | 'frontend', 77 | 'controller_action_layout_render_before', 78 | 'mk_languageroutes/observer', 79 | 'controllerActionLayoutRenderBefore' 80 | ); 81 | 82 | $this->assertEventObserverDefined( 83 | 'frontend', 84 | 'controller_action_layout_generate_blocks_after', 85 | 'mk_languageroutes/observer', 86 | 'controllerActionLayoutGenerateBlocksAfter' 87 | ); 88 | 89 | $this->assertEventObserverDefined( 90 | 'frontend', 91 | 'controller_action_predispatch', 92 | 'mk_languageroutes/observer', 93 | 'controllerActionPredispatch' 94 | ); 95 | 96 | // Adminhtml 97 | $this->assertEventObserverDefined( 98 | 'adminhtml', 99 | 'languageroute_save_after', 100 | 'mk_languageroutes/observer', 101 | 'languagerouteSaveAfter' 102 | ); 103 | } 104 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Test/Controller/Router.php: -------------------------------------------------------------------------------- 1 | markTestIncomplete( 41 | 'This test has not been implemented yet.' 42 | ); 43 | } 44 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Test/Helper/Data.php: -------------------------------------------------------------------------------- 1 | markTestIncomplete( 41 | 'This test has not been implemented yet.' 42 | ); 43 | } 44 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Test/Model/Config/Source/Routetypes.php: -------------------------------------------------------------------------------- 1 | assertEquals(3, count($routeTypes->toArray())); 43 | $this->assertEquals(3, count($routeTypes->toOptionArray())); 44 | } 45 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/Test/Model/Translation.php: -------------------------------------------------------------------------------- 1 | markTestIncomplete( 41 | 'This test has not been implemented yet.' 42 | ); 43 | } 44 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/controllers/Adminhtml/LanguagerouteController.php: -------------------------------------------------------------------------------- 1 | loadLayout() 39 | ->_setActiveMenu('mk_languageroutes/items') 40 | ->_addBreadcrumb( 41 | Mage::helper('adminhtml')->__('Items Manager'), 42 | Mage::helper('adminhtml')->__('Item Manager') 43 | ); 44 | 45 | return $this; 46 | } 47 | 48 | public function indexAction() 49 | { 50 | $this->_initAction()->renderLayout(); 51 | } 52 | 53 | public function editAction() 54 | { 55 | $id = $this->getRequest()->getParam('id', 0); 56 | $model = Mage::getModel('mk_languageroutes/languageroute')->load($id); 57 | 58 | if ($model->getId() || $id == 0) { 59 | $data = Mage::getSingleton('adminhtml/session')->getFormData(true); 60 | if (!empty($data)) { 61 | $model->setData($data); 62 | } 63 | 64 | Mage::register('languageroute_data', $model); 65 | 66 | $this->loadLayout(); 67 | $this->_setActiveMenu('mk_languageroutes/items'); 68 | 69 | $this->_addBreadcrumb( 70 | Mage::helper('adminhtml')->__('Item Manager'), 71 | Mage::helper('adminhtml')->__('Item Manager') 72 | ); 73 | $this->_addBreadcrumb( 74 | Mage::helper('adminhtml')->__('Item News'), 75 | Mage::helper('adminhtml')->__('Item News') 76 | ); 77 | 78 | $this->getLayout()->getBlock('head')->setCanLoadExtJs(true); 79 | 80 | $this->_addContent($this->getLayout()->createBlock('mk_languageroutes/adminhtml_languageroute_edit')) 81 | ->_addLeft($this->getLayout()->createBlock('mk_languageroutes/adminhtml_languageroute_edit_tabs')); 82 | 83 | $this->renderLayout(); 84 | 85 | } else { 86 | Mage::getSingleton('adminhtml/session')->addError( 87 | Mage::helper('mk_languageroutes')->__('Translation does not exist') 88 | ); 89 | $this->_redirect('*/*/'); 90 | } 91 | 92 | } 93 | 94 | public function newAction() 95 | { 96 | $this->_forward('edit'); 97 | } 98 | 99 | public function saveAction() 100 | { 101 | if ($data = $this->getRequest()->getPost()) { 102 | 103 | try { 104 | $model = Mage::getModel('mk_languageroutes/languageroute'); 105 | $model->setData($data)->setId($this->getRequest()->getParam('id')); 106 | 107 | $model->save(); 108 | 109 | Mage::getSingleton('adminhtml/session')->addSuccess($this->__('Item was successfully saved')); 110 | Mage::getSingleton('adminhtml/session')->setFormData(false); 111 | 112 | if ($this->getRequest()->getParam('back')) { 113 | $this->_redirect('*/*/edit', array('id' => $model->getId())); 114 | return; 115 | } 116 | 117 | $this->_redirect('*/*/'); 118 | return; 119 | } catch (Exception $e) { 120 | Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); 121 | Mage::getSingleton('adminhtml/session')->setFormData($data); 122 | $this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id'))); 123 | return; 124 | } 125 | 126 | } 127 | 128 | Mage::getSingleton('adminhtml/session')->addError($this->__('Unable to find item to save')); 129 | $this->_redirect('*/*/'); 130 | } 131 | 132 | public function deleteAction() 133 | { 134 | if ($this->getRequest()->getParam('id') > 0) { 135 | try { 136 | $model = Mage::getModel('mk_languageroutes/languageroute'); 137 | $model->setId($this->getRequest()->getParam('id'))->delete(); 138 | 139 | Mage::getSingleton('adminhtml/session')->addSuccess($this->__('Item was successfully deleted')); 140 | $this->_redirect('*/*/'); 141 | 142 | } catch (Exception $e) { 143 | Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); 144 | $this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id'))); 145 | } 146 | } 147 | 148 | $this->_redirect('*/*/'); 149 | } 150 | 151 | public function massDeleteAction() 152 | { 153 | $languagerouteIds = $this->getRequest()->getParam('languageroute'); 154 | 155 | if (!is_array($languagerouteIds)) { 156 | Mage::getSingleton('adminhtml/session')->addError($this->__('Please select item(s)')); 157 | } else { 158 | try { 159 | foreach ($languagerouteIds as $languagerouteId) { 160 | $languageroute = Mage::getModel('mk_languageroutes/languageroute')->load($languagerouteId); 161 | $languageroute->delete(); 162 | } 163 | 164 | Mage::getSingleton('adminhtml/session')->addSuccess( 165 | Mage::helper('adminhtml')->__( 166 | 'Total of %d record(s) were successfully deleted', 167 | count($languagerouteIds) 168 | ) 169 | ); 170 | 171 | } catch (Exception $e) { 172 | Mage::getSingleton('adminhtml/session')->addError($e->getMessage()); 173 | } 174 | } 175 | 176 | $this->_redirect('*/*/index'); 177 | } 178 | 179 | public function valuesAction() 180 | { 181 | $typeId = $this->getRequest()->getParam( 182 | 'type', 183 | MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ROUTER 184 | ); 185 | 186 | /** @var $helper MKleine_LanguageRoutes_Helper_Data */ 187 | $helper = Mage::helper('mk_languageroutes'); 188 | 189 | $result = array(); 190 | 191 | switch ($typeId) { 192 | 193 | case MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ROUTER: 194 | $result = $helper->getAvailableRoutes(); 195 | break; 196 | 197 | case MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_CONTROLLER: 198 | $result = $helper->getAvailableControllers(); 199 | break; 200 | 201 | case MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ACTION: 202 | $result = $helper->getAvailableActions(); 203 | break; 204 | } 205 | 206 | $this->getResponse()->setHeader('Content-type', 'application/json'); 207 | $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result)); 208 | } 209 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/controllers/TranslationController.php: -------------------------------------------------------------------------------- 1 | isInlineTranslationEnabled()) { 11 | $returlUrl = $this->getRequest()->getParam('current_url', false); 12 | $storeId = $this->getRequest()->getParam('store_id', false); 13 | 14 | $origRoute = $this->getRequest()->getParam('route_untranslated', false); 15 | $origController = $this->getRequest()->getParam('controller_untranslated', false); 16 | $origAction = $this->getRequest()->getParam('action_untranslated', false); 17 | 18 | $newRoute = $this->getRequest()->getParam('route', false); 19 | $newController = $this->getRequest()->getParam('controller', false); 20 | $newAction = $this->getRequest()->getParam('action', false); 21 | 22 | $languageRoutes = array( 23 | array( 24 | 'type_id' => MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ROUTER, 25 | 'store_id' => $storeId, 26 | 'is_active' => 1, 27 | 'value' => $origRoute, 28 | 'translation' => $newRoute 29 | ), 30 | array( 31 | 'type_id' => MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_CONTROLLER, 32 | 'store_id' => $storeId, 33 | 'is_active' => 1, 34 | 'value' => $origController, 35 | 'translation' => $newController 36 | ), 37 | array( 38 | 'type_id' => MKleine_LanguageRoutes_Model_Languageroute::LANGUAGEROUTE_TYPE_ACTION, 39 | 'store_id' => $storeId, 40 | 'is_active' => 1, 41 | 'value' => $origAction, 42 | 'translation' => $newAction 43 | ) 44 | ); 45 | 46 | foreach ($languageRoutes as $languageRoute) 47 | { 48 | /** @var $model MKleine_LanguageRoutes_Model_Languageroute */ 49 | $model = Mage::getModel('mk_languageroutes/languageroute'); 50 | $model->setData($languageRoute); 51 | 52 | $collection = Mage::getModel('mk_languageroutes/languageroute') 53 | ->getCollection() 54 | ->addFieldToFilter('store_id', $model->getStoreId()) 55 | ->addFieldToFilter('type_id', $model->getTypeId()) 56 | ->addFieldToFilter('value', $model->getValue()); 57 | 58 | /** @var $existingItem MKleine_LanguageRoutes_Model_Languageroute */ 59 | if ($existingItem = $collection->getFirstItem()) { 60 | $existingItem->addData($languageRoute); 61 | 62 | if ($existingItem->getTranslation()) { 63 | $existingItem->save(); 64 | } 65 | else { 66 | $existingItem->delete(); 67 | } 68 | } 69 | else if ($model->getTranslation()) { { 70 | $model->save(); 71 | } 72 | } 73 | } 74 | 75 | // Clear route translation cache 76 | Mage::helper('mk_languageroutes')->clearTranslationCache(); 77 | 78 | if ($returlUrl) { 79 | $this->_redirect(sprintf('%s/%s/%s', 80 | $newRoute ?: $origRoute, 81 | $newController ?: $origController, 82 | $newAction ?: $origAction 83 | )); 84 | } 85 | else { 86 | $this->_redirect('/'); 87 | } 88 | } 89 | else { 90 | $this->_redirect('/'); 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/etc/adminhtml.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Language Routes 8 | adminhtml/languageroute 9 | 50 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Language Routes 22 | 50 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 0.1.0 6 | 7 | 8 | 9 | 10 | 11 | MKleine_LanguageRoutes_Model 12 | mk_languageroutes_resource 13 | 14 | 15 | MKleine_LanguageRoutes_Model_Resource 16 | 17 | 18 | languageroutes
19 |
20 |
21 |
22 | 23 | 24 | MKleine_LanguageRoutes_Model_Core_Url 25 | 26 | 27 |
28 | 29 | 30 | MKleine_LanguageRoutes_Block 31 | 32 | 33 | 34 | 35 | MKleine_LanguageRoutes_Helper 36 | 37 | 38 | 39 | 40 | 41 | MKleine_LanguageRoutes 42 | 43 | 44 | core_setup 45 | 46 | 47 | 48 | 49 | core_write 50 | 51 | 52 | 53 | 54 | core_read 55 | 56 | 57 | 58 |
59 | 60 | 61 | 62 | 63 | 64 | MKleine_LanguageRoutes.csv 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | mk_languageroutes/observer 74 | singleton 75 | controllerActionLayoutRenderBefore 76 | 77 | 78 | 79 | 80 | 81 | 82 | mk_languageroutes/observer 83 | singleton 84 | controllerActionLayoutGenerateBlocksAfter 85 | 86 | 87 | 88 | 89 | 90 | 91 | mk_languageroutes/observer 92 | singleton 93 | controllerActionPredispatch 94 | 95 | 96 | 97 | 98 | 99 | 100 | standard 101 | 102 | MKleine_LanguageRoutes 103 | languageroute 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | MKleine_LanguageRoutes_Adminhtml 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | mk_languageroutes.xml 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | MKleine_LanguageRoutes.csv 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | mk_languageroutes/observer 141 | singleton 142 | languagerouteSaveAfter 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 1 152 | 0 153 | 154 | 155 | 156 | frontend 157 | MKleine_LanguageRoutes_Controller_Varien_Router_Standard 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 |
170 | -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/etc/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Activates translation of routes by module language routes 11 | select 12 | adminhtml/system_config_source_yesno 13 | 50 14 | 1 15 | 1 16 | 1 17 | 18 | 19 | 20 | Forward the user to the translated rule when accessing old url 21 | select 22 | adminhtml/system_config_source_web_redirect 23 | 60 24 | 1 25 | 1 26 | 1 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/code/community/MKleine/LanguageRoutes/sql/languageroutes_setup/mysql4-install-0.1.0.php: -------------------------------------------------------------------------------- 1 | startSetup(); 36 | 37 | /** 38 | * Create table 'customer/entity' 39 | */ 40 | $table = $installer->getConnection() 41 | ->newTable($installer->getTable('mk_languageroutes/languageroute')) 42 | ->addColumn('entity_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array( 43 | 'identity' => true, 44 | 'unsigned' => true, 45 | 'nullable' => false, 46 | 'primary' => true, 47 | ), 'Entity Id') 48 | ->addColumn('type_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array( 49 | 'unsigned' => true, 50 | 'nullable' => false, 51 | ), 'Type Id') 52 | ->addColumn('value', Varien_Db_Ddl_Table::TYPE_TEXT, 255, array( 53 | 'nullable' => false, 54 | ), 'Value') 55 | ->addColumn('translation', Varien_Db_Ddl_Table::TYPE_TEXT, 255, array( 56 | 'nullable' => false, 57 | ), 'Translation') 58 | ->addColumn('store_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array( 59 | 'unsigned' => true, 60 | 'default' => '0', 61 | ), 'Store Id') 62 | ->addColumn('created_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array( 63 | 'nullable' => false, 64 | ), 'Created At') 65 | ->addColumn('updated_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array( 66 | 'nullable' => false, 67 | ), 'Updated At') 68 | ->addColumn('is_active', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array( 69 | 'unsigned' => true, 70 | 'nullable' => false, 71 | 'default' => '1', 72 | ), 'Is Active') 73 | ->addIndex($installer->getIdxName('mk_languageroutes/languageroute', array('store_id')), 74 | array('store_id')) 75 | ->addIndex($installer->getIdxName('mk_languageroutes/languageroute', array('store_id', 'type_id', 'value'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE), 76 | array('store_id', 'type_id', 'value'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE)) 77 | ->addIndex($installer->getIdxName('mk_languageroutes/languageroute', array('store_id', 'type_id', 'translation'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE), 78 | array('store_id', 'type_id', 'translation'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE)) 79 | ->addForeignKey($installer->getFkName('mk_languageroutes/languageroute', 'store_id', 'core/store', 'store_id'), 80 | 'store_id', $installer->getTable('core/store'), 'store_id', 81 | Varien_Db_Ddl_Table::ACTION_SET_NULL, Varien_Db_Ddl_Table::ACTION_CASCADE) 82 | ->setComment('Languageroute Entity'); 83 | $installer->getConnection()->createTable($table); 84 | 85 | $installer->endSetup(); -------------------------------------------------------------------------------- /app/design/adminhtml/default/default/layout/mk_languageroutes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/mkleine/languageroutes/translate/uri.phtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | isAllowed()) : ?> 4 |
5 |
6 | __('Translate Uri'); ?> 7 |
8 |
9 |
10 |

__('Route'); ?> (getUntranslatedRoute(); ?>)

11 | 12 | 13 | 14 |

__('Controller'); ?> (getUntranslatedController(); ?>)

15 | 16 | 17 | 18 |

__('Action'); ?> (getUntranslatedAction(); ?>)

19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 |
28 |
29 |
30 |
31 | -------------------------------------------------------------------------------- /app/etc/modules/MKleine_LanguageRoutes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | community 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/locale/de_DE/MKleine_LanguageRoutes.csv: -------------------------------------------------------------------------------- 1 | "Language Route","Sprach-URL" 2 | "Language Routes","Sprach-URLs" 3 | "Add Translation","Übersetzung hinzufügen" 4 | "Save And Continue Edit","Speichern und weiter bearbeiten" 5 | "Save Translation","Übersetzung speichern" 6 | "Delete Translation","Übersetzung löschen" 7 | "Type","Typ" 8 | "Value","Wert" 9 | "Translation","Übersetzung" 10 | "Is Active","Aktiv" 11 | "Action","Aktion" 12 | "Route Part","URL-Teil" 13 | "Original Value","Original Wert" 14 | "Translation does not exist","Übersetzung existiert nicht" 15 | "Route","Route" 16 | "Controller","Controller" 17 | "Action","Action" 18 | "Enable route translation","URL-Übersetzungen aktivieren" 19 | "Activates translation of routes by module language routes","Erlaubt, einzelne Teile der URLs zu übersetzen" 20 | "Forward to translated route","Zu übersetzten URLs weiterleiten" 21 | "Forward the user to the translated rule when accessing old url","Den User zwingen, die übersetzte URL zu nutzen" -------------------------------------------------------------------------------- /app/locale/en_US/MKleine_LanguageRoutes.csv: -------------------------------------------------------------------------------- 1 | "Language Route","Language Route" 2 | "Language Routes","Language Routes" 3 | "Add Translation","Add Translation" 4 | "Save And Continue Edit","Save And Continue Edit" 5 | "Save Translation","Save Translation" 6 | "Delete Translation","Delete Translation" 7 | "Type","Type" 8 | "Value","Value" 9 | "Translation","Translation" 10 | "Is Active","Is Active" 11 | "Action","Action" 12 | "Route Part","Route Part" 13 | "Original Value","Original Value" 14 | "Translation does not exist","Translation does not exist" 15 | "Route","Route" 16 | "Controller","Controller" 17 | "Action","Action" 18 | "Enable route translation","Enable route translation" 19 | "Activates translation of routes by module language routes","Activates translation of routes by module language routes" 20 | "Forward to translated route","Forward to translated route" 21 | "Forward the user to the translated rule when accessing old url","Forward the user to the translated rule when accessing old url" -------------------------------------------------------------------------------- /app/locale/it_IT/MKleine_LanguageRoutes.csv: -------------------------------------------------------------------------------- 1 | "Language Route","Language Route" 2 | "Language Routes","Language Routes" 3 | "Add Translation","Aggiungi traduzione" 4 | "Save And Continue Edit","Salva e continua le modifiche" 5 | "Save Translation","Salva traduzione" 6 | "Delete Translation","Elimina traduzione" 7 | "Type","Tipo" 8 | "Value","Valore" 9 | "Translation","Traduzione" 10 | "Is Active","Attivata" 11 | "Action","Azione" 12 | "Route Part","Parte della URI" 13 | "Original Value","Valore originario" 14 | "Translation does not exist","La traduzione non esiste" 15 | "Route","URI" 16 | "Controller","Controller" 17 | "Action","Azione" 18 | "Enable route translation","Abilita le traduzione delle URI" 19 | "Activates translation of routes by module language routes","Abilita la traduzione delle URI con il modulo \"language routes\"" 20 | "Forward to translated route","Redirigi alla URI tradotta" 21 | "Forward the user to the translated rule when accessing old url","Redirigi l'utente alla URI tradotta se utilizza il vecchio URI non tradotto" 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mkleine/magento-language-routes", 3 | "type": "magento-module", 4 | "license": "MIT", 5 | "description": "Allows to translate the default magento routes into other languages", 6 | "homepage": "http://mkleine.de/projekte-und-referenzen/magento/", 7 | "repositories": [ 8 | { 9 | "type": "git", 10 | "url": "https://github.com/klein0r/magento-language-routes.git" 11 | } 12 | ], 13 | "keywords": [ 14 | "magento", 15 | "extension", 16 | "module" 17 | ], 18 | "authors":[ 19 | { 20 | "name": "Matthias Kleine", 21 | "email": "dev@mkleine.de", 22 | "homepage": "http://mkleine.de", 23 | "role": "Developer" 24 | } 25 | ], 26 | "require": { 27 | "php": ">=5.3.0" 28 | }, 29 | "suggest": { 30 | "magento-hackathon/magento-composer-installer": "*" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /modman: -------------------------------------------------------------------------------- 1 | app/code/community/MKleine/* app/code/community/MKleine/ 2 | app/etc/modules/* app/etc/modules/ 3 | app/design/adminhtml/default/default/layout/* app/design/adminhtml/default/default/layout/ 4 | app/design/frontend/base/default/template/mkleine/* app/design/frontend/base/default/template/mkleine/ 5 | app/locale/de_DE/* app/locale/de_DE/ 6 | app/locale/en_US/* app/locale/en_US/ -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | 16 | 17 | 18 | 19 | app/code/community/EcomDev/PHPUnit/Test/Suite.php 20 | 21 | 22 | 23 | 24 | app/code/core 25 | 26 | app/code/community/EcomDev/PHPUnit 27 | lib/EcomDev/Utils 28 | lib/EcomDev/PHPUnit 29 | lib/Spyc 30 | lib/vfsStream 31 | 32 | app/Mage.php 33 | 34 | app/design 35 | 36 | lib/Varien 37 | lib/Zend 38 | lib/Magento 39 | 40 | 41 | app/code/community/MKleine/LanguageRoutes 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /screenshots/Backend-Form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klein0r/magento-language-routes/f1e80da7bc105cf39f24556a8e2e93b68e8f2374/screenshots/Backend-Form.png -------------------------------------------------------------------------------- /screenshots/Backend-Grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klein0r/magento-language-routes/f1e80da7bc105cf39f24556a8e2e93b68e8f2374/screenshots/Backend-Grid.png -------------------------------------------------------------------------------- /screenshots/Inline-Translation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klein0r/magento-language-routes/f1e80da7bc105cf39f24556a8e2e93b68e8f2374/screenshots/Inline-Translation.png --------------------------------------------------------------------------------