Problem/Motivation

drupal_set_message() sets a message to display to the user. This messages cannot be modified from other modules, or customized in a given site.

Proposed resolution

Add a hook_messages_alter() function.

Remaining tasks

  • Check if this compromise solution is still on time for D8.
  • Write tests.

User interface changes

None.

API changes

  • drupal_set_message($message = NULL, $type = 'status', $repeat = FALSE) becomes drupal_set_message($message = NULL, $type = 'status', $message_key = NULL, $repeat = FALSE)
  • API addition: hook_messages_alter()

Original report by @Gman

Originally noted at http://www.tech-wanderings.com/Drupal-hook_message_alter, I want to propose a new hook, hook_message_alter.

As I have been working on the functional implementation for a new community Drupal site, I have been seeing the need to customize many of the core Drupal messages (the drupal_set_message function), as required by the needs of the site. A typical example would be when a contact message has been sent, the default message is 'The message has been sent.' An small change might be to 'Thank you, your message has been sent.' A more dynamic change would be 'Thank you Greg, your message has been sent'.

The first change could be accomplished using the locale module methodologies found in http://drupal.org/node/58030. But there are two short-comings to this method. First, even though all core modules use t() for the text to make it translation ready, many contributed modules do not. Second, the translation method only allows for string replacements, not dynamic insertions. Granted some of the messages place the user's name or other dynamic information into the message, but the basic idea is that you can only change what is given you, you can't add to it. The contact message is a perfect example, there is no way to add the user's name to the message.

That is why I am going to propose a new drupal hook, hook_message_alter(&$message = NULL), allowing the $message to be changed by reference. It would hook into the drupal_set_message function. All messages would invoke this hook, giving designers and developers the ability to customize those messages completely to suit their site.

Since the purpose of hooks is to 'Allow modules to interact with the Drupal core', then this hook is needed for any time that the core (or any contributed) messages are not composed the way a site owner would want them to be.

