Commit 28b2f098 authored by Dries's avatar Dries
Browse files

- Patch #334283 by Damien Tournoud, andypost, Freso et al: add context to t()...

- Patch #334283 by Damien Tournoud, andypost, Freso et al: add context to t() to help deal with ambigious strings (and improved the locale APIs a bit). Example: May is both a short month name as a long month name in English, but not necessarily in other languages.
parent ece9032a
......@@ -123,6 +123,8 @@ Drupal 7.0, xxxx-xx-xx (development version)
with other blocks in the same region.
* Blocks can now return structured arrays for later rendering just
like page callbacks.
- Translation system
* The translation system now supports message context (msgctxt).
- Upgraded the core JavaScript library to jQuery version 1.3.2.
- Upgraded the jQuery Forms library to 2.21.
......
......@@ -1126,37 +1126,44 @@ function fix_gpc_magic() {
* - @variable: escape plain text to HTML (check_plain)
* - %variable: escape text and theme as a placeholder for user-submitted
* content (check_plain + theme_placeholder)
* @param $langcode
* Optional language code to translate to a language other than what is used
* to display the page.
* @param $options
* An associative array of additional options, with the following keys:
* - 'langcode' (default to the current language) The language code to
* translate to a language other than what is used to display the page.
* - 'context' (default to the empty context) The context the source string
* belongs to.
* @return
* The translated string.
*/
function t($string, $args = array(), $langcode = NULL) {
function t($string, array $args = array(), array $options = array()) {
global $language;
$custom_strings = &drupal_static(__FUNCTION__);
if (!isset($langcode)) {
$langcode = isset($language->language) ? $language->language : 'en';
// Merge in default.
if (empty($options['langcode'])) {
$options['langcode'] = isset($language->language) ? $language->language : 'en';
}
if (empty($options['context'])) {
$options['context'] = '';
}
// First, check for an array of customized strings. If present, use the array
// *instead of* database lookups. This is a high performance way to provide a
// handful of string replacements. See settings.php for examples.
// Cache the $custom_strings variable to improve performance.
if (!isset($custom_strings[$langcode])) {
$custom_strings[$langcode] = variable_get('locale_custom_strings_' . $langcode, array());
if (!isset($custom_strings[$options['langcode']])) {
$custom_strings[$options['langcode']] = variable_get('locale_custom_strings_' . $options['langcode'], array());
}
// Custom strings work for English too, even if locale module is disabled.
if (isset($custom_strings[$langcode][$string])) {
$string = $custom_strings[$langcode][$string];
if (isset($custom_strings[$options['langcode']][$options['context']][$string])) {
$string = $custom_strings[$options['langcode']][$options['context']][$string];
}
// Translate with locale module if enabled.
// We don't use drupal_function_exists() here, because it breaks the testing
// framework if the locale module is enabled in the parent site (we cannot
// unload functions in PHP).
elseif (module_exists('locale') && $langcode != 'en') {
$string = locale($string, $langcode);
elseif (module_exists('locale') && $options['langcode'] != 'en') {
$string = locale($string, $options['context'], $options['langcode']);
}
if (empty($args)) {
return $string;
......@@ -1711,34 +1718,37 @@ function format_xml_elements($array) {
* content (check_plain + theme_placeholder)
* Note that you do not need to include @count in this array.
* This replacement is done automatically for the plural case.
* @param $langcode
* Optional language code to translate to a language other than
* what is used to display the page.
* @param $options
* An associative array of additional options, with the following keys:
* - 'langcode' (default to the current language) The language code to
* translate to a language other than what is used to display the page.
* - 'context' (default to the empty context) The context the source string
* belongs to.
* @return
* A translated string.
*/
function format_plural($count, $singular, $plural, $args = array(), $langcode = NULL) {
function format_plural($count, $singular, $plural, array $args = array(), array $options = array()) {
$args['@count'] = $count;
if ($count == 1) {
return t($singular, $args, $langcode);
return t($singular, $args, $options);
}
// Get the plural index through the gettext formula.
$index = (function_exists('locale_get_plural')) ? locale_get_plural($count, $langcode) : -1;
$index = (function_exists('locale_get_plural')) ? locale_get_plural($count, isset($options['langcode']) ? $options['langcode'] : NULL) : -1;
// Backwards compatibility.
if ($index < 0) {
return t($plural, $args, $langcode);
return t($plural, $args, $options);
}
else {
switch ($index) {
case "0":
return t($singular, $args, $langcode);
return t($singular, $args, $options);
case "1":
return t($plural, $args, $langcode);
return t($plural, $args, $options);
default:
unset($args['@count']);
$args['@count[' . $index . ']'] = $count;
return t(strtr($plural, array('@count' => '@count[' . $index . ']')), $args, $langcode);
return t(strtr($plural, array('@count' => '@count[' . $index . ']')), $args, $options);
}
}
}
......@@ -1777,19 +1787,19 @@ function parse_size($size) {
*/
function format_size($size, $langcode = NULL) {
if ($size < DRUPAL_KILOBYTE) {
return format_plural($size, '1 byte', '@count bytes', array(), $langcode);
return format_plural($size, '1 byte', '@count bytes', array(), array('langcode' => $langcode));
}
else {
$size = $size / DRUPAL_KILOBYTE; // Convert bytes to kilobytes.
$units = array(
t('@size KB', array(), $langcode),
t('@size MB', array(), $langcode),
t('@size GB', array(), $langcode),
t('@size TB', array(), $langcode),
t('@size PB', array(), $langcode),
t('@size EB', array(), $langcode),
t('@size ZB', array(), $langcode),
t('@size YB', array(), $langcode),
t('@size KB', array(), array('langcode' => $langcode)),
t('@size MB', array(), array('langcode' => $langcode)),
t('@size GB', array(), array('langcode' => $langcode)),
t('@size TB', array(), array('langcode' => $langcode)),
t('@size PB', array(), array('langcode' => $langcode)),
t('@size EB', array(), array('langcode' => $langcode)),
t('@size ZB', array(), array('langcode' => $langcode)),
t('@size YB', array(), array('langcode' => $langcode)),
);
foreach ($units as $unit) {
if (round($size, 2) >= DRUPAL_KILOBYTE) {
......@@ -1830,7 +1840,7 @@ function format_interval($timestamp, $granularity = 2, $langcode = NULL) {
foreach ($units as $key => $value) {
$key = explode('|', $key);
if ($timestamp >= $value) {
$output .= ($output ? ' ' : '') . format_plural(floor($timestamp / $value), $key[0], $key[1], array(), $langcode);
$output .= ($output ? ' ' : '') . format_plural(floor($timestamp / $value), $key[0], $key[1], array(), array('langcode' => $langcode));
$timestamp %= $value;
$granularity--;
}
......@@ -1839,7 +1849,7 @@ function format_interval($timestamp, $granularity = 2, $langcode = NULL) {
break;
}
}
return $output ? $output : t('0 sec', array(), $langcode);
return $output ? $output : t('0 sec', array(), array('langcode' => $langcode));
}
/**
......@@ -1908,13 +1918,13 @@ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NUL
for ($i = 0; $i < $max; $i++) {
$c = $format[$i];
if (strpos('AaeDlMT', $c) !== FALSE) {
$date .= t(date_format($date_time, $c), array(), $langcode);
$date .= t(date_format($date_time, $c), array(), array('langcode' => $langcode));
}
elseif ($c == 'F') {
// Special treatment for long month names: May is both an abbreviation
// and a full month name in English, but other languages have
// different abbreviations.
$date .= trim(t('!long-month-name ' . date_format($date_time, $c), array('!long-month-name' => ''), $langcode));
$date .= t(date_format($date_time, $c), array(), array('context' => 'Long month name', 'langcode' => $langcode));
}
elseif (strpos('BcdGgHhIijLmNnOoPSstUuWwYyZz', $c) !== FALSE) {
$date .= date_format($date_time, $c);
......
......@@ -883,31 +883,36 @@ function locale_translate_export_po_form_submit($form, &$form_state) {
*/
function locale_translate_edit_form(&$form_state, $lid) {
// Fetch source string, if possible.
$source = db_query('SELECT source, textgroup, location FROM {locales_source} WHERE lid = :lid', array(':lid' => $lid))->fetchObject();
$source = db_query('SELECT source, context, textgroup, location FROM {locales_source} WHERE lid = :lid', array(':lid' => $lid))->fetchObject();
if (!$source) {
drupal_set_message(t('String not found.'), 'error');
drupal_goto('admin/international/translate/translate');
}
// Add original text to the top and some values for form altering.
$form = array(
'original' => array(
'#type' => 'item',
'#title' => t('Original text'),
'#markup' => check_plain(wordwrap($source->source, 0)),
),
'lid' => array(
'#type' => 'value',
'#value' => $lid
),
'textgroup' => array(
'#type' => 'value',
'#value' => $source->textgroup,
),
'location' => array(
'#type' => 'value',
'#value' => $source->location
),
$form['original'] = array(
'#type' => 'item',
'#title' => t('Original text'),
'#markup' => check_plain(wordwrap($source->source, 0)),
);
if (!empty($source->context)) {
$form['context'] = array(
'#type' => 'item',
'#title' => t('Context'),
'#markup' => check_plain($source->context),
);
}
$form['lid'] = array(
'#type' => 'value',
'#value' => $lid
);
$form['textgroup'] = array(
'#type' => 'value',
'#value' => $source->textgroup,
);
$form['location'] = array(
'#type' => 'value',
'#value' => $source->location
);
// Include default form controls with empty values for all languages.
......@@ -1035,7 +1040,7 @@ function locale_translate_edit_form_submit($form, &$form_state) {
* String deletion confirmation page.
*/
function locale_translate_delete_page($lid) {
if ($source = db_query('SELECT * FROM {locales_source} WHERE lid = :lid', array(':lid' => $lid))->fetchObject()) {
if ($source = db_query('SELECT lid, source FROM {locales_source} WHERE lid = :lid', array(':lid' => $lid))->fetchObject()) {
return drupal_get_form('locale_translate_delete_form', $source);
}
else {
......@@ -1287,8 +1292,26 @@ function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group =
$current["msgid"] = $quoted;
$context = "MSGID";
}
elseif (!strncmp("msgctxt", $line, 7)) {
if ($context == "MSGSTR") { // End current entry, start a new one
_locale_import_one_string($op, $current, $mode, $lang, $file, $group);
$current = array();
}
elseif (!empty($current["msgctxt"])) { // Already in this context? Parse error
_locale_import_message('The translation file %filename contains an error: "msgctxt" is unexpected on line %line.', $file, lineno);
return FALSE;
}
$line = trim(substr($line, 7));
$quoted = _locale_import_parse_quoted($line);
if ($quoted === FALSE) {
_locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
return FALSE;
}
$current["msgctxt"] = $quoted;
$context = "MSGCTXT";
}
elseif (!strncmp("msgstr[", $line, 7)) {
if (($context != "MSGID") && ($context != "MSGID_PLURAL") && ($context != "MSGSTR_ARR")) { // Must come after msgid, msgid_plural, or msgstr[]
if (($context != "MSGID") && ($context != "MSGCTXT") && ($context != "MSGID_PLURAL") && ($context != "MSGSTR_ARR")) { // Must come after msgid, msgxtxt, msgid_plural, or msgstr[]
_locale_import_message('The translation file %filename contains an error: "msgstr[]" is unexpected on line %line.', $file, $lineno);
return FALSE;
}
......@@ -1308,7 +1331,7 @@ function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group =
$context = "MSGSTR_ARR";
}
elseif (!strncmp("msgstr", $line, 6)) {
if ($context != "MSGID") { // Should come just after a msgid block
if (($context != "MSGID") && ($context != "MSGCTXT")) { // Should come just after a msgid or msgctxt block
_locale_import_message('The translation file %filename contains an error: "msgstr" is unexpected on line %line.', $file, $lineno);
return FALSE;
}
......@@ -1330,6 +1353,9 @@ function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group =
if (($context == "MSGID") || ($context == "MSGID_PLURAL")) {
$current["msgid"] .= $quoted;
}
elseif ($context == "MSGCTXT") {
$current["msgctxt"] .= $quoted;
}
elseif ($context == "MSGSTR") {
$current["msgstr"] .= $quoted;
}
......@@ -1344,7 +1370,7 @@ function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group =
}
// End of PO file, flush last entry
if (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) {
if (!empty($current) && !empty($current['msgstr'])) {
_locale_import_one_string($op, $current, $mode, $lang, $file, $group);
}
elseif ($context != "COMMENT") {
......@@ -1401,7 +1427,7 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
// Store string in memory (only supports single strings)
case 'mem-store':
$strings[$value['msgid']] = $value['msgstr'];
$strings[isset($value['msgctxt']) ? $value['msgctxt'] : ''][$value['msgid']] = $value['msgstr'];
return;
// Called at end of import to inform the user
......@@ -1454,7 +1480,7 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
if ($key == 0) {
$plid = 0;
}
$plid = _locale_import_one_string_db($report, $lang, $english[$key], $trans, $group, $comments, $mode, $plid, $key);
$plid = _locale_import_one_string_db($report, $lang, isset($value['msgctxt']) ? $value['msgctxt'] : '', $english[$key], $trans, $group, $comments, $mode, $plid, $key);
}
}
......@@ -1462,7 +1488,7 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
// A simple string to import.
$english = $value['msgid'];
$translation = $value['msgstr'];
_locale_import_one_string_db($report, $lang, $english, $translation, $group, $comments, $mode);
_locale_import_one_string_db($report, $lang, isset($value['msgctxt']) ? $value['msgctxt'] : '', $english, $translation, $group, $comments, $mode);
}
}
} // end of db-store operation
......@@ -1476,6 +1502,8 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
* array(inserts, updates, deletes).
* @param $langcode
* Language code to import string into.
* @param $context
* The context of this string.
* @param $source
* Source string.
* @param $translation
......@@ -1493,8 +1521,8 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
* @return
* The string ID of the existing string modified or the new string added.
*/
function _locale_import_one_string_db(&$report, $langcode, $source, $translation, $textgroup, $location, $mode, $plid = 0, $plural = 0) {
$lid = db_query("SELECT lid FROM {locales_source} WHERE source = :source AND textgroup = :textgroup", array(':source' => $source, ':textgroup' => $textgroup))->fetchField();
function _locale_import_one_string_db(&$report, $langcode, $context, $source, $translation, $textgroup, $location, $mode, $plid = 0, $plural = 0) {
$lid = db_query("SELECT lid FROM {locales_source} WHERE source = :source AND context = :context AND textgroup = :textgroup", array(':source' => $source, ':context' => $context, ':textgroup' => $textgroup))->fetchField();
if (!empty($translation)) {
// Skip this string unless it passes a check for dangerous code.
......@@ -1547,7 +1575,12 @@ function _locale_import_one_string_db(&$report, $langcode, $source, $translation
else {
// No such source string in the database yet.
$lid = db_insert('locales_source')
->fields(array('location' => $location, 'source' => $source, 'textgroup' => $textgroup))
->fields(array(
'location' => $location,
'source' => $source,
'context' => (string) $context,
'textgroup' => $textgroup,
))
->execute();
db_insert('locales_target')
......@@ -1932,6 +1965,7 @@ function _locale_parse_js_file($filepath) {
->fields(array(
'location' => $filepath,
'source' => $string,
'context' => '',
'textgroup' => 'default',
))
->execute();
......@@ -1958,17 +1992,18 @@ function _locale_parse_js_file($filepath) {
*/
function _locale_export_get_strings($language = NULL, $group = 'default') {
if (isset($language)) {
$result = db_query("SELECT s.lid, s.source, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.textgroup = :textgroup ORDER BY t.plid, t.plural", array(':language' => $language->language, ':textgroup' => $group));
$result = db_query("SELECT s.lid, s.source, s.context, s.location, t.translation, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.textgroup = :textgroup ORDER BY t.plid, t.plural", array(':language' => $language->language, ':textgroup' => $group));
}
else {
$result = db_query("SELECT s.lid, s.source, s.location, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE s.textgroup = :textgroup ORDER BY t.plid, t.plural", array(':textgroup' => $group));
$result = db_query("SELECT s.lid, s.source, s.context, s.location, t.plid, t.plural FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE s.textgroup = :textgroup ORDER BY t.plid, t.plural", array(':textgroup' => $group));
}
$strings = array();
foreach ($result as $child) {
$string = array(
'comment' => $child->location,
'source' => $child->source,
'translation' => isset($child->translation) ? $child->translation : ''
'context' => $child->context,
'translation' => isset($child->translation) ? $child->translation : '',
);
if ($child->plid) {
// Has a parent lid. Since we process in the order of plids,
......@@ -2045,6 +2080,9 @@ function _locale_export_po_generate($language = NULL, $strings = array(), $heade
$output .= '#: ' . $string['comment'] . "\n";
}
$output .= 'msgid ' . _locale_export_string($string['source']);
if (!empty($string['context'])) {
$output .= 'msgctxt ' . _locale_export_string($string['context']);
}
if (!empty($string['plural'])) {
$plural = $string['plural'];
$output .= 'msgid_plural ' . _locale_export_string($strings[$plural]['source']);
......@@ -2199,7 +2237,7 @@ function _locale_translate_seek() {
$sql_query = db_select('locales_source', 's');
$sql_query->leftJoin('locales_target', 't', 't.lid = s.lid');
$sql_query->fields('s', array('source', 'location', 'lid', 'textgroup'));
$sql_query->fields('s', array('source', 'location', 'context', 'lid', 'textgroup'));
$sql_query->fields('t', array('translation', 'language'));
// Compute LIKE section.
......@@ -2242,7 +2280,7 @@ function _locale_translate_seek() {
$locales = $sql_query->execute();
$groups = module_invoke_all('locale', 'groups');
$header = array(t('Text group'), t('String'), ($limit_language) ? t('Language') : t('Languages'), array('data' => t('Operations'), 'colspan' => '2'));
$header = array(t('Text group'), t('String'), t('Context'), ($limit_language) ? t('Language') : t('Languages'), array('data' => t('Operations'), 'colspan' => '2'));
$strings = array();
foreach ($locales as $locale) {
......@@ -2252,6 +2290,7 @@ function _locale_translate_seek() {
'languages' => array(),
'location' => $locale->location,
'source' => $locale->source,
'context' => $locale->context,
);
}
if (isset($locale->language)) {
......@@ -2264,6 +2303,7 @@ function _locale_translate_seek() {
$rows[] = array(
$groups[$string['group']],
array('data' => check_plain(truncate_utf8($string['source'], 150, FALSE, TRUE)) . '<br /><small>' . $string['location'] . '</small>'),
$string['context'],
array('data' => _locale_translate_language_list($string['languages'], $limit_language), 'align' => 'center'),
array('data' => l(t('edit'), "admin/international/translate/edit/$lid", array('query' => drupal_get_destination())), 'class' => 'nowrap'),
array('data' => l(t('delete'), "admin/international/translate/delete/$lid", array('query' => drupal_get_destination())), 'class' => 'nowrap'),
......
......@@ -178,13 +178,13 @@ function contact_mail($key, &$message, $params) {
case 'page_mail':
case 'page_copy':
$contact = $params['contact'];
$message['subject'] .= t('[!category] !subject', array('!category' => $contact['category'], '!subject' => $params['subject']), $language->language);
$message['body'][] = t("!name sent a message using the contact form at !form.", array('!name' => $params['name'], '!form' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language))), $language->language);
$message['subject'] .= t('[!category] !subject', array('!category' => $contact['category'], '!subject' => $params['subject']), array('langcode' => $language->language));
$message['body'][] = t("!name sent a message using the contact form at !form.", array('!name' => $params['name'], '!form' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language))), array('langcode' => $language->language));
$message['body'][] = $params['message'];
break;
case 'page_autoreply':
$contact = $params['contact'];
$message['subject'] .= t('[!category] !subject', array('!category' => $contact['category'], '!subject' => $params['subject']), $language->language);
$message['subject'] .= t('[!category] !subject', array('!category' => $contact['category'], '!subject' => $params['subject']), array('langcode' => $language->language));
$message['body'][] = $contact['reply'];
break;
case 'user_mail':
......@@ -193,9 +193,9 @@ function contact_mail($key, &$message, $params) {
$account = $params['account'];
$message['subject'] .= '[' . variable_get('site_name', 'Drupal') . '] ' . $params['subject'];
$message['body'][] = "$account->name,";
$message['body'][] = t("!name (!name-url) has sent you a message via your contact form (!form-url) at !site.", array('!name' => $user->name, '!name-url' => url("user/$user->uid", array('absolute' => TRUE, 'language' => $language)), '!form-url' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)), '!site' => variable_get('site_name', 'Drupal')), $language->language);
$message['body'][] = t("If you don't want to receive such e-mails, you can change your settings at !url.", array('!url' => url("user/$account->uid", array('absolute' => TRUE, 'language' => $language))), $language->language);
$message['body'][] = t('Message:', NULL, $language->language);
$message['body'][] = t("!name (!name-url) has sent you a message via your contact form (!form-url) at !site.", array('!name' => $user->name, '!name-url' => url("user/$user->uid", array('absolute' => TRUE, 'language' => $language)), '!form-url' => url($_GET['q'], array('absolute' => TRUE, 'language' => $language)), '!site' => variable_get('site_name', 'Drupal')), array('langcode' => $language->language));
$message['body'][] = t("If you don't want to receive such e-mails, you can change your settings at !url.", array('!url' => url("user/$account->uid", array('absolute' => TRUE, 'language' => $language))), array('langcode' => $language->language));
$message['body'][] = t('Message:', array(), array('langcode' => $language->language));
$message['body'][] = $params['message'];
break;
}
......
......@@ -229,6 +229,25 @@ function locale_update_6006() {
* @} End of "defgroup updates-5.x-to-6.x"
*/
/**
* @defgroup updates-6.x-to-7.x Locale updates from 6.x to 7.x
* @{
*/
/**
* Allow longer location.
*/
function locale_update_7000() {
$ret = array();
db_drop_index($ret, 'locales_source', 'source');
db_add_index($ret, 'locales_source', 'source_context', array(array('source', 30), 'context'));
return $ret;
}
/**
* @} End of "defgroup updates-6.x-to-7.x"
*/
/**
* Implement hook_uninstall().
*/
......@@ -381,6 +400,13 @@ function locale_schema() {
'not null' => TRUE,
'description' => 'The original string in English.',
),
'context' => array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'The context this string applies to.',
),
'version' => array(
'type' => 'varchar',
'length' => 20,
......@@ -391,7 +417,7 @@ function locale_schema() {
),
'primary key' => array('lid'),
'indexes' => array(
'source' => array(array('source', 30)),
'source_context' => array(array('source', 30), 'context'),
),
);
......
......@@ -341,12 +341,14 @@ function locale_theme() {
* A string to look up translation for. If omitted, all the
* cached strings will be returned in all languages already
* used on the page.
* @param $context
* The context of this string.
* @param $langcode
* Language code to use for the lookup.
* @param $reset
* Set to TRUE to reset the in-memory cache.
*/
function locale($string = NULL, $langcode = NULL, $reset = FALSE) {
function locale($string = NULL, $context = NULL, $langcode = NULL, $reset = FALSE) {
global $language;
static $locale_t;
......@@ -377,9 +379,9 @@ function locale($string = NULL, $langcode = NULL, $reset = FALSE) {
// Refresh database stored cache of translations for given language.
// We only store short strings used in current version, to improve
// performance and consume less memory.
$result = db_query("SELECT s.source, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.textgroup = 'default' AND s.version = :version AND LENGTH(s.source) < 75", array(':language' => $langcode, ':version' => VERSION));
$result = db_query("SELECT s.source, s.context, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.textgroup = 'default' AND s.version = :version AND LENGTH(s.source) < 75", array(':language' => $langcode, ':version' => VERSION));
foreach ($result as $data) {
$locale_t[$langcode][$data->source] = (empty($data->translation) ? TRUE : $data->translation);
$locale_t[$langcode][$data->context][$data->source] = (empty($data->translation) ? TRUE : $data->translation);
}
cache_set('locale:' . $langcode, $locale_t[$langcode]);
}
......@@ -387,17 +389,18 @@ function locale($string = NULL, $langcode = NULL, $reset = FALSE) {
}
// If we have the translation cached, skip checking the database
if (!isset($locale_t[$langcode][$string])) {
if (!isset($locale_t[$langcode][$context][$string])) {
// We do not have this translation cached, so get it from the DB.
$translation = db_query("SELECT s.lid, t.translation, s.version FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.source = :source AND s.textgroup = 'default'", array(
$translation = db_query("SELECT s.lid, t.translation, s.version FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.source = :source AND s.context = :context AND s.textgroup = 'default'", array(
':language' => $langcode,
':source' => $string,
':context' => (string) $context,
))->fetchObject();
if ($translation) {
// We have the source string at least.
// Cache translation string or TRUE if no translation exists.
$locale_t[$langcode][$string] = (empty($translation->translation) ? TRUE : $translation->translation);
$locale_t[$langcode][$context][$string] = (empty($translation->translation) ? TRUE : $translation->translation);
if ($translation->version != VERSION) {
// This is the first use of this string under current Drupal version. Save version
......@@ -416,17 +419,18 @@ function locale($string = NULL, $langcode = NULL, $reset = FALSE) {
->fields(array(
'location' => request_uri(),
'source' => $string,
'context' => (string) $context,
'textgroup' => 'default',
'version' => VERSION,
))
->execute();
$locale_t[$langcode][$string] = TRUE;
$locale_t[$langcode][$context][$string] = TRUE;
// Clear locale cache so this string can be added in a later request.
cache_clear_all('locale:', 'cache', TRUE);
}
}
return ($locale_t[$langcode][$string] === TRUE ? $string : $locale_t[$langcode][$string]);
return ($locale_t[$langcode][$context][$string] === TRUE ? $string : $locale_t[$langcode][$context][$string]);
}
/**
......
......@@ -212,9 +212,9 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));
// Add string.
t($name, array(), $langcode);
t($name, array(), array('langcode' => $langcode));
// Reset locale cache.
locale(NULL, NULL, TRUE);
locale(NULL, NULL, NULL, TRUE);
$this->assertText($langcode, t('Language code found.'));
$this->assertText($name, t('Name found.'));
$this->assertText($native, t('Native found.'));
......@@ -251,7 +251,7 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
$this->drupalPost(NULL, $edit, t('Save translations'));
$this->assertText(t('The string has been saved.'), t('The string has been saved.'));
$this->assertEqual($this->getUrl(), url('admin/international/translate/translate', array('absolute' => TRUE)), t('Correct page redirection.'));