在应用程序中翻译动态文本的便捷方法是使用占位符,如下所示:
$message = 'Hello I am {firstname}';
$translation = strtr($message, array('{firstname}', 'John'));
但是我希望它更具动态性,只需传递一个完整的person对象,应用程序的用户就可以随意使用他认为合适的对象。
因此,给定以下对象:
$customer = new tstCustomer();
$customer->firstname = 'testfirst';
$customer->lastname = 'testlast';
$customer->email = 'testemail';
class tstCustomer
{
public $firstname;
public $lastname;
public $email;
public function __construct(){}
}
我希望用户能够创建这样的可翻译字符串:
$message = '{greetings} I am {customer->firstname} {customer->lastname} and my email address is {customer->email} {customer->notexisting}.';
我现在只需要传递$customer
对象,而不需要传递各种单独的属性(及其可能的占位符)。这也提供了对象遍历的可能性。
echo translation($message, array('{greetings}' => 'Hello World', '{customer}' => $customer));
// Output:
// Hello World I am testfirst testlast and my email address is testemail .
我编写了以下函数来完成上述任务:
function translation($message, $placeholders = array())
{
// catch all notices/warnings/errors due to non existent attributes
$backupHandler = set_error_handler('strtrErrorHandler');
foreach($placeholders as $placeholder => $value)
{
if(gettype($value) === 'string')
{
$message = strtr($message, array($placeholder => $value));
continue;
}
if(gettype($value) !== 'object')
continue;
$trimmed_placeholder = trim($placeholder, '{}');
$regex = '/\{'.$trimmed_placeholder.'[\-\>[\w]*]*\}/';
$matches = array();
preg_match_all($regex, $message, $matches);
// $matches should look like:
// array(1) { [0]=> array(3) { [0]=> string(21) "{customer->firstname}" [1]=> string(20) "{customer->lastname}" [2]=> string(17) "{customer->email}" } }
if(!isset($matches[0]))
continue;
foreach($matches[0] as $match)
{
$stringpath = trim($match, '{}');
$traversal = substr($stringpath, strlen($trimmed_placeholder)+2);
try
{
$message = strtr($message, array($match => $value->{$traversal}));
}
catch(Exception $e)
{
// replace the placeholder with empty string
$message = strtr($message, array($match => ''));
}
}
} // foreach $placeholders
set_error_handler($backupHandler);
return $message;
}
// catch all and convert to a catchable Exception
function strtrErrorHandler($severity, $message, $filename, $lineno) {
Yii::log($message, 'error', 'backend.test.index');
throw new Exception('');
}
现在,我的问题: