Skip to content

Instantly share code, notes, and snippets.

@fsuter
Created November 13, 2012 10:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fsuter/4065082 to your computer and use it in GitHub Desktop.
Save fsuter/4065082 to your computer and use it in GitHub Desktop.
Loading localized labels for JavaScript with TYPO3 Flow/Fluid
<?php
namespace Cobweb\Monitoring\ViewHelpers;
/* *
* This script belongs to the FLOW3 package "Cobweb.Monitoring". *
* *
* It is free software; you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License, either version 3 *
* of the License, or (at your option) any later version. *
* *
* The TYPO3 project - inspiring people to share! *
* */
use TYPO3\FLOW3\Annotations as FLOW3;
/**
* Takes some localized strings and makes them available in JavaScript
*
* IMPORTANT: note that that the string keys must not contain dots (.) or dashes (-)
* as JavaScript will choke on them.
*
* = Examples =
*
* <code title="JavaScript labels">
* <monitoring:javascriptLabels keyList="{0: 'yourFather'}" source="EmpireStrikesBack" package="StarWars"></monitoring:javascriptLabels>
* </code>
* <output>
* <script type="text/javascript">
* var Language = {
* yourFather: 'Luke, I\'m your father.',
* };
* </script>
* </output>
*
* @api
*/
class JavascriptLabelsViewHelper extends \TYPO3\Fluid\Core\ViewHelper\AbstractViewHelper {
/**
* @var \TYPO3\FLOW3\I18n\Translator
* @FLOW3\Inject
*/
protected $translator;
/**
* Reads some localized strings and stores them in global JS array
*
* This makes these strings usable from JavaScript
* Much code taken from \TYPO3\Fluid\ViewHelpers\TranslateViewHelper
*
* @param array $keyList List of strings to fetch
* @param string $source Name of file with translations
* @param string $package Target package key. If not set, the current package key will be used
* @param string $locale An identifier of locale to use (NULL for use the default locale)
* @throws \TYPO3\Fluid\Core\ViewHelper\Exception
* @return string A <script> tag containing the localized labels, as properties of a global object
* @api
*/
public function render(array $keyList = array(), $source = 'Main', $package = NULL, $locale = NULL) {
$localeObject = NULL;
if ($locale !== NULL) {
try {
$localeObject = new \TYPO3\FLOW3\I18n\Locale($locale);
} catch (\TYPO3\FLOW3\I18n\Exception\InvalidLocaleIdentifierException $e) {
throw new \TYPO3\Fluid\Core\ViewHelper\Exception('"' . $locale . '" is not a valid locale identifier.' , 1279815885);
}
}
if ($package === NULL) {
$package = $this->controllerContext->getRequest()->getControllerPackageKey();
}
$content = '<script type="text/javascript">';
$content .= 'var Language = {' . "\n";
foreach ($keyList as $key) {
$translation = $this->translator->translateById($key, array(), NULL, $localeObject, $source, $package);
$content .= $key . ': ' . "'" . addslashes($translation) . "',\n";
}
$content .= '};' . "\n";
$content .= '</script>';
return $content;
}
}
?>
@fsuter
Copy link
Author

fsuter commented Nov 13, 2012

This is pretty rough. In particular it does not take plurals into account.
We probably need a global JS object that would be able to retrieve the
appropriate strings given a key and a quantity, possibly with arguments too.
Localized strings could be pushed to this object.

Another problem is that our usual practice is to use dots in keys.
Using the key as is as a JavaScript "key" (property name) will not work.
Nor do dashes. So a serious engine would have to work around that too.

@afoeder
Copy link

afoeder commented Nov 13, 2012

a tiny improvement would at least be the use of PHP'S json_encode in order not to "hack" the JavaScript object together. So, lines 74++ could be

$jsObject = array();
foreach ($keyList as $key) {
    $jsObject[$key] = $this->translator->translateById($key, array(), NULL, $localeObject, $source, $package);
}
$content = 'var Language = ' . json_encode($jsObject);

@afoeder
Copy link

afoeder commented Nov 13, 2012

...and maybe you want to make it a TagBasedViewHelper or don'T render the <script> tags at all, meaning to just let the VH Output the actual object (probably even without the assignment; to result in the following fluid (I hope the CDATA stuff is correct ;) :

<script type="text/javascript">
<![CDATA[(function() {
var language = ]]>{acme:translation.getDto()}<![CDATA
})();
]]>
</script>

@pcworld
Copy link

pcworld commented Sep 26, 2019

Btw this code is likely vulnerable to XSS if malicious localizations would be used. The strings could include </script>.
Edit: The addslashes might prevent it, but I wouldn't be sure about it. Better use something safer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment