mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ENHANCEMENT Backwards compatible $priority parameter for i18n::_t(): Allow numeric arrays as parameters, as well as %s style replacements with a named parameter map (easier transition to new system with existing translation strings)
This commit is contained in:
parent
2288d80c30
commit
e949b6f2b0
@ -455,13 +455,36 @@ and was rarely used in practice - so we moved it to a "[homepagefordomain](https
|
||||
|
||||
### New syntax for translatable _t functions [i18n-t]###
|
||||
|
||||
You can now call the _t() function in both templates and code with a namespace and string to translate, as well as a
|
||||
comment and injection array. Note that the proxity arguement to _t is no longer supported.
|
||||
You can now call the `_t()` function in both templates and code with a namespace and string to translate, as well as a comment and injection array.
|
||||
|
||||
The new syntax supports injecting variables into the translation. For example:
|
||||
|
||||
:::php
|
||||
_t('i18nTestModule.INJECTIONS2', "Hello {name} {greeting}", array("name"=>"Paul", "greeting"=>"good you are here"));
|
||||
_t(
|
||||
'i18nTestModule.INJECTIONS2',
|
||||
"Hello {name} {greeting}",
|
||||
array("name"=>"Paul", "greeting"=>"good you are here")
|
||||
);
|
||||
|
||||
We've written the injection logic in a way that keeps backwards compatible with
|
||||
existing translations. This means that you can migrate from `sprintf()` to the new injection
|
||||
API incrementally. The following to "mixed usage" examples still work, although they
|
||||
don't get the advantage of flexible ordering in substitutions.
|
||||
|
||||
:::php
|
||||
_t(
|
||||
'i18nTestModule.INJECTIONS2',
|
||||
"Hello {name} {greeting}",
|
||||
array("Paul", "good you are here")
|
||||
);
|
||||
_t(
|
||||
'i18nTestModule.INJECTIONS2',
|
||||
"Hello %s, %s",
|
||||
array("name"=>"Paul", "greeting"=>"good you are here")
|
||||
);
|
||||
|
||||
Of course, you can keep using `sprintf()` for variable substitution in your own code.
|
||||
|
||||
|
||||
### Default translation source in YML instead of PHP $lang array, using Zend_Translate {#zend-translate}
|
||||
|
||||
|
@ -180,9 +180,10 @@ Therefore, the following would be a valid use in templates:
|
||||
|
||||
Using SS templating variables in the translatable string (e.g. $Author, $Date..) is not currently supported.
|
||||
|
||||
### Injection-support
|
||||
### Injection Support
|
||||
|
||||
Variable injection in _t allows us to dynamically replace parts of a translated string, e.g. by a username or a page-title.
|
||||
Variable injection in `_t()` allows us to dynamically replace parts of a translated string, e.g. by a username or a page-title. The named parameters also allow flexible ordering of placeholders,
|
||||
which might vary depending on the used language.
|
||||
|
||||
:::php
|
||||
// in PHP-file
|
||||
@ -196,6 +197,10 @@ Variable injection in _t allows us to dynamically replace parts of a translated
|
||||
// in SS-template ($Name must be available in the current template-scope)
|
||||
<%t MYPROJECT.INJECTIONS "Hello {name} {greeting}" name="$Name" greeting="good to see you" %>
|
||||
|
||||
Note that you can still use `sprintf()` wrapped around a `_t()` call
|
||||
for your substitutions. In contrast to `sprintf()`, our API has a more translator friendly
|
||||
placeholder syntax, as well as more graceful fallback if not all placeholders are found
|
||||
(an outdated translation with less placeholders will throw a notice rather than a fatal error).
|
||||
|
||||
## Collecting text
|
||||
|
||||
|
@ -1512,9 +1512,36 @@ class i18n extends Object implements TemplateGlobalProvider {
|
||||
}
|
||||
|
||||
// inject the variables from injectionArray (if present)
|
||||
if ($injectionArray && count($injectionArray) > 0) {
|
||||
foreach($injectionArray as $variable => $injection) {
|
||||
$returnValue = str_replace('{'.$variable.'}', $injection, $returnValue);
|
||||
if($injectionArray) {
|
||||
$regex = '/\{[\w\d]*\}/i';
|
||||
if(!preg_match($regex, $returnValue)) {
|
||||
// Legacy mode: If no injection placeholders are found,
|
||||
// replace sprintf placeholders in fixed order.
|
||||
$returnValue = vsprintf($returnValue, array_values($injectionArray));
|
||||
} else if(!ArrayLib::is_associative($injectionArray)) {
|
||||
// Legacy mode: If injection placeholders are found,
|
||||
// but parameters are passed without names, replace them in fixed order.
|
||||
$returnValue = preg_replace_callback(
|
||||
$regex,
|
||||
function($matches) use(&$injectionArray) {
|
||||
return $injectionArray ? array_shift($injectionArray) : '';
|
||||
},
|
||||
$returnValue
|
||||
);
|
||||
} else {
|
||||
// Standard placeholder replacement with named injections and variable order.
|
||||
foreach($injectionArray as $variable => $injection) {
|
||||
$placeholder = '{'.$variable.'}';
|
||||
$returnValue = str_replace($placeholder, $injection, $returnValue, $count);
|
||||
if(!$count) {
|
||||
SS_Log::log(sprintf(
|
||||
"Couldn't find placeholder '%s' in translation string '%s' (id: '%s')",
|
||||
$placeholder,
|
||||
$returnValue,
|
||||
$entity
|
||||
), SS_Log::NOTICE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,8 @@ class i18nTest extends SapphireTest {
|
||||
|
||||
i18n::get_translator('core')->getAdapter()->addTranslation(array(
|
||||
'i18nTestModule.NEWMETHODSIG' => 'TRANS New _t method signature test',
|
||||
'i18nTestModule.INJECTIONS' => 'TRANS Hello {name} {greeting}. But it is late, {goodbye}'
|
||||
'i18nTestModule.INJECTIONS' => 'TRANS Hello {name} {greeting}. But it is late, {goodbye}',
|
||||
'i18nTestModule.INJECTIONSLEGACY' => 'TRANS Hello %s %s. But it is late, %s',
|
||||
), 'en_US');
|
||||
|
||||
$entity = "i18nTestModule.INJECTIONS";
|
||||
@ -287,6 +288,24 @@ class i18nTest extends SapphireTest {
|
||||
$translated, "Testing a translation with just entity and injection array"
|
||||
);
|
||||
|
||||
$translated = i18n::_t(
|
||||
'i18nTestModule.INJECTIONSLEGACY', // has %s placeholders
|
||||
array("name"=>"Cat", "greeting2"=>"meow", "goodbye"=>"meow")
|
||||
);
|
||||
$this->assertContains(
|
||||
"TRANS Hello Cat meow. But it is late, meow",
|
||||
$translated, "Testing sprintf placeholders with named injections"
|
||||
);
|
||||
|
||||
$translated = i18n::_t(
|
||||
'i18nTestModule.INJECTIONS', // has {name} placeholders
|
||||
array("Cat", "meow", "meow")
|
||||
);
|
||||
$this->assertContains(
|
||||
"TRANS Hello Cat meow. But it is late, meow",
|
||||
$translated, "Testing named injection placeholders with unnamed injections"
|
||||
);
|
||||
|
||||
i18n::set_locale($oldLocale);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user