Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 53 additions & 19 deletions Controller/WebUIController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,36 @@
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Translator;
use Translation\Bundle\Exception\MessageValidationException;
use Translation\Bundle\Model\WebUiMessage;
use Translation\Bundle\Service\StorageService;
use Translation\Common\Exception\StorageException;
use Translation\Bundle\Model\CatalogueMessage;
use Translation\Common\Model\Message;

/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class WebUIController extends Controller
{
/**
* Show a dashboard for the configuration.
*
* @param string|null $configName
*
* @return Response
*/
public function indexAction($configName = null)
{
$config = $this->getConfiguration($configName);
$localeMap = $this->getLocale2LanguageMap();
$catalogues = $this->get('php_translation.catalogue_fetcher')->getCatalogues(array_keys($localeMap), [$config['output_dir']]);

$configuedLocales = $this->getParameter('php_translation.locales');
$allLocales = Intl::getLocaleBundle()->getLocaleNames('en');
$locales = [];
foreach ($configuedLocales as $l) {
$locales[$l] = $allLocales[$l];
}
$catalogues = $this->get('php_translation.catalogue_fetcher')->getCatalogues($configuedLocales, [$config['output_dir']]);
$catalogueSize = [];
$maxDomainSize = [];
$maxCatalogueSize = 1;

// For each catalogue (or locale)
/** @var MessageCatalogue $catalogue */
foreach ($catalogues as $catalogue) {
$locale = $catalogue->getLocale();
Expand All @@ -66,26 +71,29 @@ public function indexAction($configName = null)
'catalogueSize' => $catalogueSize,
'maxDomainSize' => $maxDomainSize,
'maxCatalogueSize' => $maxCatalogueSize,
'locales' => $locales,
'localeMap' => $localeMap,
'configName' => $configName,
'configNames' => $this->get('php_translation.configuration_manager')->getNames(),
]);
}

/**
* @param $locale
* @param $domain
* Show a catalogue.
*
* @param string $configName
* @param string $locale
* @param string $domain
*
* @return Response
*/
public function showAction($configName, $locale, $domain)
{
$config = $this->getConfiguration($configName);
$locales = $this->getParameter('php_translation.locales');
/** @var Translator $translator */
$catalogues = $this->get('php_translation.catalogue_fetcher')->getCatalogues($locales, [$config['output_dir']]);

// Get a catalogue manager and load it with all the catalogues
$catalogueManager = $this->get('php_translation.catalogue_manager');
$catalogueManager->load($catalogues);
$catalogueManager->load($this->get('php_translation.catalogue_fetcher')->getCatalogues($locales, [$config['output_dir']]));

/** @var CatalogueMessage[] $messages */
$messages = $catalogueManager->getMessages($locale, $domain);
Expand All @@ -106,21 +114,24 @@ public function showAction($configName, $locale, $domain)

/**
* @param Request $request
* @param string $configName
* @param string $locale
* @param string $domain
*
* @return Response
*/
public function createAction(Request $request, $configName, $locale, $domain)
{
$storage = $this->get('php_translation.storage.file.'.$configName);
/** @var StorageService $storage */
$storage = $this->get('php_translation.storage.'.$configName);
try {
$message = $this->getMessage($request, ['Create']);
} catch (MessageValidationException $e) {
return new Response($e->getMessage(), 400);
}

try {
$storage->set($locale, $domain, $message->getKey(), $message->getMessage());
$storage->create(new Message($message->getKey(), $domain, $locale, $message->getMessage()));
} catch (StorageException $e) {
throw new BadRequestHttpException(sprintf(
'Key "%s" does already exist for "%s" on domain "%s".',
Expand All @@ -130,7 +141,9 @@ public function createAction(Request $request, $configName, $locale, $domain)
), $e);
}

return new Response('Translation created');
return $this->render('TranslationBundle:WebUI:create.html.twig', [
'message' => $message,
]);
}

/**
Expand All @@ -149,7 +162,9 @@ public function editAction(Request $request, $configName, $locale, $domain)
return new Response($e->getMessage(), 400);
}

$this->get('php_translation.storage.file.'.$configName)->update($locale, $domain, $message->getKey(), $message->getMessage());
/** @var StorageService $storage */
$storage = $this->get('php_translation.storage.'.$configName);
$storage->update(new Message($message->getKey(), $domain, $locale, $message->getMessage()));

return new Response('Translation updated');
}
Expand All @@ -170,7 +185,9 @@ public function deleteAction(Request $request, $configName, $locale, $domain)
return new Response($e->getMessage(), 400);
}

$this->get('php_translation.storage.file.'.$configName)->delete($locale, $domain, $message->getKey());
/** @var StorageService $storage */
$storage = $this->get('php_translation.storage.'.$configName);
$storage->delete($locale, $domain, $message->getKey());

return new Response('Message was deleted');
}
Expand Down Expand Up @@ -222,4 +239,21 @@ private function getMessage(Request $request, array $validationGroups = [])

return $message;
}

/**
* This will return a map of our configured locales and their language name.
*
* @return array locale => language
*/
private function getLocale2LanguageMap()
{
$configuedLocales = $this->getParameter('php_translation.locales');
$names = Intl::getLocaleBundle()->getLocaleNames('en');
$map = [];
foreach ($configuedLocales as $l) {
$map[$l] = $names[$l];
}

return $map;
}
}
3 changes: 3 additions & 0 deletions Resources/public/css/webui.css
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
font-weight: bold;
font-size: 110%
}
.message-delete {
float: right;
}