This hook would most likely be used as part of theming/customization of site, and thus not used much in a contibuted module, though it may be used in a contibuted theme if the designer wanted to update the message prose. Personally I would use such a hook to dynamically insert text into the messages at key points in the user experience (especially if I am seeking to make certian conversion points of a client's site personalized).

The new drupal_set_message would pass the $message by reference and change to:

function drupal_set_message($message_id, $message = NULL, $type = 'status') {
  if ($message) {
    if (!isset($_SESSION['messages'])) {
      $_SESSION['messages'] = array();
    }

    if (!isset($_SESSION['messages'][$type])) {
      $_SESSION['messages'][$type] = array();
    }

    foreach (module_implements('message_alter) as $module) {
      $function = $module .'_message_alter';
      $function($message);
    }

    $_SESSION['messages'][$type][] = $message;
  }

  // messages not set when DB connection fails
  return isset($_SESSION['messages']) ? $_SESSION['messages'] : NULL;
} 

With an implementation of a hook looking like:

function example1_message_alter (&$message = NULL) {
  if (strcmp($message, 'The message has been sent.') {
    global $user;
    $message = 'Thank you ' . $user->name . ' for contacting us. Your message has been sent.';
  }
}

The return value is discarded. Modify the $message directly.

Please let me know any of your thoughts, as I will present this as an issue at Drupal.org once I have better composed this idea. -Greg

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

chx’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
468 bytes

I can not see any negatives of this and there is a beneift. Why not?

The patch was broken I rerolled.

chx’s picture

FileSize
468 bytes

I can not see any negatives of this and there is a beneift. Why not?

The patch was broken I rerolled.

Gman’s picture

Thanks for the help on the correct implementation chx, and for rerolling the patch. Also, who takes care of the api.drupal.org hook reference? I would hate to 'fire and forget' on this, I want to make sure I learn all the ways to help out.

Also, if approved, would there be a chance to roll this into a 5.x release, since it is fully backward compatible with present code?

Thanks. -Greg

RobRoy’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
469 bytes

Looks like there was a parse error in there with a missing end quote. Also, I like this, but are there any performance issues to be discussed since dsm is called so much? I know module_implements has a static cache so I guess it wouldn't be too bad.

AmrMostafa’s picture

Status: Needs review » Postponed (maintainer needs more info)

WIth the current implementation the problem doesn't go away easily, consider the message "The %post has been updated."
How would you go for replacing it with "Thank you Greg, the %post has been updated."?

I'm not sure what would be a good way to achieve this, maybe modify drupal_set_message() to accept the t() array, invoke the hook then pass the message to t(), which would also be a way to force t()ing of all messages.

Btw, wouldn't it be possible to do what this hook does by a using hook_exit() and modifying the $_SESSION['messages'] directly?

greggles’s picture

Status: Postponed (maintainer needs more info) » Needs review

In drupal_mail there are several more arguments:

drupal_mail($mailkey, $to, $subject, $body, $from = NULL, $headers = array())

A $mailkey strikes me as the kind of thing we may want in hook_message:

$mailkey A key to identify the mail sent, for altering.

Perhaps a $messagekey ?

@alienbrain this is a patch that needs review and discussion . I think we have enough "info" now we need to discuss implementation.

pwolanin’s picture

I essentially proposed adding a message ID here: http://drupal.org/node/106634

and was rejected, FYI.

Gman’s picture

greggles, drupal_mail() was actually my original inspiration for this and I tried to explore the idea of $message_id/$messagekey, for drupal_set_message(). In a differenet email exchange we hashed out that maybe it wasn't needed, but we didn't take into account already dynamic insertions like %node,which makes strcmp() replacements much harder to implement.

Hmm, catching all those variations of a message would turn into a preg_match pain, so maybe a $messagekey would solve that. In creating the hook, I would just need to switch on the $messagekey, alter the message by reference as desired and be done. Like is:

function example1_message_alter ($messagekey, &$message = NULL) {
  switch ($messagekey) {
    case 'contact_site_mail':
      global $user;
      $message = 'Thank you ' . $user->name . ' for contacting us. Your message has been sent.';
      break;
  }
}

Many times the $messagekey can just be the $form_id for consistency. But this kind of change would result in rewriting all the dsm() function calls, more work but it if is the right call I can help out.

Again, the chief reason for desiring this hook is that I don't want to hack core or contributed modules to produce the exact dynamic messages that product managers and design specification demand. The other option is to suppress $messages in the theme or intercept the $_SESSION variable and update the messages, which seems hacky as a long term solution.

pwolanin, maybe this will be a new reason to revisit the topic.

AmrMostafa’s picture

May I ask for +1/-1s for the approach I suggested earlier?

Code may explain better. Instead of the current:

drupal_set_message(t('The %post has been updated.', array('%post' => $node_type));

It would be:

drupal_set_message('The %post has been updated.', array('%post' => $node_type));

drupal_set_message() will then pass the string AND the array to interested modules via hook_message_alter() which can make modifications if needed, then drupal_set_message() will pass the string and the array to t() to get the final message.

An example of such an implementation of the hook would be:

function example_message_alter(&$message, &$params = array()) {
  global $user;

  if ($message == 'The %post has been updated.') {
    $message = 'Thanks !user, the %post has been updated.';
    $params['!user'] = theme('username', $user);
  }
}

I think the downside for this approach is that calls to drupal_set_message() must not use t() by themselves which is contrary to the general approach in Drupal. However, drupal_set_message() deals essentially with messages/strings so it makes some sense that it doesn't need to take a t()ed string as it will t() it by itself (i.e. it's not hard for developers to remember that), we already have format_plural() which also behaves in the same way.

pwolanin’s picture

Status: Needs review » Needs work

+1 from me- seems like a clean and simple approach.

Gman’s picture

In the development mailing list, there was discussion of acceptable reasons not to use t() in a message, but no further guidance was given there. If there is never an acceptable reason to not t() the string and its arguments, then this approach may be sufficient.

I must admin that I was not thinking about the translation aspect of the processing, but if I am running a multilingual site, then altering the message before translation is highly desirable.

On the other hand, should we force people to alter English messages before they hit translation, or just let them alter the messages after they have been translated into the language they want?

I lean to the former since they have to at least look at the core message to know what to alter anyway.

To keep the ball rolling I think the code from this proposal would look like:

function drupal_set_message(&$message = NULL, &$params = array(), $type = 'status') {
  if ($message) {
    if (!isset($_SESSION['messages'])) {
      $_SESSION['messages'] = array();
    }

    if (!isset($_SESSION['messages'][$type])) {
      $_SESSION['messages'][$type] = array();
    }

    foreach (module_implements('message_alter) as $module) {
      $function = $module .'_message_alter';
      $function($message, $params);
    }
    $message = t($message, $params);
    $_SESSION['messages'][$type][] = $message;
  }

  // messages not set when DB connection fails
  return isset($_SESSION['messages']) ? $_SESSION['messages'] : NULL;
}

This change will force a rewrite of all dsm() function calls though.

RobRoy’s picture

Would we really want $message and $params to be passed by reference?

Gman’s picture

Well, this method lets multiple modules have the option to change the message, but since I believe the normal use for this hook will be site specific, then their will only be one module altering the message. Then the by-reference calls won't be needed.

pwolanin’s picture

Note- per recent post on the devel list- that there are some points in the Drupal bootstrap cycle where t() is not available.

Gman’s picture

I was doing more research and I was glad to note that form_set_error() calls drupal_set_message, so that all such form validation messages can be updated in a similar fashion. If and when an API page is written for this, both drupal_set_message and form_set_error messages should be included as examples of messages that can be changed with this hook.

Just this afternoon, my project manager asked for all the 'error' text that they want to 'sanitize'. I slimmed the list down by excluding all the admin and backend messages, but still had a list of 75+ messages that they may change to some extent or other.

Again, if they merely update the text, then I can use the translation method to update the messages, BUT their will be many times they want to include dynamic text, like the example above.

Since it seems that the idea of building the t() inside the drupal_set_message will break certain essential messages (like when the db is down, during installs and the like), then we can't go at that approach.

So we are back to a very simple design of only passing the $message and doing strcmp on it to test if it is the string you want to update from chx (which is essentially backwards compatible), or we add a $messagekey for identification like the form greggles suggested.

Thank you again for reviewing this, I will be patching my site ASAP, but I believe this change can be valuable to many serious site designers going forward.

AmrMostafa’s picture

I was taking my morning swim inside bootstrap.inc and look what I've found :-)

http://api.drupal.org/api/5/function/get_t

Gman’s picture

I am not sure I am getting your implication correct, but then wouldn't we have to have to do the $t = get_t(); code every time in dsm() or switch it depending on the state of the bootstrap?

Maybe the more basic question is do we want people to alter English messages before translation or to alter already translated text?

I am glad that everyone believe that such alterations are valuable, so I will keep driving for the best implementation. -G

AmrMostafa’s picture

I am not sure I am getting your implication correct, but then wouldn't we have to have to do the $t = get_t(); code every time in dsm()

Yes, that's what I meant actually.

I don't think that would affect performance as get_t() seems to be very straightforward and fast as all what it will be doing after the first call is returning the correct localization function from a static variable.

Gman’s picture

There has not been much input from core devs, though I did get a chance to remind chx about this at the OSCMS Summit, and I mentioned it to Dries in passing as well. I will try to get a brief bit of focus on this small, but needed feature, and get the right implementation at the hackfest after the Summit.

I would like to see the simple, lean implementation of just passing the $message as usual, possibly with a $messagekey if I can get it past chx.

Too much changes without much benefit if we move the t() to inside the drupal_set_message function.

Gman’s picture

Also, if we use the patch from http://drupal.org/node/127262#comment-212710, it can actually be included in the next 5.x release, not just for 6.x, since it is fully backwards compatible with current usage.

eaton’s picture

I took a look at this, and I'd like to see two things: an optional message id, and the alterations invoked at *display* time rather than *set* time. Why? On a screen that displays numerous messages, we'll end up calling the alter hooks once for each message. if we call it on the entire list of all messages that are about to be displayed, we can save some time and we can give developers the ability to discover some context in complex scenerios -- for example, seeing that 100+ versions of the same message were set, etc...

Gman’s picture

Eaton, I definitely see the performance issue with not calling the hook every message. Without the message id, it is no trouble at all, but... I we add a $messagekey of some sort, then it will have to be added to the $_SESSION['messages'] array for the id to persist long enough to be handled by this altering hook before display., versus the id only being needed for the setting of the message, but then discarded before being written into the session variable. Will the extra data storage offset the extra innvocations?

On another note, I believe the use case for this hook is more from the 'design and messaging the user' perspective, not messaging a developer/admin. A dev/admin will usually be content with whatever messages are sent to him/her, but the public face of a site to its user base (which usually are one-off messages, not loads of db error messages during developement) sometimes needs to be precisely managed. Just noting how this hook was conjured up in the first place, as my project manager wants to change many of the stock messages with dynamics messages.

I will churn out a quick patch with the drupal_get_message() implementation.

pwolanin’s picture

Note implementation should probably use the new drupal_alter() function: http://drupal.org/node/114774#drupal-alter
and for extra points, and 5.x implementation should easily be adapted to use this for 6.x

(side note- it makes no sense to me why this wasn't called something more evocative like drupal_invoke_alter() )

pwolanin’s picture

An alternate suggestion- the main problem highlighted is the inability to add additional tokens when using the locale module to translate a DSM message. Right?

I have the feeling that there is a push to include a set of standard tokens in core, and so for 6.x, the problem might be addressed in this way.

Gman’s picture

I will update to the drupal_alter() form implementation, thanks for the lead. Also I am not sure that tokens will work to execute the hook into the alteration, but for simplifying adding dynamic content, it may be handy.

I did have a few concerns regarding adding an optional $messagekey if we go the drupal_get_message route.

Can't just use in drupal_set_message

$_SESSION['messages'][$type][$messagekey] = $message;

in the place of

$_SESSION['messages'][$type][] = $message;

because the theme_status_messages function looks for $messages[0] when there is only one message of that type. So we need to fix this theming function OR embed the key into something like which I think is rather messy (set in drupal_set:

$_SESSION['messages'][$type][] = array ('messagekey' => $messagekey, 'message' => $message);

The dgm() or dsm() implementation is almost the same as far as the changes in calling the drupal_alter() hook.

A sample implementation WITHOUT the $messagekey would look like:

function example1_message_alter(&$messages) {
  foreach($messages['status'] as $key => $message) {
    if(!strcmp('Your message has been sent.', $message)) {
      global $user;
      $messages['status'][$key] = 'Thank you, ' . $user->name . ', your message has been sent.';
    }
  }
}

The below code is NOT possible unless we fix the theming function and then ONLY if modules are supporting a $messagekey:

function example2_message_alter(&$messages) {
  if($messages['status']['contact_mail_page']) {
      global $user;
    $messages['status']['contact_mail_page'] = 'Thank you, ' . $user->name . ', your message has been sent.';
  }
}

Again, is we just call during dsm() then we don't have to worry about the structure of the $messages array, since we are altering the message before it is included.

Which route should I go? Continue with optional keys, in dgm() and update the theme function, or do it in dsm()?

Gman’s picture

Status: Needs work » Needs review
FileSize
1.72 KB

Here is the patch that I had put off.

Changed to the drupal_alter() function in drupal_get_message, per Peter (thanks for the insight on that one).

If the optional $messagekey is present, then it is used as the key in the $messages['type'][$messagekey] = $message assignment. Then you can use the example2 code above to kept for the right key and make the changes. If no key is given, or you are too lazy to find it, then you can just do a strstr() or !strcmp() check as you loop through the entire $messages array.

Also,I edited the theme_status_message function to take a keyed array, since that is what must be done for us to place the logic in drupal_get_message().

Please review and comment.

Gman’s picture

FileSize
1.75 KB

Update patch.

Updated theme_status_messages() to use array shift if only one element instead of array[0], and added note of explanation.

RobRoy’s picture

Status: Needs review » Needs work

One little nit: $messagekey should be $message_key to be consistent with core var naming.

Gman’s picture

FileSize
1.75 KB

No problem. Patch updated.

AmrMostafa’s picture

Gman’s picture

Status: Needs work » Needs review

alienbrain, that is a cool feature, but it does not allow for dynamic updates that were the requirement for this code.

I will probably keep up on that other issue to meet other needs though.

I forgot to mark my above as 'code needs review'. It is marked appropriately now.

Gman’s picture

Could I have another check of this patch? I am hoping not to have let this get stale. The need for the chance to dynamically update messages really is a must in certain situations. Thanks.

dodorama’s picture

A much needed feature.
+1

keith.smith’s picture

Status: Needs review » Needs work

Nice feature, but patch no longer applies

# patch -p0 < hook_message_alter_5.patch
(Stripping trailing CRs from patch.)
patching file includes/bootstrap.inc
Hunk #1 succeeded at 980 (offset 295 lines).
Hunk #3 FAILED at 721.
1 out of 3 hunks FAILED -- saving rejects to file includes/bootstrap.inc.rej
(Stripping trailing CRs from patch.)
patching file includes/theme.inc
patch: **** malformed patch at line 56:

moshe weitzman’s picture

subscribe

Gman’s picture

I am waiting for the D6 to get out before starting to re-roll this patch, since it missed the cut off.

I don't want to distract the D6 progress by trying to refocus on this patch now, but once D6 is released I would still like to revisit this issue.

For true, interactive sites with owners desiring precise message control, being able to easily intercept all messages sent through drupal_set_message should be exposed via drupal_alter() or some other mechanism.

-G

bdragon’s picture

Version: 6.x-dev » 7.x-dev

In that case, updating status.
Queue maintenance brought to you by Patch Bingo.

kbahey’s picture

Subscribe.

Xano’s picture

Status: Needs work » Closed (duplicate)
Dave Reid’s picture

Status: Closed (duplicate) » Needs work

No, this is the original issue. Marked the other issue as the duplicate.

Owen Barton’s picture

Subscribe

dawehner’s picture

Status: Needs work » Needs review
FileSize
3.32 KB

here is a rerole

i'm not sure whether $repeat is used anywhere else i'm not a grep master
i checked it by using

grep "drupal_set_message" . -rn | grep "FALSE"
grep "drupal_set_message" . -rn | grep "TRUE"

Status: Needs review » Needs work

The last submitted patch failed testing.

greggles’s picture

grep -rnH drupal_set_message * | grep FALSE

Finds several examples from contributed modules in a local 6x installation.

dawehner’s picture

what does the "H" do?

Xano’s picture

-H: print filename for each match.

JacobSingh’s picture

I thought about this a bit.

While the functionality is certainly needed, I would venture that a better approach is to just ask module developers to build their modules intelligently. And this means using variable_get() when looking for string to use in messages. Static strings have no place in good code (although I am certainly guilty of it on many occasions).

This should be happening anyway, and would allow you to override messages, and even build a nice UI for them. Perhaps developers could even implement a hook_message_info() or hook_messages() which would optionally return an array of message identifiers and descriptions of the messages (like 'mymodule_big_error' => "This is a message that gets showed when something horks")

Then, we could build an interface for modifying these strings. If they don't implement it, no big deal, can still be set w/ variables.

Best,
Jacob

Xano’s picture

- Variables are configuration settings.
- We already have an interface for modifying strings. Do we really want a new one to modify strings used only for messages? If so, how do we know if those strings are only used for messages?
- What if we simply want to unset messages?
- Why do static strings have no place in good code? IMO it depends on the context.

JacobSingh’s picture

"Variables are configuration settings."

Sure, but that's not a law, and really, these are configuration settings. There are many cases where bits of text are in variables. You could have another "thing" but basically, it's just storing k=v pairs.

"We already have an interface for modifying strings. Do we really want a new one to modify strings used only for messages? If so, how do we know if those strings are only used for messages?"

Do we? Are you talking about locale? This is fine, as long as you only want to use 1 language on your site, but it's kinda a hack.

"What if we simply want to unset messages?"

The point is, the variable doesn't exist in the database. It is only when they exist that they are overridden. You can make a "disable" button in the interface, settings in settings.php, etc can just be set to "".

"Why do static strings have no place in good code? IMO it depends on the context."

Meh, yeah, every rule is there to be broken, but generally true, and I think this issue is an example of this.

Best,
Jacob

Xano’s picture

I am still not sure what you mean, then, or what your approach offers more than a hook_message_alter() does.

catch’s picture

Version: 7.x-dev » 8.x-dev

Moving to D8.

sun’s picture

We don't want to do this.

We want to kill drupal_set_message() in favor of drupal_mail() instead. (and while being there, give it a new name)

Xano’s picture

You got any more info on that?

Dave Reid’s picture

@sun: Yes, is there a link for that issue because that sounds a little like crazy talk. :)

sun’s picture

The entire subsystem for building, altering, formatting, and sending a message is already in place. It is currently called drupal_mail(), and core currently implements only one sending implementation, which is a wrapper around PHP mail().

What you want is literally the same. Except of that you don't want to send the message via PHP's mail() but through a sending implementation that simply stacks a message into the user's session.

And an implementation like that almost exists already: @see modules/system/main.sending.inc: TestingMailSystem

arcaneadam’s picture

I guess I am not following what sun is saying, the drupal_mail module is not and as far as I know wouldn't ever replace drupal_set_message.

To me this sounds like a great idea, although the implementation in the original posting is not really the bast way to handle it. I would propose something like this:

<?php
function drupal_set_message($message_id,$message = NULL, $type = 'status', $repeat = TRUE,) {
  if ($message) {
    if (!isset($_SESSION['messages'][$type])) {
      $_SESSION['messages'][$type] = array();
    }

    if ($repeat || !in_array($message, $_SESSION['messages'][$type])) {
      $_SESSION['messages'][$type][$message_id] = $message;
    }

    // Mark this page has being not cacheable.
    drupal_page_is_cacheable(FALSE);
  }

  // Messages not set when DB connection fails.
  return isset($_SESSION['messages']) ? $_SESSION['messages'] : NULL;
}
?>

Which simply sets the array key for the message to the $message_id. Then instead of modifying each and every message when they are set we run drupal_alter in drupal_get_message to run the messages through the hook:

<?php
function drupal_get_messages($type = NULL, $clear_queue = TRUE) {
  if ($messages = drupal_set_message()) {
    drupal_alter('message',$messages); // <-----The alter hook being executed.
    if ($type) {
      if ($clear_queue) {
        unset($_SESSION['messages'][$type]);
      }
      if (isset($messages[$type])) {
        return array($type => $messages[$type]);
      }
    }
    else {
      if ($clear_queue) {
        unset($_SESSION['messages']);
      }
      return $messages;
    }
  }
  return array();
}
?>

Modules can then implement the hook as follows:

<?php
function hook_message_alter(&$messages) {
  unset($messages['status']['example_message_id']);
  $messages['error']['example_message_id2'] = 'My altered message to display';
}
?>

This would provide us the ability to unset and override core/contrib messages with having to do the work around of trying to grab the $_SESSION['messages'] variable and unsetting messages in that.

Now to be honest this wil require a good amount of patch work as right now api.d.o shows 218 functions calling drupal_set_message and all those will have to be rewritten to add message_ids but this is one of those features that will continue to make Drupal more flexible by allowing overriding of core code without having to hack it. If, as Drupal 7 comes out and we get started on D8, there is support from core maintainers for this feature then I will be happy to work on all the patches for it.

arcaneadam’s picture

I also wanted to address the theme_status_messages issue raised in #25, that this function calls $messages[0] if there is only one. So my proposal then is to remove the need to know the array key and just use array_shift($messages) that way we grab the first message but don't need to know what the array key is for it.

<?php
<?php
function theme_status_messages($variables) {
  $display = $variables['display'];
  $output = '';

  $status_heading = array(
    'status' => t('Status message'),
    'error' => t('Error message'),
    'warning' => t('Warning message'),
  );
  foreach (drupal_get_messages($display) as $type => $messages) {
    $output .= "<div class=\"messages $type\">\n";
    if (!empty($status_heading[$type])) {
      $output .= '<h2 class="element-invisible">' . $status_heading[$type] . "</h2>\n";
    }
    if (count($messages) > 1) {
      $output .= " <ul>\n";
      foreach ($messages as $message) {
        $output .= '  <li>' . $message . "</li>\n";
      }
      $output .= " </ul>\n";
    }
    else {
      $output .= array_shift($messages);
    }
    $output .= "</div>\n";
  }
  return $output;
}
?>
Xano’s picture

I guess I am not following what sun is saying, the drupal_mail module is not and as far as I know wouldn't ever replace drupal_set_message.

With a generalised message API we can also offer generalised hooks for modifying and processing messages, whether they be PMs, e-mails or messages that are currently set using drupal_set_message().

jim0203’s picture

subscrabulating

marc.groth’s picture

+1 for this

Would be very useful

lut4rp’s picture

Want. Gimmeh.

lut4rp’s picture

Hm, as per sun's thoughts on merging this with drupal_mail, posting #800434: drupal_mail, allow hook_mail_alter implementation to cancel mail for reference. If done properly, it gives us a way to "unset" messages as well.

larowlan’s picture

gman, put me down to help with this one.

kenorb’s picture

In Drupal 6.x it was achieved by Drupal Tweaks module by replacing theme for drupal_set_message.
See: http://drupalcode.org/project/drupal_tweaks.git/blame/refs/heads/6.x-1.x...
function theme_status_messages_dt($display = NULL) {

    drupal_alter('status_messages', $_SESSION['messages']);

Basically it can be achieved by adding one line into drupal_set_message()

corbacho’s picture

.

ebeyrent’s picture

This looks like a small change with a lot of benefit. It's tough when a simple change like this languishes for years.

geerlingguy’s picture

Subscribing, and hoping that I can someday block some messages, change others, etc., without doing anything too hackish.

Xano’s picture

@Geerlingguy: there's a big green button right next to the issue description that should be used for subscribing.

geerlingguy’s picture

Yes, I understand, and advocate its use. However, sometimes posting a comment to nudge the issue up in others' queues will give the issue more visibility (since it's been months since the last post), and I want to emphasize that the only way to not show messages right now is to do it hackishly with a theme registry alter (which messes things up if you use something like absolute messages), or hacking core. Save the kittens!

pedrorocha’s picture

Looking in this issue, i'm not sure about what is the next step to have this accomplished. So many alternatives were given, but this issue have more than 5 years, the Drupal version changed from 5 to 8 and nothing...

Maybe this seems to be a small question, that will only cleanup the code from the hacks, for the ones who uses Drupal in languages that doesn't pay much attention to gender in sentences, but is a PITA for projects that needs to worry about those other languages that does, because the sentences becomes totally inappropriate. Saying this, is an important issue for the Drupal project itself, to be able to satisfy a wider audience.

Does anybody have some idea on how to solve this, and maybe the only thing that lacks is time to code?

larowlan’s picture

Issue tags: +WSCCI

I've seen it proposed to use symfony session handling/flash to replace drupal_set_message.
Not sure where that would leave this.
Tagging this to get it on WSCCI radar.

jim0203’s picture

I've written a module that provides this functionality for Drupal 6 and 7, essentially by providing a UI for the Status Messages Alter module (this is rolled in to the Drupal 7 version of the module I've released, as the maintainer of Status Messages Alter didn't seem to be creating an official release of that module for Drupal 7).

So, should I create a Drupal 8 version as well, or is (any of) this functionality going to be included in Drupal 8?

Chandan Chaudhary’s picture

Status: Needs work » Needs review
Issue tags: -WSCCI

#42: hook_message_alter_6.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, hook_message_alter_6.patch, failed testing.

penyaskito’s picture

Mmmmmm too late for Drupal8?

Anonymous’s picture

I just wanted to create a Drupal 8 issue about this.

I'm upgrading a custom Drupal 7 distro into Drupal 8 and in order to change the messages I had to designate a whole separate file of unnecessary code to it.

A good example is that my users have no idea what the word "term" mean but they understand "category". In order to change this one word I had to write hundreds of line of totally unnecessary code because of not being able to alter the messages(of course I didn't want to access messagess directly in session nor the theme function, it can be done though).

So I tihnk this should be finally present in Drupal 8. Too much time went by and this is needed for everyone making a distro or any advanced installation.

I think the messages should be identified by a unique id that they provide themselves because it's more important where the message is comming from than what it's saying. Also this would solve any problems with multilingual sites.

penyaskito’s picture

@ivanjaros: For the problem you are talking about, I think you can use string overrides or enable English translation (new feature available in D8).

Of course this could be a very useful feature, but I wanted to be sure that you knew the workaround.

penyaskito’s picture

Issue tags: +Needs tests, +DX (Developer Experience)
FileSize
2.53 KB

Rerolled #42. Just wondering what could happen.

penyaskito’s picture

Issue summary: View changes
penyaskito’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 78: 127262-78.patch, failed testing.

Xano’s picture

I just wanted to create a Drupal 8 issue about this.

I'm upgrading a custom Drupal 7 distro into Drupal 8 and in order to change the messages I had to designate a whole separate file of unnecessary code to it.

A good example is that my users have no idea what the word "term" mean but they understand "category". In order to change this one word I had to write hundreds of line of totally unnecessary code because of not being able to alter the messages(of course I didn't want to access messagess directly in session nor the theme function, it can be done though).

So I tihnk this should be finally present in Drupal 8. Too much time went by and this is needed for everyone making a distro or any advanced installation.

I think the messages should be identified by a unique id that they provide themselves because it's more important where the message is comming from than what it's saying. Also this would solve any problems with multilingual sites.

This is a very bad example, as jargon such as term shows up in many different places, with these messages just being one of those. If your users don't understand this, you either need to train them, or simply translate the source strings through the existing l10n solutions.

Rerolled #42. Just wondering what could happen.

In case anyone wants to work on this again: this needs to be documented in system.api.php.

pedrorocha’s picture

Does this still make sense(a new hook) in the new D8 approach, with classes, plugins, etc? I'm seeing some things about Symfony "Flash Messages" and D8 is using it already, BTW.

Anonymous’s picture

Any recommended workaround for Drupal 8?

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jhedstrom’s picture

Status: Needs work » Closed (won't fix)

Now that that drupal_set_message() has been deprecated and replaced by a proper service, contrib or custom modules can either swap that service out to one that provides an alter hook, or just directly alter messages as needed. The service can either be completely swapped out or overridden via the decorator pattern.

Tentatively closing this out, but it could be re-opened if an alter hook would still be preferable.