Implementing translations (still in progress)

This commit is contained in:
Franck Allimant
2013-11-06 10:49:03 +01:00
parent 7ca625073d
commit 361e4a9d74
33 changed files with 890 additions and 169 deletions

View File

@@ -30,6 +30,7 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\KernelEvents;
use Thelia\Model\ConfigQuery; use Thelia\Model\ConfigQuery;
use Thelia\Core\Template\TemplateHelper;
/** /**
* *
@@ -55,7 +56,7 @@ class HttpException extends BaseAction implements EventSubscriberInterface
$parser = $this->container->get("thelia.parser"); $parser = $this->container->get("thelia.parser");
// Define the template thant shoud be used // Define the template thant shoud be used
$parser->setTemplate(ConfigQuery::getActiveTemplate()); $parser->setTemplate(TemplateHelper::getInstance()->getActiveFrontTemplate()->getPath());
//$event->getRequest()->attributes->set('_view', ConfigQuery::getPageNotFoundView()); //$event->getRequest()->attributes->set('_view', ConfigQuery::getPageNotFoundView());

View File

@@ -54,6 +54,8 @@ use Thelia\Core\Event\Product\ProductDeleteCategoryEvent;
use Thelia\Core\Event\Product\ProductAddCategoryEvent; use Thelia\Core\Event\Product\ProductAddCategoryEvent;
use Thelia\Core\Event\Product\ProductAddAccessoryEvent; use Thelia\Core\Event\Product\ProductAddAccessoryEvent;
use Thelia\Core\Event\Product\ProductDeleteAccessoryEvent; use Thelia\Core\Event\Product\ProductDeleteAccessoryEvent;
use Thelia\Model\Map\ProductTableMap;
use Propel\Runtime\Propel;
class Product extends BaseAction implements EventSubscriberInterface class Product extends BaseAction implements EventSubscriberInterface
{ {
@@ -257,21 +259,37 @@ class Product extends BaseAction implements EventSubscriberInterface
public function setProductTemplate(ProductSetTemplateEvent $event) public function setProductTemplate(ProductSetTemplateEvent $event)
{ {
$product = $event->getProduct();
// Delete all product feature relations $con = Propel::getWriteConnection(ProductTableMap::DATABASE_NAME);
FeatureProductQuery::create()->filterByProduct($product)->delete();
// Delete all product attributes sale elements $con->beginTransaction();
ProductSaleElementsQuery::create()->filterByProduct($product)->delete();
// Update the product template try {
$template_id = $event->getTemplateId();
// Set it to null if it's zero. $product = $event->getProduct();
if ($template_id <= 0) $template_id = NULL;
$product->setTemplateId($template_id)->save(); // Delete all product feature relations
FeatureProductQuery::create()->filterByProduct($product)->delete($con);
// Delete all product attributes sale elements
ProductSaleElementsQuery::create()->filterByProduct($product)->delete($con);
// Update the product template
$template_id = $event->getTemplateId();
// Set it to null if it's zero.
if ($template_id <= 0) $template_id = NULL;
$product->setTemplateId($template_id)->save($con);
// Store all the stuff !
$con->commit();
} catch (\Exception $ex) {
$con->rollback();
throw $ex;
}
} }
/** /**

View File

@@ -49,6 +49,7 @@
<loop class="Thelia\Core\Template\Loop\Message" name="message"/> <loop class="Thelia\Core\Template\Loop\Message" name="message"/>
<loop class="Thelia\Core\Template\Loop\Delivery" name="delivery"/> <loop class="Thelia\Core\Template\Loop\Delivery" name="delivery"/>
<loop class="Thelia\Core\Template\Loop\ProductTemplate" name="product-template"/> <!-- This is product templates ;-) --> <loop class="Thelia\Core\Template\Loop\ProductTemplate" name="product-template"/> <!-- This is product templates ;-) -->
<loop class="Thelia\Core\Template\Loop\Template" name="template"/>
<loop class="Thelia\Core\Template\Loop\Tax" name="tax"/> <loop class="Thelia\Core\Template\Loop\Tax" name="tax"/>
<loop class="Thelia\Core\Template\Loop\TaxRule" name="tax-rule"/> <loop class="Thelia\Core\Template\Loop\TaxRule" name="tax-rule"/>
<loop class="Thelia\Core\Template\Loop\TaxRuleCountry" name="tax-rule-country"/> <loop class="Thelia\Core\Template\Loop\TaxRuleCountry" name="tax-rule-country"/>

View File

@@ -1040,6 +1040,16 @@
<default key="_controller">Thelia\Controller\Admin\LangController::deactivateDomainAction</default> <default key="_controller">Thelia\Controller\Admin\LangController::deactivateDomainAction</default>
</route> </route>
<!-- translations management -->
<route id="admin.configuration.translations" path="/admin/configuration/translations">
<default key="_controller">Thelia\Controller\Admin\TranslationsController::defaultAction</default>
</route>
<route id="admin.configuration.translations.update" path="/admin/configuration/translations/update">
<default key="_controller">Thelia\Controller\Admin\TranslationsController::updateAction</default>
</route>
<!-- The default route, to display a template --> <!-- The default route, to display a template -->
<route id="admin.processTemplate" path="/admin/{template}"> <route id="admin.processTemplate" path="/admin/{template}">

View File

@@ -43,6 +43,7 @@ use Symfony\Component\Routing\Router;
use Thelia\Model\Admin; use Thelia\Model\Admin;
use Thelia\Core\Security\Token\CookieTokenProvider; use Thelia\Core\Security\Token\CookieTokenProvider;
use Thelia\Model\CurrencyQuery; use Thelia\Model\CurrencyQuery;
use Thelia\Core\Template\TemplateHelper;
class BaseAdminController extends BaseController class BaseAdminController extends BaseController
{ {
@@ -199,7 +200,7 @@ class BaseAdminController extends BaseController
$parser = $this->container->get("thelia.parser"); $parser = $this->container->get("thelia.parser");
// Define the template thant shoud be used // Define the template thant shoud be used
$parser->setTemplate($template ?: ConfigQuery::read('base-admin-template', 'admin/default')); $parser->setTemplate($template ?: TemplateHelper::getInstance()->getActiveAdminTemplate()->getPath());
return $parser; return $parser;
} }

View File

@@ -36,6 +36,7 @@ use Thelia\Model\Base\OrderAddressQuery;
use Thelia\Model\OrderQuery; use Thelia\Model\OrderQuery;
use Thelia\Model\OrderStatusQuery; use Thelia\Model\OrderStatusQuery;
use Thelia\Tools\URL; use Thelia\Tools\URL;
use Thelia\Core\Template\TemplateHelper;
/** /**
* Class OrderController * Class OrderController
@@ -218,7 +219,7 @@ class OrderController extends BaseAdminController
array( array(
'order_id' => $order_id 'order_id' => $order_id
), ),
ConfigQuery::read('pdf_template', 'pdf') TemplateHelper::getInstance()->getActivePdfTemplate()->getPath()
); );
$order = OrderQuery::create()->findPk($order_id); $order = OrderQuery::create()->findPk($order_id);

View File

@@ -66,6 +66,7 @@ use Thelia\Model\Product;
use Thelia\Model\CurrencyQuery; use Thelia\Model\CurrencyQuery;
use Thelia\Form\ProductCombinationGenerationForm; use Thelia\Form\ProductCombinationGenerationForm;
use Thelia\Core\Event\Product\ProductCombinationGenerationEvent; use Thelia\Core\Event\Product\ProductCombinationGenerationEvent;
use Thelia\Core\Event\Product\ProductSetTemplateEvent;
/** /**
* Manages products * Manages products

View File

@@ -0,0 +1,194 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program 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 3 of the License */
/* */
/* This program 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. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Controller\Admin;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Core\Security\AccessManager;
use Thelia\Form\SystemLogConfigurationForm;
use Thelia\Log\Tlog;
use Thelia\Model\ConfigQuery;
use Thelia\Model\ModuleQuery;
use Thelia\Core\Template\TemplateHelper;
use Thelia\Core\Template\TemplateDefinition;
/**
* Class LangController
* @package Thelia\Controller\Admin
* @author Manuel Raynaud <mraynaud@openstudio.fr>
*/
class TranslationsController extends BaseAdminController
{
protected function renderTemplate()
{
// Find modules
$modules = ModuleQuery::create()->joinI18n($this->getCurrentEditionLocale())->orderByPosition()->find();
TemplateHelper::getInstance()->getList(TemplateDefinition::BACK_OFFICE);
TemplateHelper::getInstance()->getList(TemplateDefinition::PDF);
TemplateHelper::getInstance()->getList(TemplateDefinition::FRONT_OFFICE);
// Get related strings, if all input data are here
$item_to_translate = $this->getRequest()->get('item_to_translate');
$item_id = $this->getRequest()->get('item_id', '');
$all_strings = $translated_strings = array();
$template = $directory = $i18n_directory = false;
if (! empty($item_id)) {
switch($item_to_translate) {
case 'mo' :
if (null !== $module = ModuleQuery::create()->findPk($item_id)) {
$directory = THELIA_MODULE_DIR . $module->getBaseDir();
$i18n_directory = THELIA_TEMPLATE_DIR . $template->getI18nPath();
}
break;
case 'fo' :
$template = new TemplateDefinition($item_id, TemplateDefinition::FRONT_OFFICE);
break;
case 'bo' :
$template = new TemplateDefinition($item_id, TemplateDefinition::BACK_OFFICE);
break;
case 'pf' :
$template = new TemplateDefinition($item_id, TemplateDefinition::PDF);
break;
}
if ($template) {
$directory = THELIA_TEMPLATE_DIR . $template->getPath();
$i18n_directory = THELIA_TEMPLATE_DIR . $template->getI18nPath();
}
if ($directory) {
// Load strings
$this->walkDir($directory, $all_strings);
// Load translated strings
if ($i18n_directory) {
$locale = $this->getCurrentEditionLocale();
}
}
}
return $this->render('translations', array(
'item_to_translate' => $item_to_translate,
'item_id' => $item_id,
'all_strings' => $all_strings,
'translated_strings' => $translated_strings,
'view_missing_traductions_only' => $this->getRequest()->get('view_missing_traductions_only', 0)
));
}
public function defaultAction()
{
if (null !== $response = $this->checkAuth(AdminResources::TRANSLATIONS, AccessManager::VIEW)) return $response;
return $this->renderTemplate();
}
public function updateAction()
{
if (null !== $response = $this->checkAuth(AdminResources::LANGUAGE, AccessManager::UPDATE)) return $response;
return $this->renderTemplate();
}
protected function normalize_path($path)
{
$path =
str_replace(
str_replace('\\', '/', THELIA_ROOT),
'',
str_replace('\\', '/', realpath($path))
);
if ($path[0] == '/') $path = substr($path, 1);
return $path;
}
protected function walkDir($directory, &$strings) {
try {
//echo "walking in $directory<br />";
foreach (new \DirectoryIterator($directory) as $fileInfo) {
if ($fileInfo->isDot()) continue;
if ($fileInfo->isDir()) $this->walkDir($fileInfo->getPathName(), $strings);
if ($fileInfo->isFile()) {
$ext = $fileInfo->getExtension();
if ($ext == 'html' || $ext == 'tpl' || $ext == 'xml') {
if ($content = file_get_contents($fileInfo->getPathName())) {
$short_path = $this->normalize_path($fileInfo->getPathName());
// echo " examining $short_path\n";
$matches = array();
if (preg_match_all('/{intl[\s]l=((?<![\\\\])[\'"])((?:.(?!(?<![\\\\])\1))*.?)\1/', $content, $matches)) {
// print_r($matches[2]);
foreach($matches[2] as $match) {
$hash = md5($match);
if (isset($strings[$hash]))
{
if (! in_array($short_path, $strings[$hash]['files']))
{
$strings[$hash]['files'][] = $short_path;
}
}
else
$strings[$hash] = array(
'files' => array($short_path),
'chaine' => $match,
'dollar' => strstr($match, '$') !== false);
}
}
}
}
}
}
} catch (\UnexpectedValueException $ex) {
echo $ex;
}
}
}

