Yeah, of course it's from my side. It's a simple str_replace(); on all of the variables. So to get join reason in scope it may be more than using a $context variable or something. The variables that are provided are variables that are already in scope, or already available for use in the template(s) already.
Look in one of the edits for a str_replace(); there are two arrays, one is 'searches', and one is 'replaces'. An example would be: $message_body = str_replace(array('{USERNAME}', '{REALNAME}'), array($context['member']['name'], $context['member']['real_name']), $message_body);