mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-27 15:54:03 +02:00
Refactor i18n implementation
One can now use $this->translate(msg) in a view or controller without the need to pass the module domain (web&cli). Forms still need to be built with _t(msg) and _mt(dom, msg). refs #5533
This commit is contained in:
parent
6cc4f1b53a
commit
bd34669357
@ -31,13 +31,11 @@ namespace Icinga\Application;
|
|||||||
|
|
||||||
use \DateTimeZone;
|
use \DateTimeZone;
|
||||||
use \Exception;
|
use \Exception;
|
||||||
use \Zend_Loader_Autoloader;
|
|
||||||
use \Icinga\Application\Modules\Manager as ModuleManager;
|
use \Icinga\Application\Modules\Manager as ModuleManager;
|
||||||
use \Icinga\Application\Platform;
|
|
||||||
use \Icinga\Application\Config;
|
use \Icinga\Application\Config;
|
||||||
use \Icinga\Exception\ProgrammingError;
|
|
||||||
use \Icinga\Exception\ConfigurationError;
|
use \Icinga\Exception\ConfigurationError;
|
||||||
use \Icinga\Util\DateTimeFactory;
|
use \Icinga\Util\DateTimeFactory;
|
||||||
|
use \Icinga\Util\Translator;
|
||||||
|
|
||||||
use Icinga\Data\ResourceFactory;
|
use Icinga\Data\ResourceFactory;
|
||||||
|
|
||||||
@ -427,4 +425,23 @@ abstract class ApplicationBootstrap
|
|||||||
DateTimeFactory::setConfig(array('timezone' => $tz));
|
DateTimeFactory::setConfig(array('timezone' => $tz));
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup internationalization using gettext
|
||||||
|
*
|
||||||
|
* Uses the language defined in the global config or the default one
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
protected function setupInternationalization()
|
||||||
|
{
|
||||||
|
Translator::setupLocale($this->config->global->get('language', 'en_US'));
|
||||||
|
|
||||||
|
$localeDir = $this->getApplicationDir('locale');
|
||||||
|
if (file_exists($localeDir) && is_dir($localeDir)) {
|
||||||
|
Translator::registerDomain('icinga', $localeDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ namespace Icinga\Application;
|
|||||||
|
|
||||||
use Icinga\Application\Platform;
|
use Icinga\Application\Platform;
|
||||||
use Icinga\Application\ApplicationBootstrap;
|
use Icinga\Application\ApplicationBootstrap;
|
||||||
use Icinga\Application\Modules\Manager as ModuleManager;
|
|
||||||
use Icinga\Cli\Params;
|
use Icinga\Cli\Params;
|
||||||
use Icinga\Cli\Loader;
|
use Icinga\Cli\Loader;
|
||||||
use Icinga\Cli\Screen;
|
use Icinga\Cli\Screen;
|
||||||
@ -63,12 +62,12 @@ class Cli extends ApplicationBootstrap
|
|||||||
{
|
{
|
||||||
$this->assertRunningOnCli();
|
$this->assertRunningOnCli();
|
||||||
$this->setupConfig()
|
$this->setupConfig()
|
||||||
->parseBasicParams()
|
->setupInternationalization()
|
||||||
->fixLoggingConfig()
|
->parseBasicParams()
|
||||||
->setupErrorHandling()
|
->fixLoggingConfig()
|
||||||
->setupResourceFactory()
|
->setupErrorHandling()
|
||||||
->setupModuleManager()
|
->setupResourceFactory()
|
||||||
;
|
->setupModuleManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function fixLoggingConfig()
|
protected function fixLoggingConfig()
|
||||||
|
@ -35,6 +35,7 @@ use Icinga\Application\ApplicationBootstrap;
|
|||||||
use Icinga\Application\Config;
|
use Icinga\Application\Config;
|
||||||
use Icinga\Application\Icinga;
|
use Icinga\Application\Icinga;
|
||||||
use Icinga\Application\Logger;
|
use Icinga\Application\Logger;
|
||||||
|
use Icinga\Util\Translator;
|
||||||
use Icinga\Web\Hook;
|
use Icinga\Web\Hook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -422,7 +423,7 @@ class Module
|
|||||||
protected function registerLocales()
|
protected function registerLocales()
|
||||||
{
|
{
|
||||||
if (file_exists($this->localedir) && is_dir($this->localedir)) {
|
if (file_exists($this->localedir) && is_dir($this->localedir)) {
|
||||||
bindtextdomain($this->name, $this->localedir);
|
Translator::registerDomain($this->name, $this->localedir);
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ use Icinga\User\Preferences\SessionStore;
|
|||||||
use Icinga\Util\DateTimeFactory;
|
use Icinga\Util\DateTimeFactory;
|
||||||
use Icinga\Session\Session as BaseSession;
|
use Icinga\Session\Session as BaseSession;
|
||||||
use Icinga\Web\Session;
|
use Icinga\Web\Session;
|
||||||
|
use Icinga\Util\Translator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this if you want to make use of Icinga functionality in other web projects
|
* Use this if you want to make use of Icinga functionality in other web projects
|
||||||
@ -116,10 +117,10 @@ class Web extends ApplicationBootstrap
|
|||||||
->setupResourceFactory()
|
->setupResourceFactory()
|
||||||
->setupSession()
|
->setupSession()
|
||||||
->setupUser()
|
->setupUser()
|
||||||
|
->setupInternationalization()
|
||||||
->setupTimezone()
|
->setupTimezone()
|
||||||
->setupRequest()
|
->setupRequest()
|
||||||
->setupZendMvc()
|
->setupZendMvc()
|
||||||
->setupTranslation()
|
|
||||||
->setupModuleManager()
|
->setupModuleManager()
|
||||||
->loadEnabledModules()
|
->loadEnabledModules()
|
||||||
->setupRoute()
|
->setupRoute()
|
||||||
@ -168,25 +169,6 @@ class Web extends ApplicationBootstrap
|
|||||||
return $this->viewRenderer;
|
return $this->viewRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load translations
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
private function setupTranslation()
|
|
||||||
{
|
|
||||||
// AuthManager::getInstance()->getSession()->language;
|
|
||||||
$locale = null;
|
|
||||||
if (!$locale) {
|
|
||||||
$locale = 'en_US';
|
|
||||||
}
|
|
||||||
putenv('LC_ALL=' . $locale . '.UTF-8');
|
|
||||||
setlocale(LC_ALL, $locale . '.UTF-8');
|
|
||||||
bindtextdomain('icinga', $this->getApplicationDir() . '/locale');
|
|
||||||
textdomain('icinga');
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatch public interface
|
* Dispatch public interface
|
||||||
*/
|
*/
|
||||||
@ -449,4 +431,30 @@ class Web extends ApplicationBootstrap
|
|||||||
DateTimeFactory::setConfig(array('timezone' => $tz));
|
DateTimeFactory::setConfig(array('timezone' => $tz));
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup internationalization using gettext
|
||||||
|
*
|
||||||
|
* Uses the preferred user language or the configured default and system default, respectively.
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
protected function setupInternationalization()
|
||||||
|
{
|
||||||
|
parent::setupInternationalization();
|
||||||
|
$userLocale = $this->user === null ? null : $this->user->getPreferences()->get('app.language');
|
||||||
|
|
||||||
|
if ($userLocale) {
|
||||||
|
try {
|
||||||
|
Translator::setupLocale($userLocale);
|
||||||
|
} catch (Exception $error) {
|
||||||
|
Logger::error(
|
||||||
|
'Cannot set locale "' . $userLocale . '" configured in ' .
|
||||||
|
'preferences of user "' . $this->user->getUsername() . '"'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,31 +27,25 @@
|
|||||||
*/
|
*/
|
||||||
// {{{ICINGA_LICENSE_HEADER}}}
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
if (function_exists('_')) {
|
use \Icinga\Util\Translator;
|
||||||
function t($messageId = null)
|
|
||||||
|
if (extension_loaded('gettext')) {
|
||||||
|
function t($messageId)
|
||||||
{
|
{
|
||||||
$msg = _($messageId);
|
return Translator::translate($messageId, 'icinga');
|
||||||
if (! $msg) {
|
|
||||||
return $messageId;
|
|
||||||
}
|
|
||||||
return $msg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mt($domain, $messageId = null)
|
function mt($domain, $messageId)
|
||||||
{
|
{
|
||||||
$msg = dgettext($domain, $messageId);
|
return Translator::translate($messageId, $domain);
|
||||||
if (! $msg) {
|
|
||||||
return $messageId;
|
|
||||||
}
|
|
||||||
return $msg;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
function t($messageId = null)
|
function t($messageId)
|
||||||
{
|
{
|
||||||
return $messageId;
|
return $messageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mt($domain, $messageId = null)
|
function mt($domain, $messageId)
|
||||||
{
|
{
|
||||||
return $messageId;
|
return $messageId;
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace Icinga\Cli;
|
namespace Icinga\Cli;
|
||||||
|
|
||||||
use Icinga\Cli\Loader;
|
|
||||||
use Icinga\Cli\Screen;
|
use Icinga\Cli\Screen;
|
||||||
|
use Icinga\Util\Translator;
|
||||||
use Icinga\Application\ApplicationBootstrap as App;
|
use Icinga\Application\ApplicationBootstrap as App;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
@ -48,6 +48,21 @@ abstract class Command
|
|||||||
return $this->trace;
|
return $this->trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate a string
|
||||||
|
*
|
||||||
|
* Autoselects the module domain, if any, and falls back to the global one if no translation could be found.
|
||||||
|
*
|
||||||
|
* @param string $text The string to translate
|
||||||
|
*
|
||||||
|
* @return string The translated string
|
||||||
|
*/
|
||||||
|
public function translate($text)
|
||||||
|
{
|
||||||
|
$domain = $this->moduleName === null ? 'icinga' : $this->moduleName;
|
||||||
|
return Translator::translate($text, $domain);
|
||||||
|
}
|
||||||
|
|
||||||
public function fail($msg)
|
public function fail($msg)
|
||||||
{
|
{
|
||||||
throw new Exception($msg);
|
throw new Exception($msg);
|
||||||
|
108
library/Icinga/Util/Translator.php
Normal file
108
library/Icinga/Util/Translator.php
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
/**
|
||||||
|
* This file is part of Icinga Web 2.
|
||||||
|
*
|
||||||
|
* Icinga Web 2 - Head for multiple monitoring backends.
|
||||||
|
* Copyright (C) 2014 Icinga Development Team
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* @copyright 2014 Icinga Development Team <info@icinga.org>
|
||||||
|
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
|
||||||
|
* @author Icinga Development Team <info@icinga.org>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
namespace Icinga\Util;
|
||||||
|
|
||||||
|
use \Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to ease internationalization when using gettext
|
||||||
|
*/
|
||||||
|
class Translator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The default gettext domain used as fallback
|
||||||
|
*/
|
||||||
|
const DEFAULT_DOMAIN = 'icinga';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Known gettext domains
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $knownDomains = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate a string
|
||||||
|
*
|
||||||
|
* Falls back to the default domain in case the string cannot be translated using the given domain
|
||||||
|
*
|
||||||
|
* @param string $text The string to translate
|
||||||
|
* @param string $domain The primary domain to use
|
||||||
|
*
|
||||||
|
* @return string The translated string
|
||||||
|
*
|
||||||
|
* @throws Exception In case the given domain is unknown
|
||||||
|
*/
|
||||||
|
public static function translate($text, $domain)
|
||||||
|
{
|
||||||
|
if ($domain !== self::DEFAULT_DOMAIN && !in_array($domain, self::$knownDomains)) {
|
||||||
|
throw new Exception("Cannot translate string '$text' with unknown domain '$domain'");
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = dgettext($domain, $text);
|
||||||
|
if ($res === $text && $domain !== self::DEFAULT_DOMAIN) {
|
||||||
|
return dgettext(self::DEFAULT_DOMAIN, $text);
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new gettext domain
|
||||||
|
*
|
||||||
|
* @param string $name The name of the domain to register
|
||||||
|
* @param string $directory The directory where message catalogs can be found
|
||||||
|
*
|
||||||
|
* @throws Exception In case the domain was not successfully registered
|
||||||
|
*/
|
||||||
|
public static function registerDomain($name, $directory)
|
||||||
|
{
|
||||||
|
if (bindtextdomain($name, $directory) === false) {
|
||||||
|
throw new Exception("Cannot register domain '$name' with path '$directory'");
|
||||||
|
}
|
||||||
|
bind_textdomain_codeset($name, 'UTF-8');
|
||||||
|
self::$knownDomains[] = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the locale to use
|
||||||
|
*
|
||||||
|
* @param string $localeName The name of the locale to use
|
||||||
|
*
|
||||||
|
* @throws Exception In case the locale's name is invalid
|
||||||
|
*/
|
||||||
|
public static function setupLocale($localeName)
|
||||||
|
{
|
||||||
|
if (setlocale(LC_ALL, $localeName . '.UTF-8') === false) {
|
||||||
|
throw new Exception("Cannot set locale '$localeName.UTF-8' for category 'LC_ALL'");
|
||||||
|
}
|
||||||
|
putenv('LC_ALL=' . $localeName . '.UTF-8'); // Failsafe, Win and Unix
|
||||||
|
putenv('LANG=' . $localeName . '.UTF-8'); // Windows fix, untested
|
||||||
|
}
|
||||||
|
}
|
@ -32,17 +32,13 @@ namespace Icinga\Web\Controller;
|
|||||||
use \Exception;
|
use \Exception;
|
||||||
use \Zend_Controller_Action;
|
use \Zend_Controller_Action;
|
||||||
use \Zend_Controller_Request_Abstract;
|
use \Zend_Controller_Request_Abstract;
|
||||||
use \Zend_Controller_Front;
|
|
||||||
use \Zend_Controller_Response_Abstract;
|
use \Zend_Controller_Response_Abstract;
|
||||||
use \Zend_Controller_Action_HelperBroker;
|
use \Zend_Controller_Action_HelperBroker;
|
||||||
use \Zend_Layout;
|
|
||||||
use Icinga\Authentication\Manager as AuthManager;
|
use Icinga\Authentication\Manager as AuthManager;
|
||||||
use Icinga\Application\Benchmark;
|
use Icinga\Application\Benchmark;
|
||||||
use Icinga\Application\Config;
|
use Icinga\Util\Translator;
|
||||||
use Icinga\Web\Notification;
|
|
||||||
use Icinga\Web\Widget\Tabs;
|
use Icinga\Web\Widget\Tabs;
|
||||||
use Icinga\Web\Url;
|
use Icinga\Web\Url;
|
||||||
use Icinga\Web\Request;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all core action controllers
|
* Base class for all core action controllers
|
||||||
@ -152,15 +148,19 @@ class ActionController extends Zend_Controller_Action
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translate the given string with the global translation catalog
|
* Translate a string
|
||||||
*
|
*
|
||||||
* @param string $string The string that should be translated
|
* Autoselects the module domain, if any, and falls back to the global one if no translation could be found.
|
||||||
*
|
*
|
||||||
* @return string
|
* @param string $text The string to translate
|
||||||
|
*
|
||||||
|
* @return string The translated string
|
||||||
*/
|
*/
|
||||||
public function translate($string)
|
public function translate($text)
|
||||||
{
|
{
|
||||||
return t($string);
|
$module = $this->getRequest()->getModuleName();
|
||||||
|
$domain = $module === 'default' ? 'icinga' : $module;
|
||||||
|
return Translator::translate($text, $domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -212,7 +212,6 @@ class ActionController extends Zend_Controller_Action
|
|||||||
$this->_helper->Redirector->gotoUrlAndExit($url);
|
$this->_helper->Redirector->gotoUrlAndExit($url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect whether the current request requires changes in the layout and apply them before rendering
|
* Detect whether the current request requires changes in the layout and apply them before rendering
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user