|
Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon. |
|
View previous topic :: View next topic |
Author |
Message |
zerkms Smarty n00b
Joined: 24 Jun 2006 Posts: 1 Location: Komsomolsk-on-Amur, Russia
|
Posted: Mon Jun 15, 2009 3:40 am Post subject: |
|
|
my solution is provide such i18n of templates:
{_ somestring}
then "somestring" is translated (doesn't matter, how) and returned back. the templates compiled in different .php. so the "english" version get names like:
%%0A^0AE^0AEA648F%%view.tpl-en.php
and other, like:
%%0A^0AE^0AEA648F%%view.tpl-ru.php
in that compiled templates the strings are "as is", they are constantly in the templates.
and, of course, the magical underscore works for functions parameters, etc. like:
{somefunc arg="_ value"}
if someone interested in such solution i can describe a little detailed how to implement such features. |
|
Back to top |
|
djazzc Smarty n00b
Joined: 10 Aug 2009 Posts: 3
|
|
Back to top |
|
spinnaker Smarty Rookie
Joined: 01 Mar 2010 Posts: 6
|
Posted: Mon Mar 01, 2010 11:20 am Post subject: |
|
|
Hi all.
I have setup a smarty project for a web site that have to be localized by multilanguage text, so I have included the gettext functionality in Smarty by this plugin.
Ok I follow the instruction reported on the plugin readme file...but I have a problem.
When I access the web page from the browser I see this warning:
Code: | Warning: Smarty error: [in tu3_site_rbooks.tpl line 28]: syntax error: block function 't' is not implemented (Smarty_Compiler.class.php, line 720) in /home/testiusati3/public_html/site/smarty/Smarty.class.php on line 1093 |
for each line that has a tag defined by the block function for the translation functionality. Infact the translation of the text do not work.
I have googled the way to solve this warning but I have not found a way. Could you help me please...
Thanks. |
|
Back to top |
|
spinnaker Smarty Rookie
Joined: 01 Mar 2010 Posts: 6
|
Posted: Mon Mar 01, 2010 11:30 am Post subject: |
|
|
I am sorry I do not include some other informations about.
I think that I need the "smarty-translate" file or similar defined in the instruction:
Code: | $smarty->register_block('t', 'smarty-translate'); |
but in the archive file that I have download there is only:
Code: | tsmarty2c.php
smarty-gettext.php |
|
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Mon Mar 01, 2010 5:15 pm Post subject: |
|
|
Example:
Code: |
$smarty = new Smarty [...];
require('smarty-gettext.php');
$smarty->register_block('t', 'smarty-translate');
|
Did you have the require('smarty-gettext.php'); line? |
|
Back to top |
|
spinnaker Smarty Rookie
Joined: 01 Mar 2010 Posts: 6
|
Posted: Tue Mar 02, 2010 2:40 pm Post subject: |
|
|
Hi. Thanks for the replay.
I have notice that in the archive that I have downloaded from the plugin page there in not the file "block.t.php" needed. So I have googled a bit and I found it for download.
Now all things works great.
Thanks. |
|
Back to top |
|
emulienfou Smarty Rookie
Joined: 28 May 2010 Posts: 18
|
Posted: Sun Jun 06, 2010 10:19 am Post subject: |
|
|
Hello, i use this code http://smarty.incutio.com/?page=SmartyMultilanguageSupport for create my multilanguage site.
In my php file i have this code :
Code: | $tpl= new smartyML('eng');
$tpl->compile_dir = ROOT_DIR . '/cache/tpl';
$tpl->compile_check = true; |
In the André Rabold's code there is a varible "$path" to specifie the file language "by default : global.lng", but can i change $path variable ?
In this example , the two call doesn't work !!!
Code: | $smarty->language->setLocale() to change the language of your template
$smarty->loadTranslationTable() to load custom translation tables |
So how i can change $path value ????
Best regards[/code] |
|
Back to top |
|
emulienfou Smarty Rookie
Joined: 28 May 2010 Posts: 18
|
Posted: Sat Jun 12, 2010 4:25 pm Post subject: |
|
|
Can i use this style ($CONFIG['USERNAME'] = "Nom d'utilisateur" in lng files ???
And not USERNAME=Nom d'utilisateur
???
i suppose i need to modified foreach ($entries as $row) {} in ngLangue class
tanks for your help !!! |
|
Back to top |
|
flexin Smarty Rookie
Joined: 23 Feb 2010 Posts: 11
|
Posted: Wed Oct 06, 2010 7:19 am Post subject: |
|
|
Hi,
I tried reading the thread diagonally, so I hope I'm not re-posting a question before.
We have a system in place using smarty which indeed allows me to write {flexinTranslate CONTEXT='context' ITEM='translate_this'}
this will call a function which returns the translated value for the context and item from an array of strings which is being cached for optimal performance.
The major disadvantage of this approach is that for one template we often have dozens of strings to manage through our interface. So we came up with another solution, but I'm unable to finish it...
The idea is to have a template file per language:
template.tpl --> default
template.en.tpl
template.nl.tpl
In our code, we have our own template class which ionherits from the Smarty class, allowing me to override methods.
I tried overriding the fetch() method as follows:
Code: | function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false) {
$l = getTranslatedString(array("CONTEXT" => "SYSTEM", "ITEMSTRING" => "SYSTEM_LANG_CODE"));
if(parent::template_exists($resource_name . "." . $l)) {
return parent::fetch($resource_name . "." . $l, $cache_id, $compile_id, $display);
} else {
return parent::fetch($resource_name, $cache_id, $compile_id, $display);
}
} |
this works great, but guess what: as soon as we do an include of the file, the included file will be processed twice, which is of course giving errors if we have {literal}{{/literal} in the included file; the literal-tags are being removed, and the second parsing will result in a smarty error...
Is there anyone out here who might have tried something like this? |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Wed Oct 06, 2010 4:00 pm Post subject: |
|
|
You can make use of the undocumented feature that template_dir can be an array of folders which is scanned in the order of the elements.
Create a template folder for each language like templates_en, templates_nl etc. Store language specific templates under the standard name template.tpl in the corresponding folder.
Assuming you have the language code in $lang you can simply use
Code: | $smarty->template_dir=array("./templates_$lang",'./templates');
$smarty->compile_id=$lang;
$smarty->display('template.tpl');
|
Smarty will first look into the language specific folder. If it does not find a template there it will go to the default folder.
Setting a compile_id is necessary to keep the compiled files for each language separated.
It does automatically work also for included subtemplates. |
|
Back to top |
|
flexin Smarty Rookie
Joined: 23 Feb 2010 Posts: 11
|
Posted: Thu Oct 07, 2010 5:50 am Post subject: |
|
|
WOW!
I'm gonna try this immediately! What a wonderful feature!!!
I had no idea that this was possible!!!
Thank you so much - this will make my life great |
|
Back to top |
|
flexin Smarty Rookie
Joined: 23 Feb 2010 Posts: 11
|
Posted: Thu Nov 04, 2010 5:46 pm Post subject: |
|
|
by the way - just wanted to confirm that this was exactly what I needed - thank s |
|
Back to top |
|
TakingSides Smarty Rookie
Joined: 11 Dec 2010 Posts: 30
|
Posted: Fri Jan 28, 2011 3:59 pm Post subject: |
|
|
I personally believe the best way for multiple languages with Smarty is the precompile function.
Inside your generated/cache directories just create a new compile/cache directory per language.
Using a database to store your language texts, so it can be exported/imported via XML (for translation )
Secondly, you can set PHP's settings such as mb_internal_encoding(), locale() etc. and with MySQL, you can set the CHARSET of the database etc.
The databases...
Code: |
--
-- LANGUAGES
--
CREATE TABLE IF NOT EXISTS `pfx_languages` (
`la_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`la_name` VARCHAR(45) NOT NULL,
`la_charset` VARCHAR(45) NOT NULL,
`la_dbcharset` VARCHAR(45) NOT NULL,
`la_language` VARCHAR(45) NOT NULL,
`la_timezone` VARCHAR(45) NOT NULL,
`la_dbtimezone` VARCHAR(45) NOT NULL,
`la_mb_charset` VARCHAR(45) NOT NULL,
`la_date_format` VARCHAR(45) NOT NULL,
`la_time_format` VARCHAR(45) NOT NULL,
`la_datetime_format` VARCHAR(45) NOT NULL,
PRIMARY KEY (`la_id`),
UNQIUE `LANGNAME` (`la_name`)
) ENGINE=InnoDB AUTO_INCREMENT=1;
--
-- INSERT ENGLISH
--
INSERT INTO `pfx_languages` (`la_name`, `la_charset`, `la_dbcharset`, `la_language`, `la_timezone`, `la_dbtimezone`, `la_mb_charset`, `la_date_format`, `la_time_format`, `la_datetime_format`) VALUES
('English', 'utf-8', 'UTF8', 'en_GB', 'Europe/London', '+0:00', 'en', '%d/%m/%Y', '%H:%M', '%d/%m/%Y %H:%M');
--
-- LANGUAGE TEXT TABLE
--
CREATE TABLE IF NOT EXISTS `pfx_languages_text` (
`la_id` INT(11) UNSIGNED NOT NULL,
`lt_label` VARCHAR(100) NOT NULL,
`lt_text` BLOB NOT NULL,
PRIMARY KEY (`la_id`, `lt_label`)
) ENGINE=InnoDB;
--
-- INSERT ENGLISH WORDS
--
INSERT INTO `pfx_languages_text` VALUES (1, 'TTL_WELCOME_HEADING', 'Welcome!'),(1, 'TXT_WELCOME', 'Welcome, lorem ipsum dolor sit armet...');
|
So with Smarty's lovely precompile filter...
config.php
Code: |
<?php
define('DEVELOPER_MODE', false); // true will throw any warnings, or internal notices.
class Config {
// Variables / Constants
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static $langLocale;
private static $db, $sess, $smarty;
// Public Methods
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final public static function MySQL() {
if (!is_a(self::$db, 'MySQL')) {
self::$db = new MySQL();
self::$db->error_reporting = DEVELOPER_MODE;
}
return self::$db;
}
final public static function Session() {
if (!is_a(self::$sess, 'Session'))
self::$sess = new Session();
return self::$sess;
}
final public static function Smarty($area = 'web') {
if (!is_a(self::$smarty, 'Templates'))
self::$smarty = new Templates($area, true);
return self::$smarty;
}
}
Config::$langLocale = new stdClass;
$session = Config::Session();
$db = Config::MySQL();
// set-up the default language settings
if (!intval($session->getSession('myLanguageSettings')))
$session->setSession('myLanguageSettings', 1); // english = default language.
// fetch all language settings from database
$row = $db->qr(sprintf('SELECT * FROM pfx_languages WHERE la_id = %d', $session->getSession('myLanguageSettings')));
Config::$langLocale->name = $row['la_name'];
Config::$langLocale->html_charset = $row['la_charset'];
Config::$langLocale->db_charset = $row['la_dbcharset'];
Config::$langLocale->language = $row['la_language'];
Config::$langLocale->timezone = $row['la_timezone'];
Config::$langLocale->db_timezone = $row['la_dbtimezone'];
Config::$langLocale->mb_language = $row['la_mb_charset'];
Config::$langLocale->date_format = $row['la_date_format'];
Config::$langLocale->time_format = $row['la_time_format'];
Config::$langLocale->datetime_format = $row['la_datetime_format'];
// correctly append all language settings
header(sprintf('Content-Type: text/html; charset=%s', Config::$langLocale->html_charset));
setlocale(LC_ALL, Config::$langLocale->language);
date_default_timezone_set(Config::$langLocale->timezone);
mb_internal_encoding(strtoupper(Config::$langLocale->html_charset));
mb_language(Config::$langLocale->mb_language);
// standard mysql characterset/timezone settings.
//$db->set_charset(Config::$langLocale->db_charset);
//$db->set_timezone(Config::$langLocale->db_timezone);
|
class.templates_security.php
Code: |
<?php
class Templates_Security extends Smarty_Security {
public $php_functions = array('isset', 'empty', 'count', 'in_array', 'time', 'nl2br');
public $php_modifiers = array();
}
|
class.templates.php
Code: |
<?php
require_once ('lib/Smarty/Smarty.class.php');
final class Templates extends Smarty {
public function __construct($style) {
parent::__construct();
$session = Config::Session();
$this->_lang = $session->getSession('myLanguageSettings');
$this->enableSecurity('Templates_Security');
$this->template_dir = CONF_DIR_TMPL . $style;
$this->compile_dir = sprintf('%sSmarty/generated/%s/templates_c/%s', CONF_DIR_LIB, $style, Config::$langLocale->language);
if (!file_exists($this->compile_dir))
@mkdir($this->compile_dir);
$this->registerFilter(Smarty::FILTER_PRE, array($this, 'precompile_filter_language'));
$this->assign('Locale', Config::$langLocale);
}
public function precompile_filter_language($tmpl) {
$session = Config::Session();
$db = Config::MySQL();
$labels = array();
preg_match_all('~(/##(.*?)##/)~i', $tmpl, $labels);
foreach ($labels[max(array_keys($labels))] as $label) {
$t_replace = $db->qc(sprintf('
SELECT
lt_text
FROM
pfx_languages_text
WHERE
lt_label = %s
AND la_id = %d
',
$db->esc(trim($label)),
$session->getSession('myLanguageSettings')
));
$replacement = DEVELOPER_MODE ? (empty($t_replace) ? "[ MISSING:{$label}]" : $t_replace) : $t_replace;
$tmpl = stripslashes(str_ireplace("/##{$label}##/", $replacement, $tmpl));
}
return $tmpl;
}
}
|
Now the smarty, test.tpl
Code: |
<!DOCTYPE html>
<html>
<head>
<!-- stuff here -->
</head>
<body>
<h1>/## TTL_WELCOME_HEADING ##/</h1>
<p>/## TXT_WELCOME ##/</p>
<!-- dates are dynamic too, why? UK = D/M/Y, US = M/D/Y, EU = Y/M/D, etc. plus timezone corrections. -->
<p>{'2010-01-01 06:15:05'|date_format:$Locale->datetime_format}
</body>
</html>
|
Smarty will compile the languages and store them correctly, therefore you wont need to keep reading XML's or running Queries.
This is only an example, and is completely untested. Snippets from a Framework i'm working on. |
|
Back to top |
|
theseend Smarty n00b
Joined: 16 Apr 2011 Posts: 1
|
Posted: Sat Apr 16, 2011 11:13 am Post subject: smarty.incutio.com code and Smarty3 |
|
|
If you want Smarty3 to work with http://smarty.incutio.com/?page=SmartyMultilanguageSupport you have to alter the code for the classes to this:
Code: |
<?php
require('../libs/Smarty.class.php'); //adjust to the correct location
/**
* smarty_prefilter_i18n()
* This function takes the language file, and rips it into the template
* $GLOBALS['_NG_LANGUAGE_'] is not unset anymore
*
* @param $tpl_source
* @return
**/
function smarty_prefilter_i18n($tpl_source, &$smarty) {
if (!is_object($GLOBALS['_NG_LANGUAGE_'])) {
die("Error loading Multilanguage Support");
}
// load translations (if needed)
$GLOBALS['_NG_LANGUAGE_']->loadCurrentTranslationTable();
// Now replace the matched language strings with the entry in the file
return preg_replace_callback('/##(.+?)##/', '_compile_lang', $tpl_source);
}
/**
* _compile_lang
* Called by smarty_prefilter_i18n function it processes every language
* identifier, and inserts the language string in its place.
*
*/
function _compile_lang($key) {
return $GLOBALS['_NG_LANGUAGE_']->getTranslation($key[1]);
}
class smartyML extends Smarty {
var $language;
function __construct($locale="") {
parent::__construct();
// Multilanguage Support
// use $smarty->language->setLocale() to change the language of your template
// $smarty->loadTranslationTable() to load custom translation tables
$this->language = new ngLanguage($locale); // create a new language object
$GLOBALS['_NG_LANGUAGE_'] =$this->language;
$this->registerFilter('pre','smarty_prefilter_i18n');
}
function fetch($_smarty_tpl_file, $_smarty_cache_id = null, $_smarty_compile_id = null, $_smarty_parent = null, $_smarty_display = false) {
// We need to set the cache id and the compile id so a new script will be
// compiled for each language. This makes things really fast ;-)
$_smarty_compile_id = $this->language->getCurrentLanguage().'-'.$_smarty_compile_id;
$_smarty_cache_id = $_smarty_compile_id;
// Now call parent method
return parent::fetch( $_smarty_tpl_file, $_smarty_cache_id, $_smarty_compile_id, $_smarty_parent, true);
}
/**
* test to see if valid cache exists for this template
*
* @param string $tpl_file name of template file
* @param string $cache_id
* @param string $compile_id
* @return string|false results of {@link _read_cache_file()}
*/
function is_cached($tpl_file, $cache_id = null, $compile_id = null) {
if (!$this->caching)
return false;
if (!isset($compile_id)) {
$compile_id = $this->language->getCurrentLanguage().'-'.$this->compile_id;
$cache_id = $compile_id;
return parent::is_cached($tpl_file, $cache_id, $compile_id);
}
}
}
class ngLanguage {
var $_translationTable; // currently loaded translation table
var $_supportedLanguages; // array of all supported languages
var $_defaultLocale; // the default language
var $_currentLocale; // currently set locale
var $_currentLanguage; // currently loaded language
var $_languageTable; // array of language to file associations
var $_loadedTranslationTables; // array of all loaded translation tables
function ngLanguage($locale="") {
$this->_languageTable = Array(
"de" => "deu",
"en" => "eng",
"en-us" => "eng",
"en-gb" => "eng",
"nl" => "nld",
"zh" => "chn",
"dk" => "dnk",
"es" => "esp",
"fr" => "fra",
"it" => "ita",
"no" => "nor",
"pl" => "pol",
"pt" => "prt",
"ru" => "rus",
"sv" => "swe",
"tr" => "tur"
); // to be continued ...
$this->_translationTable = Array();
$this->_loadedTranslationTables = Array();
foreach ($this->_languageTable as $lang)
$this->_translationTable[$lang] = Array();
$this->_defaultLocale = 'en';
if (empty($locale))
$locale = $this->getHTTPAcceptLanguage();
$this->setCurrentLocale($locale);
}
function getAvailableLocales() {
return array_keys($this->_languageTable);
}
function getAvailableLanguages() {
return array_unique(array_values($this->_languageTable));
}
function getCurrentLanguage() {
return $this->_currentLanguage;
}
function setCurrentLanguage($language) {
$this->_currentLanguage = $language;
}
function getCurrentLocale() {
return $this->_currentLocale;
}
function setCurrentLocale($locale) {
$language = $this->_languageTable[$locale];
if (empty($language)) {
die ("LANGUAGE Error: Unsupported locale '$locale'");
}
$this->_currentLocale = $locale;
return $this->setCurrentLanguage($language);
}
function getDefaultLocale() {
return $this->_defaultLocale;
}
function getHTTPAcceptLanguage() {
$langs = explode(';', $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
$locales = $this->getAvailableLocales();
foreach ($langs as $value_and_quality) {
// Loop through all the languages, to see if any match our supported ones
$values = explode(',', $value_and_quality);
foreach ($values as $value) {
if (in_array($value, $locales)){
// If found, return the language
return $value;
}
}
}
// If we can't find a supported language, we use the default
return $this->getDefaultLocale();
}
// Warning: parameter positions are changed!
function _loadTranslationTable($locale, $path='') {
if (empty($locale))
$locale = $this->getDefaultLocale();
$language = $this->_languageTable[$locale];
if (empty($language)) {
die ("LANGUAGE Error: Unsupported locale '$locale'");
}
if (!is_array($this->_translationTable[$language])) {
die ("LANGUAGE Error: Language '$language' not available");
}
if(empty($path))
$path = 'languages/'.$this->_languageTable[$locale].'/global.lng';
if (isset($this->_loadedTranslationTables[$language])) {
if (in_array($path, $this->_loadedTranslationTables[$language])) {
// Translation table was already loaded
return true;
}
}
if (file_exists($path)) {
$entries = file($path);
$this->_translationTable[$language][$path] = Array();
$this->_loadedTranslationTables[$language][] = $path;
foreach ($entries as $row) {
if (substr(ltrim($row),0,2) == '//') // ignore comments
continue;
$keyValuePair = explode('=',$row);
// multiline values: the first line with an equal sign '=' will start a new key=value pair
if(sizeof($keyValuePair) == 1) {
$this->_translationTable[$language][$path][$key] .= ' ' . chop($keyValuePair[0]);
continue;
}
$key = trim($keyValuePair[0]);
$value = $keyValuePair[1];
if (!empty($key)) {
$this->_translationTable[$language][$path][$key] = chop($value);
}
}
return true;
}
return false;
}
// Warning: parameter positions are changed!
function _unloadTranslationTable($locale, $path) {
$language = $this->_languageTable[$locale];
if (empty($language)) {
die ("LANGUAGE Error: Unsupported locale '$locale'");
}
unset($this->_translationTable[$language][$path]);
foreach($this->_loadedTranslationTables[$language] as $key => $value) {
if ($value == $path) {
unset($this->_loadedTranslationTables[$language][$key]);
break;
}
}
return true;
}
function loadCurrentTranslationTable() {
$this->_loadTranslationTable($this->getCurrentLocale());
}
// Warning: parameter positions are changed!
function loadTranslationTable($locale, $path) {
// This method is only a placeholder and wants to be overwritten by YOU! ;-)
// Here's a example how it could look:
if (empty($locale)) {
// Load default locale of no one has been specified
$locale = $this->getDefaultLocale();
}
// Select corresponding language
$language = $this->_languageTable[$locale];
// Set path and filename of the language file
$path = "languages/$language/$path.lng";
// _loadTranslationTable() does the rest
$this->_loadTranslationTable($locale, $path);
}
// Warning: parameter positions are changed!
function unloadTranslationTable($locale, $path) {
// This method is only a placeholder and wants to be overwritten by YOU! ;-)
$this->_unloadTranslationTable($locale, $path);
}
function getTranslation($key) {
$trans = $this->_translationTable[$this->_currentLanguage];
if (is_array($trans)) {
foreach ($this->_loadedTranslationTables[$this->_currentLanguage] as $table) {
if (isset($trans[$table][$key])) {
return $trans[$table][$key];
}
}
}
return $key;
}
}
?>
|
Hope this helps. |
|
Back to top |
|
jebediah Smarty Rookie
Joined: 28 Jan 2012 Posts: 16
|
Posted: Sat Dec 01, 2012 3:42 pm Post subject: smarty-gettext |
|
|
Hi there,
I found the i18n support of Smarty (not per see, but as the whole process) a bit lacking. That's why I've implemented and released a smarty-gettext project that enables full i18n support for Smarty, including the creation of po files, etc.
Have a look here: http://code.google.com/p/smarty-gettext/
any feedback, etc. would be very much appreciated!
Bests,
Charly |
|
Back to top |
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|
|