* @param string $text
* the original string.
* @param array $params
- * the params of the translation (if any).
- *
+ * The params of the translation (if any).
+ * - domain: string|array a list of translation domains to search (in order)
+ * - context: string
* @return string
* the translated string
*/
return $text;
}
+ $plural = $count = NULL;
if (isset($params['plural'])) {
$plural = $params['plural'];
unset($params['plural']);
$context = NULL;
}
+ if (isset($params['domain'])) {
+ $domain = $params['domain'];
+ unset($params['domain']);
+ }
+ else {
+ $domain = NULL;
+ }
+
+ if (!empty($domain)) {
+ // It might be prettier to cast to an array, but this is high-traffic stuff.
+ if (is_array($domain)) {
+ foreach ($domain as $d) {
+ $candidate = $this->crm_translate_raw($text, $d, $count, $plural, $context);
+ if ($candidate != $text) {
+ $text = $candidate;
+ break;
+ }
+ }
+ }
+ else {
+ $text = $this->crm_translate_raw($text, $domain, $count, $plural, $context);
+ }
+ }
+ else {
+ $text = $this->crm_translate_raw($text, NULL, $count, $plural, $context);
+ }
+
+ // replace the numbered %1, %2, etc. params if present
+ if (count($params)) {
+ $text = $this->strarg($text, $params);
+ }
+
+ // escape SQL if we were asked for it
+ if (isset($escape) and ($escape == 'sql')) {
+ $text = CRM_Core_DAO::escapeString($text);
+ }
+
+ // escape for JavaScript (if requested)
+ if (isset($escape) and ($escape == 'js')) {
+ $text = addcslashes($text, "'");
+ }
+
+ return $text;
+ }
+
+ /**
+ * Lookup the raw translation of a string (without any extra escaping or interpolation).
+ *
+ * @param string $text
+ * @param string|NULL $domain
+ * @param int|NULL $count
+ * @param string $plural
+ * @param string $context
+ * @return mixed|string|translated
+ */
+ protected function crm_translate_raw($text, $domain, $count, $plural, $context) {
// gettext domain for extensions
$domain_changed = FALSE;
- if (!empty($params['domain']) && $this->_phpgettext) {
- if ($this->setGettextDomain($params['domain'])) {
+ if (!empty($domain) && $this->_phpgettext) {
+ if ($this->setGettextDomain($domain)) {
$domain_changed = TRUE;
}
}
}
}
- // replace the numbered %1, %2, etc. params if present
- if (count($params)) {
- $text = $this->strarg($text, $params);
- }
-
- // escape SQL if we were asked for it
- if (isset($escape) and ($escape == 'sql')) {
- $text = CRM_Core_DAO::escapeString($text);
- }
-
- // escape for JavaScript (if requested)
- if (isset($escape) and ($escape == 'js')) {
- $text = addcslashes($text, "'");
- }
-
if ($domain_changed) {
$this->setGettextDomain('civicrm');
}
* relative weight within a given region.
* @param string $region
* location within the file; 'html-header', 'page-header', 'page-footer'.
- * @param $translate , whether to parse this file for strings enclosed in ts()
+ * @param bool|string $translate
+ * Whether to load translated strings for this file. Use one of:
+ * - FALSE: Do not load translated strings.
+ * - TRUE: Load translated strings. Use the $ext's default domain.
+ * - string: Load translated strings. Use a specific domain.
*
* @return CRM_Core_Resources
*/
public function addScriptFile($ext, $file, $weight = self::DEFAULT_WEIGHT, $region = self::DEFAULT_REGION, $translate = TRUE) {
if ($translate) {
- // For each extension, maintain one cache record which
- // includes parsed (translatable) strings for all its files.
- $this->addString($this->strings->get($ext, $this->getPath($ext, $file), 'text/javascript'));
+ $domain = ($translate === TRUE) ? $ext : $translate;
+ $this->addString($this->strings->get($domain, $this->getPath($ext, $file), 'text/javascript'), $domain);
}
// Look for non-minified version if we are in debug mode
if (CRM_Core_Config::singleton()->debug && strpos($file, '.min.js') !== FALSE) {
* And from javascript access it at CRM.myNamespace.myString
*
* @param string|array $text
+ * @param string|NULL $domain
* @return CRM_Core_Resources
*/
- public function addString($text) {
+ public function addString($text, $domain = 'civicrm') {
foreach ((array) $text as $str) {
- $translated = ts($str);
+ $translated = ts($str, array(
+ 'domain' => ($domain == 'civicrm') ? NULL : array($domain, NULL),
+ ));
+
// We only need to push this string to client if the translation
// is actually different from the original
if ($translated != $str) {
- $this->addSetting(array('strings' => array($str => $translated)));
+ $bucket = $domain == 'civicrm' ? 'strings' : 'strings::' . $domain;
+ $this->addSetting(array(
+ $bucket => array($str => $translated),
+ ));
}
}
return $this;
*/
function ts(text, params) {
"use strict";
- text = CRM.strings[text] || text;
+ var d = (params && params.domain) ? ('strings::' + params.domain) : null;
+ if (d && CRM[d] && CRM[d][text]) {
+ text = CRM[d][text];
+ }
+ else if (CRM['strings'][text]) {
+ text = CRM['strings'][text];
+ }
if (typeof(params) === 'object') {
for (var i in params) {
if (typeof(params[i]) === 'string' || typeof(params[i]) === 'number') {
module('Translation');
test('ts()', function() {
+ equal(ts('Lexicographical enigma'), "Lexicographical enigma", "If a string has no translation, pass it through");
equal(ts('One, two, three'), "Un, deux, trois", "We expect translations to work");
+ equal(ts('I know'), "Je sais", "We expect translations to work");
});
test('CRM.ts()', function() {
(function (ts) {
- equal(ts('One, two, three'), "Un, deux, trois", "We expect translations to work");
+ equal(ts('Lexicographical enigma'), "Lexicographical enigma", "If a string has no translation, pass it through");
+ equal(ts('One, two, three'), "Un, deux, trois", "Fallback to translations from default domain");
+ equal(ts('I know'), "Je connais", "We expect translations to work");
}(CRM.ts('org.example.foo')));
});
<?php
CRM_Core_Resources::singleton()->addSetting(array(
- 'strings' => array('One, two, three' => 'Un, deux, trois'),
+ 'strings' => array(
+ 'One, two, three' => 'Un, deux, trois',
+ 'I know' => 'Je sais',
+ ),
+ 'strings::org.example.foo' => array(
+ 'I know' => 'Je connais',
+ ),
)
);
// CRM_Core_Resources::singleton()->addScriptFile(...);