Skip to content

Instantly share code, notes, and snippets.

@jgornick
Created September 18, 2009 17:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jgornick/189194 to your computer and use it in GitHub Desktop.
Save jgornick/189194 to your computer and use it in GitHub Desktop.
ZF: Bootstrap Process for I18n
# Autoloader Namespaces
autoloaderNamespaces[] = "My_"
# Custom Resource Plugins
pluginPaths.My_Application_Resource = APPLICATION_PATH "/../lib/My/Application/Resource/"
# Front Controller Params
resources.frontController.params.locales[] = "en"
resources.frontController.params.locales[] = "ja"
resources.frontController.params.tldLocales.jp = "ja"
# Front Controller Plugins
resources.frontController.plugins.I18n = "My_Controller_Plugin_I18n"
# Locale
resources.locale.default = "en"
# Router/Routes
resources.router.locale.enabled = true
resources.router.routes.action_index.route = ":action/*"
resources.router.routes.action_index.defaults.controller = "index"
resources.router.routes.action_index.defaults.action = "index"
#resources.router.routes.action_index.type = "Zend_Controller_Router_Route_Regex"
#resources.router.routes.action_index.route = "(\w+)\/*"
#resources.router.routes.action_index.defaults.controller = "index"
#resources.router.routes.action_index.defaults.action = "index"
#resources.router.routes.action_index.map.1 = "action"
<?php
class My_Controller_Plugin_I18n extends Zend_Controller_Plugin_Abstract
{
/**
* Sets the application locale and translation based on the locale param, if
* one is not provided it defaults to english
*
* @param Zend_Controller_Request_Abstract $request
*/
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
$frontController = Zend_Controller_Front::getInstance();
$params = $request->getParams();
$registry = Zend_Registry::getInstance();
// Steps setting the locale.
// 1. Defaults to English (Done in config)
// 2. TLD in host header
// 3. Locale params specified in request
$locale = $registry->get('Zend_Locale');
// Check host header TLD.
$tld = preg_replace('/^.*\./', '', $request->getHeader('Host'));
// Provide a list of tld's and their corresponding default languages
$tldLocales = $frontController->getParam('tldLocales');
if (array_key_exists($tld, $tldLocales)) {
// The TLD in the request matches one of our specified TLD -> Locales
$locale->setLocale($tldLocales[$tld]);
} else if (isset($params['locale'])) {
// There is a locale specified in the request params.
$locale->setLocale($params['locale']);
}
// Now that our locale is set, let's check which language has been selected
// and try to load a translation file for it. If the language is the default,
// then we do not need to load a translation.
$language = $locale->getLanguage();
if ($language !== $locale->getDefault()) {
$i18nFile = APPLICATION_PATH . '/data/i18n/source-' . $language . '.mo';
try {
$translate =
new Zend_Translate('gettext', $i18nFile, $locale, array('disableNotices' => true));
Zend_Registry::set('Zend_Translate', $translate);
Zend_Form::setDefaultTranslator($translate);
} catch (Zend_Translate_Exception $e) {
// Since there was an error when trying to load the translation catalog,
// let's not load a translation object which essentially defaults to
// locale default.
}
}
// Now that we have our locale setup, let's check to see if we are loading
// a language that is not the default, and update our base URL on the front
// controller to the specified language.
$defaultLanguage = array_keys($locale->getDefault());
$defaultLanguage = $defaultLanguage[0];
$path = '/' . ltrim($request->getPathInfo(), '/\\');
// If the language is in the path, then we will want to set the baseUrl
// to the specified language.
if (preg_match('/^\/' . $language . '\/?/', $path)) {
$viewRenderer =
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
$view = $viewRenderer->view;
$baseUrl = $frontController->getBaseUrl() . '/' . $language;
$frontController->setBaseUrl($baseUrl);
$view->getHelper('BaseUrl')->setBaseUrl($baseUrl);
}
setcookie('Zend_Locale', $language, null, '/', $request->getHttpHost());
}
}
<?php
class Default_View_Helper_LocaleSwitcher extends Zend_View_Helper_Abstract
{
public function localeSwitcher()
{
$output = array();
$frontController = Zend_Controller_Front::getInstance();
$locales = $frontController->getParam('locales');
$request = $frontController->getRequest();
$baseUrl = $request->getBaseUrl();
$path = '/' . trim($request->getPathInfo(), '/\\');
if (count($locales) > 0) {
$locale = Zend_Registry::get('Zend_Locale');
$localeLanguage = $locale->getLanguage();
$defaultLocaleLanguage = array_keys($locale->getDefault());
$defaultLocaleLanguage = $defaultLocaleLanguage[0];
array_push($output, '<ul id="locale_switcher">');
foreach ($locales as $language) {
$imageSrc = 'img/i18n_';
$imageSrc .= $language . '_' . ($localeLanguage == $language ? 'on' : 'off');
$imageSrc .= '.gif';
$urlLanguage = $defaultLocaleLanguage == $language
? ''
: '/' . $language;
if (strlen($baseUrl) === 0) {
$localeUrl = $urlLanguage . $path;
} else {
$localeUrl = preg_replace('/^' . preg_quote($baseUrl, '/') . '\/?/',
$urlLanguage . '/', $path);
}
array_push($output, '<li>');
array_push($output, '<a href="' . $localeUrl . '">');
array_push($output, '<img src="' . $this->view->assetUrl($imageSrc) . '" alt="' . $language . '" />');
array_push($output, '</a>');
array_push($output, '</li>');
}
array_push($output, '</ul>');
}
return join('', $output);
}
}
<?php
class My_Application_Resource_Router extends Zend_Application_Resource_Router
{
public $_explicitType = 'router';
protected $_front;
protected $_locale;
/**
* Retrieve router object
*
* @return Zend_Controller_Router_Rewrite
*/
public function getRouter()
{
$options = $this->getOptions();
if (!isset($options['locale']['enabled']) ||
!$options['locale']['enabled']) {
return parent::getRouter();
}
$bootstrap = $this->getBootstrap();
if (!$this->_front) {
$bootstrap->bootstrap('FrontController');
$this->_front = $bootstrap->getContainer()->frontcontroller;
}
if (!$this->_locale) {
$bootstrap->bootstrap('Locale');
$this->_locale = $bootstrap->getContainer()->locale;
}
$defaultLocale = array_keys($this->_locale->getDefault());
$defaultLocale = $defaultLocale[0];
$locales = $this->_front->getParam('locales');
$requiredLocalesRegex = '^(' . join('|', $locales) . ')$';
$routes = $options['routes'];
foreach ($routes as $key => $value) {
// First let's add the default locale to this routes defaults.
$defaults = isset($value['defaults'])
? $value['defaults']
: array();
// Always default all routes to the Zend_Locale default
$value['defaults'] = array_merge(array( 'locale' => $defaultLocale ), $defaults);
$routes[$key] = $value;
// Get our route and make sure to remove the first forward slash
// since it's not needed.
$routeString = $value['route'];
$routeString = ltrim($routeString, '/\\');
// Modify our normal route to have the locale parameter.
if (!isset($value['type']) ||
$value['type'] === 'Zend_Controller_Router_Route') {
$value['route'] = ':locale/' . $routeString;
$value['reqs']['locale'] = $requiredLocalesRegex;
$routes['locale_' . $key] = $value;
} else if ($value['type'] === 'Zend_Controller_Router_Route_Regex') {
$value['route'] = '(' . join('|', $locales) . ')\/' . $routeString;
// Since we added the local regex match, we need to bump the existing
// match numbers plus one.
$map = isset($value['map']) ? $value['map'] : array();
foreach ($map as $index => $word) {
unset($map[$index++]);
$map[$index] = $word;
}
// Add our locale map
$map[1] = 'locale';
ksort($map);
$value['map'] = $map;
$routes['locale_' . $key] = $value;
} else if ($value['type'] === 'Zend_Controller_Router_Route_Static') {
foreach ($locales as $locale) {
$value['route'] = $locale . '/' . $routeString;
$value['defaults']['locale'] = $locale;
$routes['locale_' . $locale . '_' . $key] = $value;
}
}
}
$options['routes'] = $routes;
$this->setOptions($options);
return parent::getRouter();
}
}
@thoys
Copy link

thoys commented Feb 19, 2015

hey @jgornick , great snippet/example , one note tho, for me the .ini comments are starting with semicolons (;), hashes (#) are not allowed.

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