pre a {
text-decoration: none;
Expand Down
91 changes: 91 additions & 0 deletions Resources/public/js/webui.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,83 @@ function editTranslation(el) {
xmlhttp.send(JSON.stringify({message: el.value, key: el.getAttribute("data-key")}));
}

/**
* Create a new translation
* @param el
* @param url
* @returns {boolean}
*/
function createTranslation(el, url) {
var xmlhttp = new XMLHttpRequest();
var messageInput = document.getElementById('create-message');
var keyInput = document.getElementById('create-key');

xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE ) {
var errorDiv = el.getElementsByClassName("ajax-result")[0];

if (xmlhttp.status == 200) {
messageInput.value = "";
keyInput.value = "";

var resultDiv = document.getElementById("new-translations");
resultDiv.innerHTML = xmlhttp.responseText + resultDiv.innerHTML;
}
else if (xmlhttp.status == 400) {
errorDiv.className += ' error';
errorDiv.innerHTML = xmlhttp.responseText;
}
else {
errorDiv.className += ' error';
errorDiv.innerHTML = "Unknown error";
}

setTimeout(function() {removeResultElement(errorDiv);}, 6000);
}
};

xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlhttp.send(JSON.stringify({message: messageInput.value, key: keyInput.value}));

return false;
}


/**
* Delete a translation.
* @param el
*/
function deleteTranslation(el) {
var xmlhttp = new XMLHttpRequest();
var messageKey = el.getAttribute("data-key");

xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE ) {
var row = document.getElementById(messageKey);
var errorDiv = row.getElementsByClassName("ajax-result")[0];

if (xmlhttp.status == 200) {
row.parentNode.removeChild(row);
}
else if (xmlhttp.status == 400) {
errorDiv.className += ' error';
errorDiv.innerHTML = xmlhttp.responseText;
}
else {
errorDiv.className += ' error';
errorDiv.innerHTML = "Unknown error";
}

setTimeout(function() {removeResultElement(errorDiv);}, 6000);
}
};

xmlhttp.open("DELETE", editUrl, true);
xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlhttp.send(JSON.stringify({key: messageKey}));
}

/**
* Remove the result element
*
Expand All @@ -40,3 +117,17 @@ function removeResultElement(el) {
el.innerHTML = '';
el.className = "ajax-result";
}

/**
* Toggle visibility of an element
* @param id
*/
function toggleElement(id) {
var el = document.getElementById(id);
if (el.offsetParent === null) {
el.classList.add("in");
} else {
el.classList.remove("in");
}
}

11 changes: 11 additions & 0 deletions Resources/views/WebUI/create.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div class="message row" id="{{ message.key }}">
<div class="col-md-6 col-xs-12">
<a class="message-key" href="#{{ message.key }}">{{ message.key }}</a>
<textarea
class="message-textarea"
data-key="{{ message.key }}"
onchange="editTranslation(this)"
>{{ message.message }}</textarea>
<div class="ajax-result"></div>
</div>
</div>
2 changes: 1 addition & 1 deletion Resources/views/WebUI/index.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<div class="catalogue-list">
{% for cataloge in catalogues %}
<div class="catalouge">
<h3>{{ locales[cataloge.locale] }}</h3>
<h3>{{ localeMap[cataloge.locale] }}</h3>
<table class="domain-table">
{% for domain,messages in cataloge.all %}
{% set pg = (100*messages|length/maxDomainSize[domain])|round %}
Expand Down
24 changes: 23 additions & 1 deletion Resources/views/WebUI/show.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,27 @@

<div class="container-fluid message-list">

<h1>Translations</h1>
<h1>Translations <a href="javascript:void(0);"
class="btn btn-secondary"
onclick='toggleElement("create-translation")'
aria-controls="create-translation">Add new</a></h1>

<div class="collapse" id="create-translation">
<form class="form" onsubmit="return createTranslation(this, '{{ path('translation_create', {configName: configName, locale:currentLocale,domain:currentDomain}) }}')">
<div class="form-group">
<label for="create-key">Key</label>
<input type="text" class="form-control" id="create-key" placeholder="foo.label">
</div>
<div class="form-group">
<label for="create-message">Translation</label>
<input type="email" class="form-control" id="create-message" placeholder="Lorem Ipsum">
</div>
<button type="submit" class="btn btn-primary">Create</button>
<div class="ajax-result"></div>
</form>
</div>

<div id="new-translations"></div>
{% for idx, message in messages if message.new %}
{{ macro.printMessage(idx + 1, message) }}
{% endfor %}
Expand All @@ -57,6 +77,8 @@
<span class="text-warning" title="Obsolete">&#x26A0;</span>
{% endif %}
<a class="message-key" href="#{{ message.key }}">{{ message.key }}</a>
<a class="message-delete" href="javascript:void(0)" data-key="{{ message.key }}" title="Delete translation" onclick='confirm("Are you sure?")?deleteTranslation(this):false;'>&#x274C;</a>

<textarea
class="message-textarea"
data-key="{{ message.key }}"
Expand Down
5 changes: 2 additions & 3 deletions Service/CatalogueFetcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@
use Symfony\Component\Translation\MessageCatalogue;

/**
* Fetches catalogues from source files.
* Fetches catalogues from source files. This will only work with local file storage
* and the actions are read only.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*
* @deprecated I think this could be removed.. Not sure.
*/
class CatalogueFetcher
{
Expand Down