View File

@@ -67,26 +67,26 @@ class RegisterRouterPass implements CompilerPassInterface
$modules = \Thelia\Model\ModuleQuery::getActivated(); $modules = \Thelia\Model\ModuleQuery::getActivated();
foreach ($modules as $module) { foreach ($modules as $module) {
$moduleCode = ucfirst($module->getCode()); $moduleBaseDir = $module->getBaseDir();
if (file_exists(THELIA_MODULE_DIR . "/" . $moduleCode . "/Config/routing.xml")) { if (file_exists(THELIA_MODULE_DIR . "/" . $moduleBaseDir . "/Config/routing.xml")) {
$definition = new Definition( $definition = new Definition(
$container->getParameter("router.class"), $container->getParameter("router.class"),
array( array(
new Reference("router.module.xmlLoader"), new Reference("router.module.xmlLoader"),
ucfirst($module->getCode()) . "/Config/routing.xml", $moduleBaseDir . "/Config/routing.xml",
array( array(
"cache_dir" => $container->getParameter("kernel.cache_dir"), "cache_dir" => $container->getParameter("kernel.cache_dir"),
"debug" => $container->getParameter("kernel.debug"), "debug" => $container->getParameter("kernel.debug"),
"matcher_cache_class" => $container::camelize("ProjectUrlMatcher".$moduleCode), "matcher_cache_class" => $container::camelize("ProjectUrlMatcher".$moduleBaseDir),
"generator_cache_class" => $container::camelize("ProjectUrlGenerator".$moduleCode), "generator_cache_class" => $container::camelize("ProjectUrlGenerator".$moduleBaseDir),
), ),
new Reference("request.context") new Reference("request.context")
) )
); );
$container->setDefinition("router.".$moduleCode, $definition); $container->setDefinition("router.".$moduleBaseDir, $definition);
$chainRouter->addMethodCall("add", array(new Reference("router.".$moduleCode), 150)); $chainRouter->addMethodCall("add", array(new Reference("router.".$moduleBaseDir), 150));
} }
} }
} }

View File

@@ -99,4 +99,6 @@ final class AdminResources
const TEMPLATE = "admin.configuration.template"; const TEMPLATE = "admin.configuration.template";
const SYSTEM_LOG = "admin.configuration.system-log"; const SYSTEM_LOG = "admin.configuration.system-log";
const TRANSLATIONS = "admin.configuration.translations";
} }

View File

@@ -24,6 +24,7 @@
namespace Thelia\Core\Template\Loop; namespace Thelia\Core\Template\Loop;
use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\Criteria;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Template\Element\BaseI18nLoop; use Thelia\Core\Template\Element\BaseI18nLoop;
use Thelia\Core\Template\Element\LoopResult; use Thelia\Core\Template\Element\LoopResult;
use Thelia\Core\Template\Element\LoopResultRow; use Thelia\Core\Template\Element\LoopResultRow;
@@ -31,29 +32,39 @@ use Thelia\Core\Template\Element\LoopResultRow;
use Thelia\Core\Template\Loop\Argument\ArgumentCollection; use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
use Thelia\Core\Template\Loop\Argument\Argument; use Thelia\Core\Template\Loop\Argument\Argument;
use Thelia\Model\Base\TemplateQuery; use Thelia\Model\ModuleQuery;
use Thelia\Module\BaseModule;
use Thelia\Type;
use Thelia\Core\Template\TemplateHelper;
use Thelia\Core\Template\TemplateDefinition;
/** /**
* *
* Template loop * Template loop, to get available back-office or front-office templates.
* *
*
* Class Template
* @package Thelia\Core\Template\Loop * @package Thelia\Core\Template\Loop
* @author Etienne Roudeix <eroudeix@openstudio.fr> *
* @author Franck Allimant <franck@cqfdev.fr>
*/ */
class Template extends BaseI18nLoop class Template extends BaseI18nLoop
{ {
public $timestampable = true;
/** /**
* @return ArgumentCollection * @return ArgumentCollection
*/ */
protected function getArgDefinitions() protected function getArgDefinitions()
{ {
return new ArgumentCollection( return new ArgumentCollection(
Argument::createIntListTypeArgument('id'), new Argument(
Argument::createIntListTypeArgument('exclude') 'template_type',
new Type\TypeCollection(
new Type\EnumListType(array(
'front-office',
'back-office',
'pdf'
))
)
)
); );
} }
@@ -64,40 +75,27 @@ class Template extends BaseI18nLoop
*/ */
public function exec(&$pagination) public function exec(&$pagination)
{ {
$search = TemplateQuery::create(); $type = $this->getArg(template_type);
$backendContext = $this->getBackend_context(); if ($type == 'front-office')
$templateType = TemplateDefinition::FRONT_OFFICE;
else if ($type == 'back-office')
$templateType = TemplateDefinition::BACK_OFFICE;
else if ($type == 'pdf')
$templateType = TemplateDefinition::PDF;
$lang = $this->getLang(); $templates = TemplateHelper::getInstance()->getList($templateType);
/* manage translations */ $loopResult = new LoopResult();
$locale = $this->configureI18nProcessing($search, $columns = array('NAME'));
$id = $this->getId();
if (null !== $id) {
$search->filterById($id, Criteria::IN);
}
$exclude = $this->getExclude();
if (null !== $exclude) {
$search->filterById($exclude, Criteria::NOT_IN);
}
/* perform search */
$templates = $this->search($search, $pagination);
$loopResult = new LoopResult($templates);
foreach ($templates as $template) { foreach ($templates as $template) {
$loopResultRow = new LoopResultRow($loopResult, $template, $this->versionable, $this->timestampable, $this->countable);
$loopResultRow = new LoopResultRow($loopResult);
$loopResultRow $loopResultRow
->set("ID", $template->getId()) ->set("NAME" , $template->getName())
->set("IS_TRANSLATED" , $template->getVirtualColumn('IS_TRANSLATED')) ->set("RELATIVE_PATH" , $template->getPath())
->set("LOCALE" , $locale) ->set("ABSOLUTE_PATH" , THELIA_TEMPLATE_DIR . $template->getPath())
->set("NAME" , $template->getVirtualColumn('i18n_NAME'))
; ;
$loopResult->addRow($loopResultRow); $loopResult->addRow($loopResultRow);
@@ -105,4 +103,4 @@ class Template extends BaseI18nLoop
return $loopResult; return $loopResult;
} }
} }

View File

@@ -29,6 +29,7 @@ use Thelia\Tools\URL;
use Thelia\Core\Security\SecurityContext; use Thelia\Core\Security\SecurityContext;
use Thelia\Model\Config; use Thelia\Model\Config;
use Thelia\Model\ConfigQuery; use Thelia\Model\ConfigQuery;
use Thelia\Core\Template\TemplateHelper;
/** /**
* This class implements variour admin template utilities * This class implements variour admin template utilities
@@ -50,7 +51,7 @@ class AdminUtilities extends AbstractSmartyPlugin
$snippet_path = sprintf('%s/%s/%s.html', $snippet_path = sprintf('%s/%s/%s.html',
THELIA_TEMPLATE_DIR, THELIA_TEMPLATE_DIR,
ConfigQuery::read('base-admin-template', 'admin/default'), TemplateHelper::getInstance()->getActiveAdminTemplate()->getPath(),
$templateName $templateName
); );

View File

@@ -48,7 +48,7 @@ class Module extends AbstractSmartyPlugin
foreach ($modules as $module) { foreach ($modules as $module) {
$file = sprintf("%s/%s/AdminIncludes/%s.html", THELIA_MODULE_DIR, ucfirst($module->getCode()), $location); $file = sprintf("%s/%s/AdminIncludes/%s.html", THELIA_MODULE_DIR, $module->getBaseDir(), $location);
if (file_exists($file)) { if (file_exists($file)) {
$content .= file_get_contents($file); $content .= file_get_contents($file);

View File

@@ -14,6 +14,7 @@ use Thelia\Core\Template\Smarty\AbstractSmartyPlugin;
use Thelia\Core\Template\Exception\ResourceNotFoundException; use Thelia\Core\Template\Exception\ResourceNotFoundException;
use Thelia\Core\Template\ParserContext; use Thelia\Core\Template\ParserContext;
use Thelia\Model\ConfigQuery; use Thelia\Model\ConfigQuery;
use Thelia\Core\Template\TemplateHelper;
/** /**
* *
@@ -62,7 +63,7 @@ class SmartyParser extends Smarty implements ParserInterface
$this->setCompileDir($compile_dir); $this->setCompileDir($compile_dir);
$this->setCacheDir($cache_dir); $this->setCacheDir($cache_dir);
$this->setTemplate($template ?: ConfigQuery::read('active-template', 'default')); $this->setTemplate($template ?: TemplateHelper::getInstance()->getActiveFrontTemplate()->getPath());
$this->debugging = $debug; $this->debugging = $debug;

View File

@@ -0,0 +1,102 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program 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 3 of the License */
/* */
/* This program 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. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Core\Template;
use Thelia\Model\ConfigQuery;
class TemplateDefinition
{
const FRONT_OFFICE = 1;
const BACK_OFFICE = 2;
const PDF = 3;
const BACK_OFFICE_SUBDIR = 'admin/';
const PDF_SUBDIR = 'pdf/';
/**
* @var the template directory name (e.g. 'default')
*/
protected $name;
/**
* @var the template directory full path
*/
protected $path;
/**
* @var the template type (front, back, pdf)
*/
protected $type;
public function __construct($name, $type)
{
$this->name = $name;
$this->type = $type;
if ($type == self::BACK_OFFICE)
$this->path = self::BACK_OFFICE_SUBDIR . $name;
else if ($type == self::PDF)
$this->path = self::PDF_SUBDIR . $name;
else
$this->path = $name;
}
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getI18nPath() {
return $this->getPath() . DS . 'I18n';
}
public function getPath()
{
return $this->path;
}
public function setPath($path)
{
$this->path = $path;
return $this;
}
public function getType()
{
return $this->type;
}
public function setType($type)
{
$this->type = $type;
return $this;
}
}

View File

@@ -0,0 +1,96 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program 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 3 of the License */
/* */
/* This program 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. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Core\Template;
use Thelia\Model\ConfigQuery;
class TemplateHelper
{
/**
* This is a singleton
*/
private static $instance = null;
private function __construct() {}
public static function getInstance() {
if (self::$instance == null) self::$instance = new TemplateHelper();
return self::$instance;
}
public function getActivePdfTemplate() {
return new TemplateDefinition(
ConfigQuery::read('active-pdf-template', 'default'),
TemplateDefinition::PDF
);
}
public function getActiveAdminTemplate() {
return new TemplateDefinition(
ConfigQuery::read('active-admin-template', 'default'),
TemplateDefinition::BACK_OFFICE
);
}
public function getActiveFrontTemplate() {
return new TemplateDefinition(
ConfigQuery::read('active-admin-template', 'default'),
TemplateDefinition::FRONT_OFFICE
);
}
public function getList($templateType) {
$list = $exclude = array();
if ($templateType == TemplateDefinition::BACK_OFFICE) {
$baseDir = THELIA_TEMPLATE_DIR.TemplateDefinition::BACK_OFFICE_SUBDIR;
}
else if ($templateType == TemplateDefinition::PDF) {
$baseDir = THELIA_TEMPLATE_DIR.TemplateDefinition::PDF_SUBDIR;
}
else {
$baseDir = THELIA_TEMPLATE_DIR;
$exclude = array(TemplateDefinition::BACK_OFFICE_SUBDIR, TemplateDefinition::PDF_SUBDIR);
}
// Every subdir of the basedir is supposed to be a template.
$di = new \DirectoryIterator($baseDir);
foreach ($di as $file) {
// Ignore 'dot' elements
if ($file->isDot() || ! $file->isDir()) continue;
// Ignore reserved directory names
if (in_array($file->getFilename()."/", $exclude)) continue;
$list[] = new TemplateDefinition($file->getFilename(), $templateType);
}
return $list;
}
}

