| [ Index ] |
|
Code source de Symfony 1.0.0 |
1 <?php 2 3 /* 4 * $Id: TranslateGettext.php 3076 2006-12-18 08:52:12Z fabien $ 5 * 6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 7 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 8 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 9 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 10 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 12 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 13 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 14 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 15 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 16 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 17 * 18 * This software consists of voluntary contributions made by many individuals 19 * and is licensed under the LGPL. For more information please see 20 * <http://phing.info>. 21 */ 22 23 require_once 'phing/filters/BaseParamFilterReader.php'; 24 include_once 'phing/filters/ChainableReader.php'; 25 26 /** 27 * Replaces gettext("message id") and _("message id") with the translated string. 28 * 29 * Gettext is great for creating multi-lingual sites, but in some cases (e.g. for 30 * performance reasons) you may wish to replace the gettext calls with the translations 31 * of the strings; that's what this task is for. Note that this is similar to 32 * ReplaceTokens, but both the find and the replace aspect is more complicated -- hence 33 * this is a separate, stand-alone filter. 34 * 35 * <p> 36 * Example:<br> 37 * <pre> 38 * <translategettext locale="en_US" domain="messages" dir="${webroot}/local"/> 39 * </pre> 40 * 41 * @author Hans Lellelid <hans@xmpl.org> 42 * @version $Revision: 1.11 $ $Date: 2005/12/08 15:59:56 $ 43 * @access public 44 * @see BaseFilterReader 45 * @package phing.filters 46 */ 47 class TranslateGettext extends BaseParamFilterReader implements ChainableReader { 48 49 // constants for specifying keys to expect 50 // when this is called using <filterreader ... /> 51 const DOMAIN_KEY = "domain"; 52 const DIR_KEY = "dir"; 53 const LOCALE_KEY = "locale"; 54 55 /** The domain to use */ 56 private $domain = 'messages'; 57 58 /** The dir containing LC_MESSAGES */ 59 private $dir; 60 61 /** The locale to use */ 62 private $locale; 63 64 /** The system locale before it was changed for this filter. */ 65 private $storedLocale; 66 67 /** 68 * Set the text domain to use. 69 * The text domain must correspond to the name of the compiled .mo files. 70 * E.g. "messages" ==> $dir/LC_MESSAGES/messages.mo 71 * "mydomain" ==> $dir/LC_MESSAGES/mydomain.mo 72 * @param string $domain 73 */ 74 function setDomain($domain) { 75 $this->domain = $domain; 76 } 77 78 /** 79 * Get the current domain. 80 * @return string 81 */ 82 function getDomain() { 83 return $this->domain; 84 } 85 86 /** 87 * Sets the root locale directory. 88 * @param PhingFile $dir 89 */ 90 function setDir(PhingFile $dir) { 91 $this->dir = $dir; 92 } 93 94 /** 95 * Gets the root locale directory. 96 * @return PhingFile 97 */ 98 function getDir() { 99 return $this->dir; 100 } 101 102 /** 103 * Sets the locale to use for translation. 104 * Note that for gettext() to work, you have to make sure this locale 105 * is specific enough for your system (e.g. some systems may allow an 'en' locale, 106 * but others will require 'en_US', etc.). 107 * @param string $locale 108 */ 109 function setLocale($locale) { 110 $this->locale = $locale; 111 } 112 113 /** 114 * Gets the locale to use for translation. 115 * @return string 116 */ 117 function getLocale() { 118 return $this->locale; 119 } 120 121 /** 122 * Make sure that required attributes are set. 123 * @throws BuldException - if any required attribs aren't set. 124 */ 125 protected function checkAttributes() { 126 if (!$this->domain || !$this->locale || !$this->dir) { 127 throw new BuildException("You must specify values for domain, locale, and dir attributes."); 128 } 129 } 130 131 /** 132 * Initialize the gettext/locale environment. 133 * This method will change some env vars and locale settings; the 134 * restoreEnvironment should put them all back :) 135 * 136 * @return void 137 * @throws BuildException - if locale cannot be set. 138 * @see restoreEnvironment() 139 */ 140 protected function initEnvironment() { 141 $this->storedLocale = getenv("LANG"); 142 143 $this->log("Setting locale to " . $this->locale, PROJECT_MSG_DEBUG); 144 putenv("LANG=".$this->locale); 145 $ret = setlocale(LC_ALL, $this->locale); 146 if ($ret === false) { 147 $msg = "Could not set locale to " . $this->locale 148 . ". You may need to use fully qualified name" 149 . " (e.g. en_US instead of en)."; 150 throw new BuildException($msg); 151 } 152 153 $this->log("Binding domain '".$this->domain."' to " . $this->dir, PROJECT_MSG_DEBUG); 154 bindtextdomain($this->domain, $this->dir->getAbsolutePath()); 155 textdomain($this->domain); 156 } 157 158 /** 159 * Restores environment settings and locale. 160 * This does _not_ restore any gettext-specific settings 161 * (e.g. textdomain()). 162 * 163 * @return void 164 */ 165 protected function restoreEnvironment() { 166 putenv("LANG=".$this->storedLocale); 167 setlocale(LC_ALL, $this->storedLocale); 168 } 169 170 /** 171 * Performs gettext translation of msgid and returns translated text. 172 * 173 * This function simply wraps gettext() call, but provides ability to log 174 * string replacements. (alternative would be using preg_replace with /e which 175 * would probably be faster, but no ability to debug/log.) 176 * 177 * @param array $matches Array of matches; we're interested in $matches[2]. 178 * @return string Translated text 179 */ 180 private function xlateStringCallback($matches) { 181 $charbefore = $matches[1]; 182 $msgid = $matches[2]; 183 $translated = gettext($msgid); 184 $this->log("Translating \"$msgid\" => \"$translated\"", PROJECT_MSG_DEBUG); 185 return $charbefore . '"' . $translated . '"'; 186 } 187 188 /** 189 * Returns the filtered stream. 190 * The original stream is first read in fully, and then translation is performed. 191 * 192 * @return mixed the filtered stream, or -1 if the end of the resulting stream has been reached. 193 * 194 * @throws IOException - if the underlying stream throws an IOException during reading 195 * @throws BuildException - if the correct params are not supplied 196 */ 197 function read($len = null) { 198 199 if ( !$this->getInitialized() ) { 200 $this->_initialize(); 201 $this->setInitialized(true); 202 } 203 204 // Make sure correct params/attribs have been set 205 $this->checkAttributes(); 206 207 $buffer = $this->in->read($len); 208 if($buffer === -1) { 209 return -1; 210 } 211 212 // Setup the locale/gettext environment 213 $this->initEnvironment(); 214 215 216 // replace any occurrences of _("") or gettext("") with 217 // the translated value. 218 // 219 // ([^\w]|^)_\("((\\"|[^"])*)"\) 220 // --$1--- -----$2---- 221 // ---$3-- [match escaped quotes or any char that's not a quote] 222 // 223 // also match gettext() -- same as above 224 225 $buffer = preg_replace_callback('/([^\w]|^)_\("((\\\"|[^"])*)"\)/', array($this, 'xlateStringCallback'), $buffer); 226 $buffer = preg_replace_callback('/([^\w]|^)gettext\("((\\\"|[^"])*)"\)/', array($this, 'xlateStringCallback'), $buffer); 227 228 // Check to see if there are any _('') calls and flag an error 229 230 // Check to see if there are any unmatched gettext() calls -- and flag an error 231 232 $matches = array(); 233 if (preg_match('/([^\w]|^)(gettext\([^\)]+\))/', $buffer, $matches)) { 234 $this->log("Unable to perform translation on: " . $matches[2], PROJECT_MSG_WARN); 235 } 236 237 $this->restoreEnvironment(); 238 239 return $buffer; 240 } 241 242 /** 243 * Creates a new TranslateGettext filter using the passed in 244 * Reader for instantiation. 245 * 246 * @param Reader $reader A Reader object providing the underlying stream. 247 * Must not be <code>null</code>. 248 * 249 * @return TranslateGettext A new filter based on this configuration, but filtering 250 * the specified reader 251 */ 252 function chain(Reader $reader) { 253 $newFilter = new TranslateGettext($reader); 254 $newFilter->setProject($this->getProject()); 255 $newFilter->setDomain($this->getDomain()); 256 $newFilter->setLocale($this->getLocale()); 257 $newFilter->setDir($this->getDir()); 258 return $newFilter; 259 } 260 261 /** 262 * Parses the parameters if this filter is being used in "generic" mode. 263 */ 264 private function _initialize() { 265 $params = $this->getParameters(); 266 if ( $params !== null ) { 267 foreach($params as $param) { 268 switch($param->getType()) { 269 case self::DOMAIN_KEY: 270 $this->setDomain($param->getValue()); 271 break; 272 case self::DIR_KEY: 273 $this->setDir($this->project->resolveFile($param->getValue())); 274 break; 275 276 case self::LOCALE_KEY: 277 $this->setLocale($param->getValue()); 278 break; 279 } // switch 280 } 281 } // if params !== null 282 } 283 } 284 285 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Fri Mar 16 22:42:14 2007 | par Balluche grâce à PHPXref 0.7 |