Index: modules/aggregator/aggregator.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v
retrieving revision 1.338
diff -u -p -r1.338 aggregator.module
--- modules/aggregator/aggregator.module 30 Apr 2007 17:03:22 -0000 1.338
+++ modules/aggregator/aggregator.module 4 May 2007 19:57:07 -0000
@@ -200,6 +200,21 @@ function aggregator_menu() {
return $items;
}
+/**
+ * Implementation of hook_locale().
+ */
+function aggregator_locale($op = 'groups') {
+ switch($op) {
+ case 'groups':
+ return array('aggregator' => t('Aggregator'));
+ case 'objects':
+ return array('aggregator' => array(
+ 'category' => array('cid', 'title', 'description'),
+ 'feed' => array('fid', 'title'),
+ ));
+ }
+}
+
function aggregator_init() {
drupal_add_css(drupal_get_path('module', 'aggregator') .'/aggregator.css');
}
@@ -267,11 +282,11 @@ function aggregator_block($op = 'list',
if (user_access('access news feeds')) {
if ($op == 'list') {
$result = db_query('SELECT cid, title FROM {aggregator_category} ORDER BY title');
- while ($category = db_fetch_object($result)) {
+ while ($category = dt('aggregator', 'category', db_fetch_object($result))) {
$block['category-'. $category->cid]['info'] = t('!title category latest items', array('!title' => $category->title));
}
$result = db_query('SELECT fid, title FROM {aggregator_feed} ORDER BY fid');
- while ($feed = db_fetch_object($result)) {
+ while ($feed = dt('aggregator', 'feed', db_fetch_object($result))) {
$block['feed-'. $feed->fid]['info'] = t('!title feed latest items', array('!title' => $feed->title));
}
}
@@ -299,7 +314,7 @@ function aggregator_block($op = 'list',
list($type, $id) = explode('-', $delta);
switch ($type) {
case 'feed':
- if ($feed = db_fetch_object(db_query('SELECT fid, title, block FROM {aggregator_feed} WHERE fid = %d', $id))) {
+ if ($feed = dt('aggregator', 'feed', db_fetch_object(db_query('SELECT fid, title, block FROM {aggregator_feed} WHERE fid = %d', $id)))) {
$block['subject'] = check_plain($feed->title);
$result = db_query_range('SELECT * FROM {aggregator_item} WHERE fid = %d ORDER BY timestamp DESC, iid DESC', $feed->fid, 0, $feed->block);
$read_more = '
'. l(t('more'), 'aggregator/sources/'. $feed->fid, array('title' => t("View this feed's recent news."))) .'
';
@@ -307,7 +322,7 @@ function aggregator_block($op = 'list',
break;
case 'category':
- if ($category = db_fetch_object(db_query('SELECT cid, title, block FROM {aggregator_category} WHERE cid = %d', $id))) {
+ if ($category = dt('aggregator', 'category', db_fetch_object(db_query('SELECT cid, title, block FROM {aggregator_category} WHERE cid = %d', $id)))) {
$block['subject'] = check_plain($category->title);
$result = db_query_range('SELECT i.* FROM {aggregator_category_item} ci LEFT JOIN {aggregator_item} i ON ci.iid = i.iid WHERE ci.cid = %d ORDER BY i.timestamp DESC, i.iid DESC', $category->cid, 0, $category->block);
$read_more = ''. l(t('more'), 'aggregator/categories/'. $category->cid, array('title' => t("View this category's recent news."))) .'
';
@@ -417,14 +432,17 @@ function aggregator_form_category_submit
function aggregator_save_category($edit) {
if (!empty($edit['cid']) && !empty($edit['title'])) {
db_query("UPDATE {aggregator_category} SET title = '%s', description = '%s' WHERE cid = %d", $edit['title'], $edit['description'], $edit['cid']);
+ module_invoke('locale', 'dynamic_update', 'aggregator', 'category', (object) $edit);
}
else if (!empty($edit['cid'])) {
db_query('DELETE FROM {aggregator_category} WHERE cid = %d', $edit['cid']);
+ module_invoke('locale', 'dynamic_update', 'aggregator', 'category', (object) $edit, 'delete');
}
else if (!empty($edit['title'])) {
// A single unique id for bundles and feeds, to use in blocks
- $next_id = db_next_id('{aggregator_category}_cid');
- db_query("INSERT INTO {aggregator_category} (cid, title, description, block) VALUES (%d, '%s', '%s', 5)", $next_id, $edit['title'], $edit['description']);
+ $edit['cid'] = db_next_id('{aggregator_category}_cid');
+ db_query("INSERT INTO {aggregator_category} (cid, title, description, block) VALUES (%d, '%s', '%s', 5)", $edit['cid'], $edit['title'], $edit['description']);
+ module_invoke('locale', 'dynamic_update', 'aggregator', 'category', (object) $edit);
}
}
@@ -463,7 +481,7 @@ function aggregator_form_feed($edit = ar
$options = array();
$values = array();
$categories = db_query('SELECT c.cid, c.title, f.fid FROM {aggregator_category} c LEFT JOIN {aggregator_category_feed} f ON c.cid = f.cid AND f.fid = %d ORDER BY title', $edit['fid']);
- while ($category = db_fetch_object($categories)) {
+ while ($category = dt('aggregator', 'category', db_fetch_object($categories))) {
$options[$category->cid] = check_plain($category->title);
if ($category->fid) $values[] = $category->cid;
}
@@ -557,6 +575,7 @@ function aggregator_save_feed($edit) {
}
if ($edit['fid'] && $edit['title']) {
db_query("UPDATE {aggregator_feed} SET title = '%s', url = '%s', refresh = %d WHERE fid = %d", $edit['title'], $edit['url'], $edit['refresh'], $edit['fid']);
+ module_invoke('locale', 'dynamic_update', 'aggregator', 'feed', (object) $edit);
}
else if ($edit['fid']) {
$result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = %d', $edit['fid']);
@@ -568,11 +587,13 @@ function aggregator_save_feed($edit) {
}
db_query('DELETE FROM {aggregator_feed} WHERE fid = %d', $edit['fid']);
db_query('DELETE FROM {aggregator_item} WHERE fid = %d', $edit['fid']);
+ module_invoke('locale', 'dynamic_update', 'aggregator', 'feed', (object) $edit, 'delete');
}
else if ($edit['title']) {
// A single unique id for bundles and feeds, to use in blocks.
$edit['fid'] = db_next_id('{aggregator_feed}_fid');
db_query("INSERT INTO {aggregator_feed} (fid, title, url, refresh, block) VALUES (%d, '%s', '%s', %d, 5)", $edit['fid'], $edit['title'], $edit['url'], $edit['refresh']);
+ module_invoke('locale', 'dynamic_update', 'aggregator', 'feed', (object) $edit);
}
if ($edit['title']) {
// The feed is being saved, save the categories as well.
@@ -1002,7 +1023,7 @@ function aggregator_view() {
$header = array(t('Title'), t('Items'), t('Last update'), t('Next update'), array('data' => t('Operations'), 'colspan' => '3'));
$rows = array();
- while ($feed = db_fetch_object($result)) {
+ while ($feed = dt('aggregator', 'feed', db_fetch_object($result))) {
$rows[] = array(l($feed->title, "aggregator/sources/$feed->fid"), format_plural($feed->items, '1 item', '@count items'), ($feed->checked ? t('@time ago', array('@time' => format_interval(time() - $feed->checked))) : t('never')), ($feed->checked ? t('%time left', array('%time' => format_interval($feed->checked + $feed->refresh - time()))) : t('never')), l(t('edit'), "admin/content/aggregator/edit/feed/$feed->fid"), l(t('remove items'), "admin/content/aggregator/remove/$feed->fid"), l(t('update items'), "admin/content/aggregator/update/$feed->fid"));
}
$output .= theme('table', $header, $rows);
@@ -1013,7 +1034,7 @@ function aggregator_view() {
$header = array(t('Title'), t('Items'), t('Operations'));
$rows = array();
- while ($category = db_fetch_object($result)) {
+ while ($category = dt('aggregator', 'category', db_fetch_object($result))) {
$rows[] = array(l($category->title, "aggregator/categories/$category->cid"), format_plural($category->items, '1 item', '@count items'), l(t('edit'), "admin/content/aggregator/edit/category/$category->cid"));
}
$output .= theme('table', $header, $rows);
@@ -1057,7 +1078,7 @@ function aggregator_page_last() {
* Menu callback; displays all the items captured from a particular feed.
*/
function aggregator_page_source() {
- $feed = db_fetch_object(db_query('SELECT * FROM {aggregator_feed} WHERE fid = %d', arg(2)));
+ $feed = dt('aggregator', 'feed', db_fetch_object(db_query('SELECT * FROM {aggregator_feed} WHERE fid = %d', arg(2))));
drupal_set_title(check_plain($feed->title));
$info = theme('aggregator_feed', $feed);
@@ -1068,7 +1089,7 @@ function aggregator_page_source() {
* Menu callback; displays all the items aggregated in a particular category.
*/
function aggregator_page_category() {
- $category = db_fetch_object(db_query('SELECT cid, title FROM {aggregator_category} WHERE cid = %d', arg(2)));
+ $category = dt('aggregator', 'feed', db_fetch_object(db_query('SELECT cid, title FROM {aggregator_category} WHERE cid = %d', arg(2))));
drupal_add_feed(url('aggregator/rss/'. arg(2)), variable_get('site_name', 'Drupal') .' '. t('aggregator - @title', array('@title' => $category->title)));
@@ -1091,7 +1112,7 @@ function aggregator_page_list($sql, $hea
if ($categorize) {
$categories_result = db_query('SELECT c.cid, c.title, ci.iid FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid AND ci.iid = %d', $item->iid);
$selected = array();
- while ($category = db_fetch_object($categories_result)) {
+ while ($category = dt('aggregator', 'category', db_fetch_object($categories_result))) {
if (!$done) {
$categories[$category->cid] = check_plain($category->title);
}
@@ -1180,7 +1201,7 @@ function aggregator_page_list_submit($fo
function aggregator_page_sources() {
$result = db_query('SELECT f.fid, f.title, f.description, f.image, MAX(i.timestamp) AS last FROM {aggregator_feed} f LEFT JOIN {aggregator_item} i ON f.fid = i.fid GROUP BY f.fid, f.title, f.description, f.image ORDER BY last DESC, f.title');
$output = "\n";
- while ($feed = db_fetch_object($result)) {
+ while ($feed = dt('aggregator', 'feed', db_fetch_object($result))) {
$output .= '
'. check_plain($feed->title) ."
\n";
// Most recent items:
@@ -1212,7 +1233,7 @@ function aggregator_page_rss() {
// arg(2) is the passed cid, only select for that category
$result = NULL;
if (arg(2)) {
- $category = db_fetch_object(db_query('SELECT cid, title FROM {aggregator_category} WHERE cid = %d', arg(2)));
+ $category = dt('aggregator', 'category', db_fetch_object(db_query('SELECT cid, title FROM {aggregator_category} WHERE cid = %d', arg(2))));
$url = '/categories/'. $category->cid;
$title = ' '. t('in category') .' '. $category->title;
$sql = 'SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_category_item} c LEFT JOIN {aggregator_item} i ON c.iid = i.iid LEFT JOIN {aggregator_feed} f ON i.fid = f.fid WHERE cid = %d ORDER BY timestamp DESC, iid DESC';
@@ -1268,7 +1289,7 @@ function aggregator_page_opml($cid = NUL
$output .= "\n";
$output .= "\n";
- while ($feed = db_fetch_object($result)) {
+ while ($feed = dt('aggregator', 'feed', db_fetch_object($result))) {
$output .= '
\n";
}
@@ -1286,7 +1307,7 @@ function aggregator_page_categories() {
$result = db_query('SELECT c.cid, c.title, c.description FROM {aggregator_category} c LEFT JOIN {aggregator_category_item} ci ON c.cid = ci.cid LEFT JOIN {aggregator_item} i ON ci.iid = i.iid GROUP BY c.cid, c.title, c.description');
$output = "
\n";
- while ($category = db_fetch_object($result)) {
+ while ($category = dt('aggregator', 'category', db_fetch_object($result))) {
$output .= '
'. check_plain($category->title) ."
\n";
if (variable_get('aggregator_summary_items', 3)) {
$list = array();
@@ -1405,7 +1426,7 @@ function theme_aggregator_page_item($ite
$result = db_query('SELECT c.title, c.cid FROM {aggregator_category_item} ci LEFT JOIN {aggregator_category} c ON ci.cid = c.cid WHERE ci.iid = %d ORDER BY c.title', $item->iid);
$categories = array();
- while ($category = db_fetch_object($result)) {
+ while ($category = dt('aggregator', 'category', db_fetch_object($result))) {
$categories[] = l($category->title, 'aggregator/categories/'. $category->cid);
}
if ($categories) {
Index: modules/locale/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v
retrieving revision 1.171
diff -u -p -r1.171 locale.module
--- modules/locale/locale.module 3 May 2007 09:51:08 -0000 1.171
+++ modules/locale/locale.module 4 May 2007 19:57:06 -0000
@@ -387,6 +387,154 @@ function locale_get_plural($count) {
return $plurals[$count];
}
+/**
+ * Dynamic object translation.
+ *
+ * @param $group
+ * Text group to search strings in. For the 'default' group,
+ * use the t() function. For other groups, use dt(). Groups
+ * should be defined using hook_locale().
+ * @param $object_type
+ * The name of the object type as specified in hook_locale().
+ * @param $object
+ * Object to translate. Localizable properties defined in hook_locale()
+ * are replaced with localized versions if available.
+ * @param $dt_language
+ * Optional language code to look up strings in.
+ * Defaults to the language used to generate the page.
+ *
+ * @todo
+ * - We could add a cache property to $object[$group][$object_type]['cache'] = TRUE | FALSE
+ * - An empty string may be a valid translation too!! Let's allow some flexibility.
+ */
+function locale_dynamic($group, $object_type, $object, $dt_language = NULL) {
+ global $language;
+ static $objects = NULL;
+ static $cache = array();
+
+ // Cache object metadata provided by modules for translation.
+ if (!isset($objects)) {
+ $objects = module_invoke_all('locale', 'objects');
+ }
+
+ // Fall back on default language if not instructed otherwise.
+ $default = language_default();
+ if (!isset($dt_language)) {
+ $dt_language = $language->language;
+ }
+
+ // Skip if default language or found no descriptor for the object.
+ if (($dt_language == $default->language) || !isset($objects[$group][$object_type])) {
+ return $object;
+ }
+
+ // Allow groups to be translated with custom callbacks by contributed
+ // modules, enabling better caching tailored for specific needs.
+ if (isset($objects[$group]['#callback']) && function_exists($objects[$group]['#callback'])) {
+ return call_user_func($objects[$group]['#callback'], $group, $object_type, $object, $dt_language);
+ }
+
+ // Build a list of locations searched for.
+ $properties = $objects[$group][$object_type];
+ $idname = array_shift($properties);
+ $locations = array();
+ foreach ($properties as $property) {
+ // Only try to look up properties present in the passed object.
+ if (isset($object->$property)) {
+ $location = $object_type .':'. $object->$idname .':'. $property;
+ // Try to find in cached properties first.
+ if (isset($cache[$dt_language][$group][$location])) {
+ // Nonexistent translations are cached as NULL.
+ $object->property = is_null($cache[$dt_language][$group][$location]) ? $object->property : $cache[$dt_language][$group][$location];
+ } else {
+ $locations[] = $location;
+ // Expecting that we have no translation for this, or will
+ // replace this NULL later with a value.
+ $cache[$dt_language][$group][$location] = NULL;
+ }
+ }
+ }
+
+ // We assume source strings will exist in the database, because
+ // locale_dynamic_update() should have been called earlier for
+ // the object. We search the database if not all properties were
+ // in our local cache.
+ if (count($locations)) {
+ $result = db_query("SELECT s.location, s.source, t.translation FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid WHERE t.language = '%s' AND s.location IN ('". join("','", $locations) ."') AND s.textgroup = '%s'", $dt_language, $group);
+
+ // Translate every object property for which we have translation.
+ while ($row = db_fetch_object($result)) {
+ list (,,$property) = explode(':', $row->location);
+ if ($object->$property == $row->source) {
+ $object->$property = $row->translation;
+ }
+ $cache[$dt_language][$group][$row->location] = $row->translation;
+ }
+ }
+
+ return $object;
+}
+
+/**
+ * Update dynamic strings from objects.
+ * Create new entries and remove old ones.
+ *
+ * @param $group
+ * Text group to save the strings in. This function should not be used for
+ * the 'default' group! Groups should be defined using hook_locale().
+ * @param $object_type
+ * The name of the object type as specified in hook_locale().
+ * @param $object
+ * Object to save. Localizable properties defined in hook_locale() are saved.
+ * @param $op
+ * 'update' (default) to create/update existing source strings.
+ * 'delete' to remove existing entries.
+ */
+function locale_dynamic_update($group, $object_type, $object, $op = 'update') {
+ static $objects = NULL;
+
+ // Cache object metadata provided by modules for translation.
+ if (!isset($objects)) {
+ $objects = module_invoke_all('locale', 'objects');
+ }
+
+ // Return with error if no information found about this object type.
+ if (!isset($objects[$group][$object_type])) {
+ return FALSE;
+ }
+
+ // Build a list of locations we need to work with.
+ $properties = $objects[$group][$object_type];
+ $idname = array_shift($properties);
+ $locations = array();
+ foreach ($properties as $property) {
+ $locations[$property] = $object_type .':'. $object->$idname .':'. $property;
+ }
+
+ switch ($op) {
+ case 'update':
+ foreach ($locations as $property => $location) {
+ if ($source = db_fetch_object(db_query("SELECT * FROM {locales_source} WHERE location = '%s' AND textgroup = '%s'", $location, $group))) {
+ // Update entry only if source string changed.
+ if ($source->source != $object->$property) {
+ db_query("UPDATE {locales_source} SET source = '%s' WHERE location = '%s' AND textgroup = '%s'", $object->$property, $location, $group);
+ }
+ } else {
+ // Create new entry.
+ db_query("INSERT INTO {locales_source} (source, location, textgroup) VALUES('%s', '%s', '%s')", $object->$property, $location, $group);
+ }
+ }
+ break;
+ case 'delete':
+ foreach ($locations as $location) {
+ if ($lid = db_result(db_query("SELECT lid FROM {locales_source} WHERE location = '%s' AND textgroup = '%s'", $location, $group))) {
+ db_query("DELETE FROM {locales_source} WHERE lid = %d", $lid);
+ db_query("DELETE FROM {locales_target} WHERE lid = %d", $lid);
+ }
+ }
+ break;
+ }
+}
/**
* Returns a language name