I'm adapting an existing application to support several languages and I'd like to implement pseudolocalization, i.e. make localized strings:
<?php echo h(__('Edit program settings')); ?>
... stand out:
[!!! εÐiţ Þr0ģЯãm səTτıИğ§ !!!]
... so I can quickly spot omissions and detect potential layout problems.
Unless I'm wrong the feature is not builtin and there aren't third-party plugins. What are my chances?
I feel a sensible path would be to extend I18n
and overwrite I18n::translate()
. However I'm not specially familiar with CakePHP internals and I'm not sure about how to make __()
and family use my extended class.
On the other side, functions in lib\Cake\basics.php
are wrapped in function_exists()
calls so I guess I could write my own versions...
I'd welcome any suggestion.
The ideal technique would be to be able to define a custom class:
class CustomI18n extends I18n {
public static function translate($singular, $plural = null, $domain = null, $category = 6, $count = null, $language = null) {
}
}
… and instruct CakePHP to use my custom class rather than the original. That would be coherent with e.g. the way view helpers work.
Unfortunately, I don't think it can't be done¹ because $this->Html
inside a view is a dynamic property but __()
contains a hard-coded class name: I18n::translate($singular)
.
¹ Yes, almost everything can be done. You know what I mean :)
Since it's just a helper tool that's not meant for Production, you can always resort to a quick and dirty hack not really specific to CakePHP:
Rewrite into a file of your choice the functions from lib\Cake\basics.php
you're interested in, typically the ones that start with underscore: __()
, _n()
, ...
function __($singular, $args = null) {
if (!$singular) {
return;
}
$singular = pseudotranslation($singular); // <---------------------
App::uses('I18n', 'I18n');
$translated = I18n::translate($singular);
if ($args === null) {
return $translated;
} elseif (!is_array($args)) {
$args = array_slice(func_get_args(), 1);
}
return vsprintf($translated, $args);
}
Make sure you don't break vsprintf
codes.
Use auto_prepend_file to load the file before CakePHP startup begins. Ideally, set it on in your development box.
This has the advantage of being unobtrusive. You can enable or disable auto_prepend_file
quite easily or you can take care of that in your prepended script.
Alternatively, CakePHP allows to override most classes so you could copy /lib/Cake/I18n/I18n.php
as /app/Lib/I18n/I18n.php
and tweak I18n::translate()
to your liking. However I find this less convenient: you still have to maintain a custom copy of a system file if you upgrade CakePHP and there's no simple mechanism to disable pseudolocalisation on runtime since CakePHP will always use the file when it's present.