View File

@@ -52,6 +52,7 @@ use Symfony\Component\Config\FileLocator;
use Propel\Runtime\Propel; use Propel\Runtime\Propel;
use Propel\Runtime\Connection\ConnectionManagerSingle; use Propel\Runtime\Connection\ConnectionManagerSingle;
use Thelia\Core\Template\TemplateHelper;
class Thelia extends Kernel class Thelia extends Kernel
{ {
@@ -138,10 +139,10 @@ class Thelia extends Kernel
$defintion $defintion
); );
$loader = new XmlFileLoader($container, new FileLocator(THELIA_MODULE_DIR . "/" . ucfirst($module->getCode()) . "/Config")); $loader = new XmlFileLoader($container, new FileLocator(THELIA_MODULE_DIR . $module->getConfigPath()));
$loader->load("config.xml"); $loader->load("config.xml");
if (is_dir($dir = THELIA_MODULE_DIR . "/" . ucfirst($module->getCode()) . "/I18n")) { if (is_dir($dir = THELIA_MODULE_DIR . $module->getI18nPath())) {
$dirs[] = $dir; $dirs[] = $dir;
} }
} catch (\InvalidArgumentException $e) { } catch (\InvalidArgumentException $e) {
@@ -149,18 +150,22 @@ class Thelia extends Kernel
} }
} }
//Load translation from templates // Load translation from templates
//core translation //core translation
$dirs[] = THELIA_ROOT . "/core/lib/Thelia/Config/I18n"; $dirs[] = THELIA_ROOT . "core/lib/Thelia/Config/I18n";
//admin template // admin template
if(is_dir($dir = THELIA_TEMPLATE_DIR . '/admin/default/I18n')) { if (is_dir($dir = THELIA_TEMPLATE_DIR . TemplateHelper::getInstance()->getActiveAdminTemplate()->getI18nPath())) {
$dirs[] = $dir; $dirs[] = $dir;
} }
//front template // front template
$template = ConfigQuery::getActiveTemplate(); if (is_dir($dir = THELIA_TEMPLATE_DIR . TemplateHelper::getInstance()->getActiveFrontTemplate()->getI18nPath())) {
if(is_dir($dir = THELIA_TEMPLATE_DIR . $template . "/I18n")) { $dirs[] = $dir;
}
// PDF template
if (is_dir($dir = THELIA_TEMPLATE_DIR . TemplateHelper::getInstance()->getActivePdfTemplate()->getI18nPath())) {
$dirs[] = $dir; $dirs[] = $dir;
} }

View File

@@ -82,12 +82,6 @@ class ConfigQuery extends BaseConfigQuery {
return self::read('passed_url_view', 'passed-url'); return self::read('passed_url_view', 'passed-url');
} }
public static function getActiveTemplate()
{
return self::read('active-template', 'default');
}
public static function useTaxFreeAmounts() public static function useTaxFreeAmounts()
{ {
return self::read('use_tax_free_amounts', 'default') == 1; return self::read('use_tax_free_amounts', 'default') == 1;

View File

@@ -166,7 +166,7 @@ class ConfigTableMap extends TableMap
// columns // columns
$this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null); $this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null);
$this->addColumn('NAME', 'Name', 'VARCHAR', true, 255, null); $this->addColumn('NAME', 'Name', 'VARCHAR', true, 255, null);
$this->addColumn('VALUE', 'Value', 'VARCHAR', true, 255, null); $this->addColumn('VALUE', 'Value', 'LONGVARCHAR', true, null, null);
$this->addColumn('SECURED', 'Secured', 'TINYINT', true, null, 1); $this->addColumn('SECURED', 'Secured', 'TINYINT', true, null, 1);
$this->addColumn('HIDDEN', 'Hidden', 'TINYINT', true, null, 1); $this->addColumn('HIDDEN', 'Hidden', 'TINYINT', true, null, 1);
$this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null); $this->addColumn('CREATED_AT', 'CreatedAt', 'TIMESTAMP', false, null, null);

View File

@@ -11,4 +11,25 @@ class Module extends BaseModule {
{ {
ModuleQuery::resetActivated(); ModuleQuery::resetActivated();
} }
/**
* @return the module's base directory path, relative to THELIA_MODULE_DIR
*/
public function getBaseDir() {
return ucfirst($this->getCode());
}
/**
* @return the module's config directory path, relative to THELIA_MODULE_DIR
*/
public function getConfigPath() {
return $this->getBaseDir() . DS . "Config";
}
/**
* @return the module's i18N directory path, relative to THELIA_MODULE_DIR
*/
public function getI18nPath() {
return $this->getBaseDir() . DS . "I18n";
}
} }

View File

