/[drupal]/contributions/modules/active_translation/active_translation.module
ViewVC logotype

Contents of /contributions/modules/active_translation/active_translation.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.12 - (show annotations) (download) (as text)
Sun Jul 12 15:57:29 2009 UTC (4 months, 1 week ago) by drewish
Branch: MAIN
CVS Tags: DRUPAL-6--1-4, HEAD
Changes since 1.11: +2 -2 lines
File MIME type: text/x-php
#434428 by drewish and mdupont: Better message why users are seeing content in a different language.
1 <?php
2 // $Id: active_translation.module,v 1.11 2008/11/17 08:42:56 drewish Exp $
3
4 /**
5 * Implementation of hook_theme().
6 */
7 function active_translation_theme() {
8 return array(
9 'active_translation_node_message' => array(
10 'arguments' => array('form_element' => NULL),
11 ),
12 );
13 }
14
15 /**
16 * Implementation of hook_menu().
17 */
18 function active_translation_menu() {
19 $items['admin/settings/active_translation'] = array(
20 'title' => 'Active Translation',
21 'description' => 'Settings for the Active Translation module.',
22 'page callback' => 'drupal_get_form',
23 'page arguments' => array('active_translation_settings_form'),
24 'access arguments' => array('administer site configuration'),
25 'type' => MENU_NORMAL_ITEM,
26 'file' => 'active_translation.admin.inc',
27 );
28 $items['admin/settings/active_translation/settings'] = array(
29 'title' => 'Settings',
30 'type' => MENU_DEFAULT_LOCAL_TASK,
31 'weight' => -1,
32 );
33 $items['admin/settings/active_translation/rebuild'] = array(
34 'title' => 'Rebuild Table',
35 'page callback' => 'drupal_get_form',
36 'page arguments' => array('active_translation_rebuild_form'),
37 'access arguments' => array('administer site configuration'),
38 'type' => MENU_LOCAL_TASK,
39 'file' => 'active_translation.admin.inc',
40 );
41
42 return $items;
43 }
44
45 /**
46 * Implementation of hook_link_alter().
47 *
48 * Remove language links from the node.
49 */
50 function active_translation_link_alter(&$links, $node) {
51 if (variable_get('active_translation_hide_node_links', 0)) {
52 foreach ($links AS $module => $link) {
53 if (preg_match('<^node\_translation\_>',$module)) {
54 unset($links[$module]);
55 }
56 }
57 }
58 }
59
60 /**
61 * Implementation of hook_nodeapi().
62 */
63 function active_translation_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
64 switch ($op) {
65 case 'load':
66 return active_translation_nodeapi_load($node);
67 case 'view':
68 return active_translation_nodeapi_view($node, $a3, $a4);
69 case 'insert':
70 return active_translation_nodeapi_insert($node);
71 case 'update':
72 return active_translation_nodeapi_update($node);
73 case 'delete':
74 return active_translation_nodeapi_delete($node);
75 }
76 }
77
78 function active_translation_nodeapi_view(&$node, $teaser, $page) {
79 if ($page && !empty($node->language) && variable_get('active_translation_show_status', 1)) {
80 global $language;
81 $languages = locale_language_list('name', TRUE);
82
83 if ($node->language != $language->language) {
84 $trans = $node->active_translation;
85
86 $original = node_load($node->tnid);
87 $best_tran = node_load($trans[db_escape_table($language->language)]);
88
89 $message = '';
90 if ($best_tran->nid == $node->nid) {
91 $message = t("The %node-language version of this content is being displayed because the %user-language translation is unavailable.", array('%user-language' => $languages[$language->language], '%node-language' => $languages[$node->language]));
92 }
93 elseif ($best_tran->language == $language->language) {
94 $message = t("A %user-language translation of this content is available <a href='!link'>here</a>.", array('%user-language' => $languages[$language->language], '!link' => url('node/'. $best_tran->nid)));
95 }
96 elseif ($best_tran->nid == $original->nid) {
97 $message = t("This content has not been translated to %user-language but you may find <a href='!link'>the original</a> %node-langauge version easier to read.", array('%user-language' => $languages[$language->language], '%node-langauge' => $languages[$original->language], '!link' => url('node/'. $original->nid)));
98 }
99 else {
100 $message = t("This content has not been translated to %user-language but a %node-langauge version is available <a href='!link'>here</a>.", array('%user-language' => $languages[$language->language], '%node-langauge' => $languages[$best_tran->language], '!link' => url('node/'. $best_tran->nid)));
101 }
102 $node->content['language'] = array(
103 '#type' => 'item',
104 '#title' => t('Translation Note'),
105 '#value' => $message,
106 '#theme' => 'active_translation_node_message',
107 '#weight' => -100,
108 );
109 }
110 }
111 }
112
113 function theme_active_translation_node_message($form_element) {
114 $output = '<div class="active-translation-message">';
115 $output .= '<span class="active-translation-message-label">'. $form_element['#title'] .':</span> ';
116 $output .= $form_element['#value'] .'</div>';
117 return $output;
118 }
119
120 function active_translation_nodeapi_load($node, $reset = FALSE) {
121 static $cache;
122
123 if (!isset($cache) || $reset) {
124 $cache = array();
125 }
126
127 $atid = empty($node->tnid) ? $node->nid : $node->tnid;
128 if (isset($cache[$atid])) {
129 return $cache[$atid];
130 }
131
132 $result = db_query('SELECT * FROM {active_translation} WHERE atid = %d', $atid);
133 if ($cache[$atid] = db_fetch_array($result)) {
134 return array('active_translation' => $cache[$atid]);
135 }
136 }
137
138 function active_translation_nodeapi_insert($node) {
139 // Need to load the tnid out of the source.
140 if (isset($node->translation_source)) {
141 $source = $node->translation_source;
142 $node->tnid = empty($source->tnid) ? $source->nid : $source->tnid;
143 }
144
145 $translation = active_translation_recompute($node);
146 if ($translation['atid'] == $node->nid) {
147 drupal_write_record('active_translation', $translation);
148 }
149 else {
150 drupal_write_record('active_translation', $translation, array('atid'));
151 }
152 }
153
154 function active_translation_nodeapi_update($node) {
155 $translation = active_translation_recompute($node);
156 drupal_write_record('active_translation', $translation, array('atid'));
157 }
158
159 function active_translation_nodeapi_delete($node) {
160 if (!empty($node->tnid) && $node->nid != $node->tnid) {
161 // Recomputing for the node will load the record for the node's tnid.
162 $translation = active_translation_recompute($node);
163 drupal_write_record('active_translation', $translation, array('atid'));
164 }
165 else {
166 // TODO: I'm not really sure this is correct... Does deleting the original
167 // remove all the translations?
168 db_query('DELETE FROM {active_translation} WHERE atid = %d', array($node->nid));
169 }
170 }
171
172 /**
173 * Return an array of language field names that can be used as substutions for
174 * one another.
175 *
176 * TODO: might make more sense to have this specified as a setting rather than
177 * doing it automagically.
178 *
179 * @return array keyed by {active_translation} field name with an array of
180 * field names that can be used in place of it.
181 */
182 function _active_translation_language_substitutions() {
183 static $subs = NULL;
184
185 if (empty($subs)) {
186 // Break everything up by language.
187 $chunks = array();
188 foreach (language_list('language', TRUE) as $lang_code => $language) {
189 $parts = explode('-', $lang_code);
190 if (count($parts) == 2) {
191 $chunks[$parts[0]][] = $lang_code;
192 }
193 }
194
195 // Then provide mappings between each of region.
196 $subs = array();
197 foreach ($chunks as $language => $regions) {
198 $count = count($regions);
199 foreach ($regions as $lang_code) {
200 for ($i = 0; $i < $count; $i++) {
201 if ($regions[$i] != $lang_code) {
202 $subs[db_escape_table($lang_code)][] = db_escape_table($regions[$i]);
203 }
204 }
205 }
206 }
207 }
208
209 return $subs;
210 }
211
212 /**
213 * Compute the active tranlsations for a given node.
214 *
215 * @param $node Object with tnid or nid tnid properties.
216 * @return array with translation mapping.
217 */
218 function active_translation_recompute($node) {
219 $languages = array_keys(language_list('language'));
220
221 if (empty($node->tnid)) {
222 // If there are no tranlsations use this for all languages.
223 $translation = array('atid' => $node->nid);
224 foreach ($languages as $lang_code) {
225 $translation[db_escape_table($lang_code)] = $node->nid;
226 }
227 }
228 else {
229 $translation = array('atid' => $node->tnid);
230
231 // Locate all the existing, published translations...
232 $result = db_query("SELECT nid, language FROM {node} WHERE tnid <> nid AND tnid = %d AND status = 1", $node->tnid);
233 while ($row = db_fetch_object($result)) {
234 $translation[db_escape_table($row->language)] = $row->nid;
235 }
236
237 // ...then use the original to fill in any gaps. This will also take care
238 // of the case where all nodes are unpublished: the original node will be
239 // used.
240 $subs = _active_translation_language_substitutions();
241 foreach ($languages as $lang_code) {
242 $field = db_escape_table($lang_code);
243 if (empty($translation[$field])) {
244 // To be safe fill in the original...
245 $translation[$field] = $node->tnid;
246
247 // ...then go see if we can find a substitute
248 if (isset($subs[$field])) {
249 foreach ((array) $subs[$field] as $sub_field) {
250 if (isset($translation[$sub_field])) {
251 $translation[$field] = $translation[$sub_field];
252 break;
253 }
254 }
255 }
256 }
257 }
258 }
259
260 return $translation;
261 }
262
263 /**
264 * Implementation of hook_alter_translation_link().
265 *
266 * Replaces links with pointers to translated versions of the content.
267 */
268 function active_translation_translation_link_alter(&$links, $path) {
269 // Check for a node related path, and for its translations.
270 if ((preg_match("!^node/([0-9]+)(/.+|)$!", $path, $matches)) && ($node = node_load((int)$matches[1])) && !empty($node->tnid)) {
271 // Basically we're redoing the work of the local.module that the
272 // translation.module undoes in translation_translation_link_alter().
273 $languages = language_list('enabled');
274 $links = array();
275 foreach ($languages[1] as $language) {
276 $field = db_escape_table($language->language);
277 if (isset($node->active_translation[$field])) {
278 $links[$language->language] = array(
279 'href' => 'node/'. $node->active_translation[$field] . $matches[2],
280 'title' => $language->native,
281 'language' => $language,
282 'attributes' => array('class' => 'language-link'),
283 );
284 }
285 }
286 }
287 }
288
289 /**
290 * Implementation of hook_form_alter().
291 *
292 * We inject our own submit handler into the locale module's forms that add
293 * or remove languages so that when they're submitted we rebuild the active
294 * translation table.
295 */
296 function active_translation_form_alter(&$form, $form_state, $form_id) {
297 switch ($form_id) {
298 case 'locale_languages_delete_form':
299 case 'locale_languages_predefined_form':
300 case 'locale_languages_custom_form':
301 $form['#submit'][] = 'active_translation_rebuild_on_submit';
302 break;
303 }
304 }
305
306 /**
307 * Submission handler for the local module's forms so we can rebuild the
308 * active translation table in case languages are added or removed.
309 */
310 function active_translation_rebuild_on_submit() {
311 // Now build a batch to update the table.
312 require_once drupal_get_path('module', 'active_translation') .'/active_translation.batch.inc';
313 batch_set(active_translation_build_batch_all());
314 }
315
316 /**
317 * Implementation of hook_db_rewrite_sql().
318 *
319 * Rewrite node queries so language selection options are enforced.
320 */
321 function active_translation_db_rewrite_sql($query, $primary_table, $primary_key) {
322 global $language;
323
324 switch ($primary_table) {
325 case 'n':
326 case 'node':
327 // STOLE THISE FROM I18N, NEED TO MAKE SURE THEY'RE STILL VALID.
328
329 // Ignore the admin pages.
330 if (arg(0) == 'admin') return;
331 // No rewrite for queries with subselect ? (views count queries)
332 // @ TO DO Actually these queries look un-rewrittable, check with other developers
333 if (preg_match("/FROM \(SELECT/", $query)) return;
334 // No rewrite for translation module queries
335 if (preg_match("/.*FROM {node} $primary_table WHERE.*$primary_table\.tnid/", $query)) return;
336 // When loading specific nodes, language conditions shouldn't apply
337 if (preg_match("/WHERE.*\s$primary_table.nid\s*=\s*(\d|%d)/", $query)) return;
338
339 // Try to keep the i18n module from screwing with our queries.
340 if (module_exists('i18n')) {
341 i18n_selection_mode('off');
342 }
343
344 $field = db_escape_table($language->language);
345 $result['join'] = "INNER JOIN {active_translation} ON $primary_table.nid = {active_translation}.$field";
346 return $result;
347 }
348 }

  ViewVC Help
Powered by ViewVC 1.1.2