@@ -8,7 +8,8 @@ INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updat
('session_config.default', '1', 1, 1, NOW(), NOW()), ('session_config.default', '1', 1, 1, NOW(), NOW()),
('verifyStock', '1', 0, 0, NOW(), NOW()), ('verifyStock', '1', 0, 0, NOW(), NOW()),
('active-template', 'default', 0, 0, NOW(), NOW()), ('active-template', 'default', 0, 0, NOW(), NOW()),
('base-admin-template', 'admin/default', 0, 0, NOW(), NOW()), ('active-admin-template', 'default', 0, 0, NOW(), NOW()),
('active-pdf-template', 'default', 0, 0, NOW(), NOW()),
('default_lang_without_translation', '1', 1, 1, NOW(), NOW()), ('default_lang_without_translation', '1', 1, 1, NOW(), NOW()),
('rewriting_enable', '0', 0, 0, NOW(), NOW()), ('rewriting_enable', '0', 0, 0, NOW(), NOW()),
('imagine_graphic_driver', 'gd', 0, 0, NOW(), NOW()), ('imagine_graphic_driver', 'gd', 0, 0, NOW(), NOW()),
@@ -33,6 +34,8 @@ INSERT INTO `config` (`name`, `value`, `secured`, `hidden`, `created_at`, `updat
('contact_email','', 0, 0, NOW(), NOW()), ('contact_email','', 0, 0, NOW(), NOW()),
('url_site','', 0, 0, NOW(), NOW()), ('url_site','', 0, 0, NOW(), NOW()),
('one_domain_foreach_lang','0', 1, 1, NOW(), NOW()), ('one_domain_foreach_lang','0', 1, 1, NOW(), NOW()),
('pdf_invoice_file', 'invoice', 0, 0, NOW(), NOW()),
('pdf_delivery_file', 'delivery', 0, 0, NOW(), NOW()),
('thelia_version','2.0.0-beta1', 1, 1, NOW(), NOW()), ('thelia_version','2.0.0-beta1', 1, 1, NOW(), NOW()),
('thelia_major_version','2', 1, 1, NOW(), NOW()), ('thelia_major_version','2', 1, 1, NOW(), NOW()),
('thelia_minus_version','0', 1, 1, NOW(), NOW()), ('thelia_minus_version','0', 1, 1, NOW(), NOW()),
@@ -1207,7 +1210,7 @@ generated with command : php Thelia thelia:generate-resources --output sql
*/ */
INSERT INTO resource (`id`, `code`, `created_at`, `updated_at`) VALUES INSERT INTO resource (`id`, `code`, `created_at`, `updated_at`) VALUES
(1, 'admin.address', NOW(), NOW()), (1, 'admin.address', NOW(), NOW()),
(2, 'admin.configuration.admin', NOW(), NOW()), (2, 'admin.configuration.administrator', NOW(), NOW()),
(3, 'admin.configuration.area', NOW(), NOW()), (3, 'admin.configuration.area', NOW(), NOW()),
(4, 'admin.configuration.attribute', NOW(), NOW()), (4, 'admin.configuration.attribute', NOW(), NOW()),
(5, 'admin.category', NOW(), NOW()), (5, 'admin.category', NOW(), NOW()),
@@ -1228,7 +1231,8 @@ INSERT INTO resource (`id`, `code`, `created_at`, `updated_at`) VALUES
(20, 'admin.configuration.profile', NOW(), NOW()), (20, 'admin.configuration.profile', NOW(), NOW()),
(21, 'admin.configuration.shipping-zone', NOW(), NOW()), (21, 'admin.configuration.shipping-zone', NOW(), NOW()),
(22, 'admin.configuration.tax', NOW(), NOW()), (22, 'admin.configuration.tax', NOW(), NOW()),
(23, 'admin.configuration.template', NOW(), NOW()); (23, 'admin.configuration.template', NOW(), NOW()),
(24, 'admin.configuration.system-log', NOW(), NOW());
/** /**
generated with command : php Thelia thelia:generate-resources --output sql-i18n generated with command : php Thelia thelia:generate-resources --output sql-i18n
@@ -1236,8 +1240,8 @@ generated with command : php Thelia thelia:generate-resources --output sql-i18n
INSERT INTO resource_i18n (`id`, `locale`, `title`) VALUES INSERT INTO resource_i18n (`id`, `locale`, `title`) VALUES
(1, 'en_US', 'Address'), (1, 'en_US', 'Address'),
(1, 'fr_FR', 'Address'), (1, 'fr_FR', 'Address'),
(2, 'en_US', 'Configuration / Admin'), (2, 'en_US', 'Configuration / Administrator'),
(2, 'fr_FR', 'Configuration / Admin'), (2, 'fr_FR', 'Configuration / Administrator'),
(3, 'en_US', 'Configuration / Area'), (3, 'en_US', 'Configuration / Area'),
(3, 'fr_FR', 'Configuration / Area'), (3, 'fr_FR', 'Configuration / Area'),
(4, 'en_US', 'Configuration / Attribute'), (4, 'en_US', 'Configuration / Attribute'),
@@ -1279,7 +1283,9 @@ INSERT INTO resource_i18n (`id`, `locale`, `title`) VALUES
(22, 'en_US', 'Configuration / Tax'), (22, 'en_US', 'Configuration / Tax'),
(22, 'fr_FR', 'Configuration / Tax'), (22, 'fr_FR', 'Configuration / Tax'),
(23, 'en_US', 'Configuration / Template'), (23, 'en_US', 'Configuration / Template'),
(23, 'fr_FR', 'Configuration / Template'); (23, 'fr_FR', 'Configuration / Template'),
(24, 'en_US', 'Configuration / System Log'),
(24, 'fr_FR', 'Configuration / Logs système');
INSERT INTO `message` (`id`, `name`, `secured`, `created_at`, `updated_at`, `version`, `version_created_at`, `version_created_by`) VALUES INSERT INTO `message` (`id`, `name`, `secured`, `created_at`, `updated_at`, `version`, `version_created_at`, `version_created_by`) VALUES

View File

@@ -416,7 +416,7 @@ CREATE TABLE `config`
( (
`id` INTEGER NOT NULL AUTO_INCREMENT, `id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL, `name` VARCHAR(255) NOT NULL,
`value` VARCHAR(255) NOT NULL, `value` TEXT NOT NULL,
`secured` TINYINT DEFAULT 1 NOT NULL, `secured` TINYINT DEFAULT 1 NOT NULL,
`hidden` TINYINT DEFAULT 1 NOT NULL, `hidden` TINYINT DEFAULT 1 NOT NULL,
`created_at` DATETIME, `created_at` DATETIME,

View File

@@ -26,98 +26,106 @@
<div class="row inner-toolbar"> <div class="row inner-toolbar">
<div class="col-md-12 inner-actions clearfix"> <div class="col-md-12 inner-actions clearfix">
<button type="button" class="btn btn-default btn-success pull-right js-show-logs" title="{intl l='Show logs'}">{intl l='Show logs'} <span class="glyphicon glyphicon-eye-open"></span></button> <button type="button" class="btn btn-default btn-success pull-right js-show-logs" title="{intl l='Show \'logs'}">{intl l='Show logs'} <span class="glyphicon glyphicon-eye-open"></span></button>
</div> </div>
</div> </div>
<div class="col-md-12 clearfix"> <div class="row">
<div> <div class="col-md-12">
<strong>{intl l='Period'} :</strong> <div>
</div> <strong>{intl l='Period'} :</strong>
</div>
<div class="row"> <div class="row">
<div class="col-lg-3 clearfix"> <div class="col-lg-3 clearfix">
<div class="input-group"> <div class="input-group">
<span class="input-group-addon">{intl l='From'}</span> <span class="input-group-addon">{intl l='From'}</span>
<input class="form-control" type="text" id="from_date" readonly="readonly"> <input class="form-control" type="text" id="from_date" readonly="readonly">
<span class="input-group-btn"> <span class="input-group-btn">
<button class="btn btn-default js-show-datepicker" data-datepicker-selector="#from_date" type="button"> <button class="btn btn-default js-show-datepicker" data-datepicker-selector="#from_date" type="button">
<span class="glyphicon glyphicon-calendar"></span> <span class="glyphicon glyphicon-calendar"></span>
</button> </button>
</span> </span>
</div> </div>
</div> </div>
<div class="col-lg-3 clearfix input-group"> <div class="col-lg-3 clearfix input-group">
<div class="input-group"> <div class="input-group">
<span class="input-group-addon">{intl l='To'}</span> <span class="input-group-addon">{intl l='To'}</span>
<input class="form-control" type="text" id="to_date" readonly="readonly"> <input class="form-control" type="text" id="to_date" readonly="readonly">
<span class="input-group-btn"> <span class="input-group-btn">
<button class="btn btn-default js-show-datepicker" data-datepicker-selector="#to_date" type="button"> <button class="btn btn-default js-show-datepicker" data-datepicker-selector="#to_date" type="button">
<span class="glyphicon glyphicon-calendar"></span> <span class="glyphicon glyphicon-calendar"></span>
</button> </button>
</span> </span>
</div> </div>
</div> </div>
</div> </div>
</div>
</div> </div>
<div class="col-md-12 clearfix"> <div class="row">
<div> <div class="col-md-12">
<strong>{intl l='Administrators'} :</strong> <div>
</div> <strong>{intl l='Administrators'} :</strong>
</div>
<div class="row"> <div class="row">
{loop type="admin" name="admin-list" backend_context="1"} {loop type="admin" name="admin-list" backend_context="1"}
{if ($LOOP_COUNT-1)%4 == 0 AND $LOOP_COUNT != 0 AND $LOOP_COUNT != $LOOP_TOTAL} {if ($LOOP_COUNT-1)%4 == 0 AND $LOOP_COUNT != 0 AND $LOOP_COUNT != $LOOP_TOTAL}
</div> </div>
<div class="row"> <div class="row">
{/if} {/if}
<div class="col-md-3"> <div class="col-md-3">
<input id="admin_{$ID}" data-id="{$LOGIN}" class="js-admin" type="checkbox" checked> <input id="admin_{$ID}" data-id="{$LOGIN}" class="js-admin" type="checkbox" checked>
<label for="admin_{$ID}" style="font-weight: normal;">{$LOGIN} ({$FIRSTNAME|upper} {$LASTNAME|ucwords})</label> <label for="admin_{$ID}" style="font-weight: normal;">{$LOGIN} ({$FIRSTNAME|upper} {$LASTNAME|ucwords})</label>
</div> </div>
{/loop} {/loop}
</div> </div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div>
<strong>{intl l='Resources'} :</strong>
</div>
<div class="row">
{loop type="resource" name="resources-list" backend_context="1"}
{if ($LOOP_COUNT-1)%4 == 0 AND $LOOP_COUNT != 0 AND $LOOP_COUNT != $LOOP_TOTAL}
</div>
<div class="row">
{/if}
<div class="col-md-3">
<input id="resource_{$ID}" data-id="{$CODE}" class="js-resource" type="checkbox" checked>
<label for="resource_{$ID}" style="font-weight: normal;">{$TITLE}</label>
</div>
{/loop}
</div>
</div>
</div> </div>
<div class="col-md-12 clearfix"> <div class="row">
<div> <div class="col-md-12">
<strong>{intl l='Resources'} :</strong> <div>
</div> <strong>{intl l='Modules'} :</strong>
</div>
<div class="row"> <div class="row">
{loop type="resource" name="resources-list" backend_context="1"} {loop type="module" name="modules-list" backend_context="1"}
{if ($LOOP_COUNT-1)%4 == 0 AND $LOOP_COUNT != 0 AND $LOOP_COUNT != $LOOP_TOTAL} {if ($LOOP_COUNT-1)%4 == 0 AND $LOOP_COUNT != 0 AND $LOOP_COUNT != $LOOP_TOTAL}
</div> </div>
<div class="row"> <div class="row">
{/if} {/if}
<div class="col-md-3"> <div class="col-md-3">
<input id="resource_{$ID}" data-id="{$CODE}" class="js-resource" type="checkbox" checked> <input id="module_{$ID}" data-id="{$CODE}" class="js-module" type="checkbox" checked>
<label for="resource_{$ID}" style="font-weight: normal;">{$TITLE}</label> <label for="module_{$ID}" style="font-weight: normal;">{$TITLE}</label>
</div> </div>
{/loop} {/loop}
</div> </div>
</div>
<div class="col-md-12 clearfix">
<div>
<strong>{intl l='Modules'} :</strong>
</div>
<div class="row">
{loop type="module" name="modules-list" backend_context="1"}
{if ($LOOP_COUNT-1)%4 == 0 AND $LOOP_COUNT != 0 AND $LOOP_COUNT != $LOOP_TOTAL}
</div>
<div class="row">
{/if}
<div class="col-md-3">
<input id="module_{$ID}" data-id="{$CODE}" class="js-module" type="checkbox" checked>
<label for="module_{$ID}" style="font-weight: normal;">{$TITLE}</label>
</div>
{/loop}
</div>
</div>
</div> </div>
<div class="row inner-toolbar"> <div class="row inner-toolbar">
@@ -129,7 +137,6 @@
<div id="loading-block" class="col-md-12 loading-block"></div> <div id="loading-block" class="col-md-12 loading-block"></div>
<div class="col-md-12 clearfix" id="logger-display"></div> <div class="col-md-12 clearfix" id="logger-display"></div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -151,6 +151,13 @@
</tr> </tr>
{/loop} {/loop}
{loop type="auth" name="pcc5.1" role="ADMIN" resource="admin.configuration.translations" access="VIEW"}
<tr>
<td><a href="{url path='/admin/configuration/translations'}">{intl l='Translations'}</a></td>
<td><a class="btn btn-default btn-xs" href="{url path='/admin/configuration/translations'}"><i class="glyphicon glyphicon-edit"></i></a></td>
</tr>
{/loop}
{loop type="auth" name="pcc6" role="ADMIN" resource="admin.configuration.mailing-system" access="VIEW"} {loop type="auth" name="pcc6" role="ADMIN" resource="admin.configuration.mailing-system" access="VIEW"}
<tr> <tr>
<td><a href="{url path='/admin/configuration/mailingSystem'}">{intl l='Mailing system'}</a></td> <td><a href="{url path='/admin/configuration/mailingSystem'}">{intl l='Mailing system'}</a></td>

View File

@@ -23,7 +23,7 @@
<div class="row"> <div class="row">
<div class="col-md-12 title title-without-tabs"> <div class="col-md-12 title title-without-tabs">
{intl l="Edit customer $FIRSTNAME $LASTNAME"} {intl l="Edit customer %firstname %lastname" firstname=$FIRSTNAME lastname=$LASTNAME}
</div> </div>
<div class="form-container"> <div class="form-container">
@@ -143,7 +143,7 @@
</a> </a>
</span> </span>
</p> </p>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-bordered table-striped"> <table class="table table-bordered table-striped">
<thead> <thead>

View File

@@ -0,0 +1,238 @@
{extends file="admin-layout.tpl"}
{block name="page-title"}{intl l='Translations'}{/block}
{block name="check-resource"}admin.configuration.variable{/block}
{block name="check-access"}update{/block}
{block name="main-content"}
<div class="variables translations">
<div id="wrapper" class="container">
<ul class="breadcrumb">
<li><a href="{url path='/admin/home'}">{intl l="Home"}</a></li>
<li><a href="{url path='/admin/configuration'}">{intl l="Configuration"}</a></li>
<li><a href="{url path='/admin/configuration/translations'}">{intl l="Translations"}</a></li>
</ul>
<div class="row">
<div class="col-md-12 general-block-decorator">
<div class="row">
<div class="col-md-12 title title-without-tabs">
{intl l="Translation"}
</div>
<div class="form-container">
<div class="col-md-12">
<form method="POST" id="translation_form" action="{url path='/admin/configuration/translations/update'}">
<fieldset>
{include
file = "includes/inner-form-toolbar.html"
close_url = {url path='/admin/configuration'}
}
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label class="control-label" for="item_to_translate">{intl l='Select which items you want to translate'}</label>
<select id="item_to_translate" required="required" name="item_to_translate" class="submit-on-change form-control">
<option value="">{intl l='Please select items to translate'}</option>
<option value="fo" {if $item_to_translate=='fo'}selected="selected"{/if}>{intl l='Front-office templates'}</option>
<option value="pf" {if $item_to_translate=='pf'}selected="selected"{/if}>{intl l='PDF templates'}</option>
<option value="bo" {if $item_to_translate=='bo'}selected="selected"{/if}>{intl l='Back-office templates'}</option>
<option value="mo" {if $item_to_translate=='mo'}selected="selected"{/if}>{intl l='Modules'}</option>
<option value="co" {if $item_to_translate=='co'}selected="selected"{/if}>{intl l='Thelia core'}</option>
</select>
</div>
</div>
{if $item_to_translate == 'mo'}
<div class="col-md-4">
<div class="form-group">
<label class="control-label" for="item_id">{intl l='Select the module you want to translate'}</label>
<select id="item_id" required="required" name="item_id" class="submit-on-change form-control">
<option value="">{intl l='Please select the module to translate'}</option>
{loop type="module" name="translate-module" backend_context=1}
<option value="{$ID}" {if $item_id == $ID}selected="selected"{/if}>{$TITLE}</option>
{/loop}
</select>
</div>
</div>
{else if $item_to_translate == 'fo'}
<div class="col-md-4">
<div class="form-group">
<label class="control-label" for="item_id">{intl l='Select the front-office template you want to translate'}</label>
<select id="item_id" required="required" name="item_id" class="submit-on-change form-control">
<option value="">{intl l='Please select the F.O. template to translate'}</option>
{loop type="template" name="translate-fo-template" template-type="front-office" backend_context=1}
<option value="{$NAME}" {if $item_id == $NAME}selected="selected"{/if}>{$NAME}</option>
{/loop}
</select>
</div>
</div>
{else if $item_to_translate == 'bo'}
<div class="col-md-4">
<div class="form-group">
<label class="control-label" for="item_id">{intl l='Select the back-office template you want to translate'}</label>
<select id="item_id" required="required" name="item_id" class="submit-on-change form-control">
<option value="">{intl l='Please select the B.O. template to translate'}</option>
{loop type="template" name="translate-fo-template" template-type="back-office" backend_context=1}
<option value="{$NAME}" {if $item_id == $NAME}selected="selected"{/if}>{$NAME}</option>
{/loop}
</select>
</div>
</div>
{else if $item_to_translate == 'pf'}
<div class="col-md-4">
<div class="form-group">
<label class="control-label" for="item_id">{intl l='Select the PDF template you want to translate'}</label>
<select id="pdf_template" required="required" name="item_id" class="submit-on-change form-control">
<option value="">{intl l='Please select the PDF template to translate'}</option>
{loop type="template" name="translate-pdf-template" template-type="pdf" backend_context=1}
<option value="{$NAME}" {if $item_id == $NAME}selected="selected"{/if}>{$NAME}</option>
{/loop}
</select>
</div>
</div>
{/if}
<div class="col-md-4">
<div class="form-group">
<label class="control-label">&nbsp;</label>
<label class="checkbox control-label">
<input type="checkbox" name="view_missing_traductions_only" value="1" {if $view_missing_traductions_only}checked="checked"{/if}> {intl l='View only missing translations'}
</label>
</div>
</div>
</div>
</fieldset>
{* -- STRINGS TO TRANSLATE --------------------------------------------- *}
{$currfile = false}
{$untranslated = 0}
{foreach $all_strings as $hash => $info}
{if $view_missing_traductions_only != 1 || ! isset($translated_strings[$info.chaine]) || $translated_strings[$info.chaine]== ''}
{* Create a liste of files names *}
{if count($info.files) > 1}
{$label = {intl l='In pages:'}}
{capture name="banner" assign=file_names}
<ul>
{foreach $info.files as $file}
<li>{$file}</li>
{/foreach}
</ul>
{/capture}
{else}
{$label = {intl l='In page'}}
{$file_names = $info.files.0}
{/if}
{* Display current file liste, if required *}
{if $file_names != $currfile}
{if $currfile !== false}
{* Close current panel *}
</tbody></table>
</div>
{/if}
{$currfile = $file_names}
<div class="panel panel-default">
<div class="panel-heading">
{loop name="lang_list" type="lang" id=$edit_language_id}
<img src="{image file="assets/img/flags/{$CODE}.gif"}" alt="{intl l=$TITLE}" />
{/loop}
{$label} {$file_names nofilter}
</div>
<table class="table table-condensed table-hover">
<tbody>
{/if}
<tr>
<td class="col-md-6">
<span id="{$hash}">{$info.chaine}</span>
{if $info.dollar}
<span class="label label-warning">{intl l='Warning'}</span>
{intl l='This string contains a Smarty variable, and cannot not be translated properly'}
{/if}
</td>
<td class="col-md-6">
<div class="input-group">
<span class="input-group-addon"><a href="#" data-hash="{$hash}" class="copy-translation"><span class="glyphicon glyphicon-chevron-right"></span></a></span>
<input type="text" class="translation_field form-control" name="{$hash}" value="{$translated_strings[$info.chaine]}" />
</div>
</td>
</tr>
{/if}
{/foreach}
</tbody>
</table>
</div> {* panel *}
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{/block}
{block name="javascript-initialization"}
<script>
$(function() {
var translation_changed = false;
$('.submit-on-change').change(function() {
$('#translation_form').submit();
});
$('input.translation_field').change(function() { translation_changed = true; });
$('.copy-translation').click(function(ev) {
var hash = $(this).data('hash');
$('input[name='+hash+']').val($('#'+hash).html());
translation_changed = true;
ev.preventDefault();
})
$('#translation_form').submit(function(ev) {
if (translation_changed
&&
! confirm("{intl l='Some of your translations are not saved. Continue anyway ?'}") ) {
ev.preventDefault();
}
});
});
</script>
{/block}

View File

@@ -16,7 +16,7 @@
<li><a href="{url path='/admin/home'}">{intl l="Home"}</a></li> <li><a href="{url path='/admin/home'}">{intl l="Home"}</a></li>
<li><a href="{url path='/admin/configuration'}">{intl l="Configuration"}</a></li> <li><a href="{url path='/admin/configuration'}">{intl l="Configuration"}</a></li>
<li><a href="{url path='/admin/configuration/variables'}">{intl l="System variables"}</a></li> <li><a href="{url path='/admin/configuration/variables'}">{intl l="System variables"}</a></li>
<li>{intl l='Editing variable "%name"' name="{$NAME}"}</li> <li>{intl l='Editing variable "%name"' name=$NAME}</li>
</ul> </ul>
<div class="row"> <div class="row">
@@ -24,7 +24,7 @@
<div class="row"> <div class="row">
<div class="col-md-12 title title-without-tabs"> <div class="col-md-12 title title-without-tabs">
{intl l="Edit variable $NAME"} {intl l="Edit variable %name" name=$NAME}
</div> </div>
<div class="form-container"> <div class="form-container">

View File

@@ -0,0 +1,4 @@
<?php
return array (
);

View File

@@ -0,0 +1,4 @@
<?php
return array (
);

View File

@@ -0,0 +1,4 @@
<?php
return array (
);

View File

@@ -0,0 +1,4 @@
<?php
return array (
);