Commit 32f3ff65 authored by lpsolit%gmail.com's avatar lpsolit%gmail.com

Bug 297186: Send emails in the recipient's locale, not the current user's -…

Bug 297186: Send emails in the recipient's locale, not the current user's - Patch by Fré©ric Buclin <LpSolit@gmail.com> r=bkor a=justdave
parent 36540893
......@@ -146,14 +146,17 @@ init_page() if !$ENV{MOD_PERL};
sub template {
my $class = shift;
request_cache()->{language} = "";
request_cache()->{template} ||= Bugzilla::Template->create();
return request_cache()->{template};
}
sub template_inner {
my $class = shift;
$class->request_cache->{template_inner} ||= Bugzilla::Template->create();
return $class->request_cache->{template_inner};
my ($class, $lang) = @_;
$lang = defined($lang) ? $lang : (request_cache()->{language} || "");
request_cache()->{language} = $lang;
request_cache()->{"template_inner_$lang"} ||= Bugzilla::Template->create();
return request_cache()->{"template_inner_$lang"};
}
sub cgi {
......@@ -497,7 +500,10 @@ The current C<Template> object, to be used for output
=item C<template_inner>
If you ever need a L<Bugzilla::Template> object while you're already
processing a template, use this.
processing a template, use this. Also use it if you want to specify
the language to use. If no argument is passed, it uses the last
language set. If the argument is "" (empty string), the language is
reset to the current one (the one used by Bugzilla->template).
=item C<cgi>
......
......@@ -1405,7 +1405,7 @@ sub ValidateTime {
}
sub GetComments {
my ($id, $comment_sort_order, $start, $end) = @_;
my ($id, $comment_sort_order, $start, $end, $raw) = @_;
my $dbh = Bugzilla->dbh;
$comment_sort_order = $comment_sort_order ||
......@@ -1438,21 +1438,9 @@ sub GetComments {
$comment{'email'} .= Bugzilla->params->{'emailsuffix'};
$comment{'name'} = $comment{'name'} || $comment{'email'};
if ($comment{'type'} == CMT_DUPE_OF) {
$comment{'body'} .= "\n\n" . get_text('bug_duplicate_of',
{ dupe_of => $comment{'extra_data'} });
}
elsif ($comment{'type'} == CMT_HAS_DUPE) {
$comment{'body'} = get_text('bug_has_duplicate',
{ dupe => $comment{'extra_data'} });
}
elsif ($comment{'type'} == CMT_POPULAR_VOTES) {
$comment{'body'} = get_text('bug_confirmed_by_votes');
}
elsif ($comment{'type'} == CMT_MOVED_TO) {
$comment{'body'} .= "\n\n" . get_text('bug_moved_to',
{ login => $comment{'extra_data'} });
}
# If raw data is requested, do not format 'special' comments.
$comment{'body'} = format_comment(\%comment) unless $raw;
push (@comments, \%comment);
}
......@@ -1464,6 +1452,32 @@ sub GetComments {
return \@comments;
}
# Format language specific comments. This routine must not update
# $comment{'body'} itself, see BugMail::prepare_comments().
sub format_comment {
my $comment = shift;
my $body;
if ($comment->{'type'} == CMT_DUPE_OF) {
$body = $comment->{'body'} . "\n\n" .
get_text('bug_duplicate_of', { dupe_of => $comment->{'extra_data'} });
}
elsif ($comment->{'type'} == CMT_HAS_DUPE) {
$body = get_text('bug_has_duplicate', { dupe => $comment->{'extra_data'} });
}
elsif ($comment->{'type'} == CMT_POPULAR_VOTES) {
$body = get_text('bug_confirmed_by_votes');
}
elsif ($comment->{'type'} == CMT_MOVED_TO) {
$body = $comment->{'body'} . "\n\n" .
get_text('bug_moved_to', { login => $comment->{'extra_data'} });
}
else {
$body = $comment->{'body'};
}
return $body;
}
# Get the activity of a bug, starting from $starttime (if given).
# This routine assumes ValidateBugID has been previously called.
sub GetBugActivity {
......
......@@ -313,7 +313,7 @@ sub Send {
}
my ($newcomments, $anyprivate) = get_comments_by_bug($id, $start, $end);
my ($raw_comments, $anyprivate, $count) = get_comments_by_bug($id, $start, $end);
###########################################################################
# Start of email filtering code
......@@ -408,6 +408,9 @@ sub Send {
my @sent;
my @excluded;
# Some comments are language specific. We cache them here.
my %comments;
foreach my $user_id (keys %recipients) {
my %rels_which_want;
my $sent_mail = 0;
......@@ -416,15 +419,24 @@ sub Send {
# Deleted users must be excluded.
next unless $user;
if ($user->can_see_bug($id))
{
# What's the language chosen by this user for email?
my $lang = $user->settings->{'lang'}->{'value'};
if ($user->can_see_bug($id)) {
# It's time to format language specific comments.
unless (exists $comments{$lang}) {
Bugzilla->template_inner($lang);
$comments{$lang} = prepare_comments($raw_comments, $count);
Bugzilla->template_inner("");
}
# Go through each role the user has and see if they want mail in
# that role.
foreach my $relationship (keys %{$recipients{$user_id}}) {
if ($user->wants_bug_mail($id,
$relationship,
$diffs,
$newcomments,
$comments{$lang},
$changer,
!$start))
{
......@@ -471,7 +483,7 @@ sub Send {
\%defmailhead,
\%fielddescription,
\@diffparts,
$newcomments,
$comments{$lang},
$anyprivate,
$start,
$id,
......@@ -634,16 +646,17 @@ sub sendMail {
};
my $msg;
my $template = Bugzilla->template_inner;
my $template = Bugzilla->template_inner($user->settings->{'lang'}->{'value'});
$template->process("email/newchangedmail.txt.tmpl", $vars, \$msg)
|| ThrowTemplateError($template->error());
Bugzilla->template_inner("");
MessageToMTA($msg);
return 1;
}
# Get bug comments for the given period and format them to be used in emails.
# Get bug comments for the given period.
sub get_comments_by_bug {
my ($id, $start, $end) = @_;
my $dbh = Bugzilla->dbh;
......@@ -661,22 +674,35 @@ sub get_comments_by_bug {
undef, ($id, $start));
}
my $comments = Bugzilla::Bug::GetComments($id, "oldest_to_newest", $start, $end);
my $raw = 1; # Do not format comments which are not of type CMT_NORMAL.
my $comments = Bugzilla::Bug::GetComments($id, "oldest_to_newest", $start, $end, $raw);
if (Bugzilla->params->{'insidergroup'}) {
$anyprivate = 1 if scalar(grep {$_->{'isprivate'} > 0} @$comments);
}
return ($comments, $anyprivate, $count);
}
# Prepare comments for the given language.
sub prepare_comments {
my ($raw_comments, $count) = @_;
foreach my $comment (@$comments) {
my $result = "";
foreach my $comment (@$raw_comments) {
if ($count) {
$result .= "\n\n--- Comment #$count from " . $comment->{'name'} . " <" .
$comment->{'email'} . Bugzilla->params->{'emailsuffix'} . "> " .
format_time($comment->{'time'}) . " ---\n";
}
if ($comment->{'isprivate'} > 0 && Bugzilla->params->{'insidergroup'}) {
$anyprivate = 1;
}
$result .= ($comment->{'already_wrapped'} ? $comment->{'body'}
: wrap_comment($comment->{'body'}));
# Format language specific comments. We don't update $comment->{'body'}
# directly, otherwise it would grow everytime you call format_comment()
# with a different language as some text may be appended to the existing one.
my $body = Bugzilla::Bug::format_comment($comment);
$result .= ($comment->{'already_wrapped'} ? $body : wrap_comment($body));
$count++;
}
return ($result, $anyprivate);
return $result;
}
1;
......@@ -35,7 +35,8 @@ use Bugzilla::User::Setting;
use Bugzilla::Util qw(get_text);
use Bugzilla::Version;
use constant SETTINGS => {
sub SETTINGS {
return {
# 2005-03-03 travis@sedsystems.ca -- Bug 41972
display_quips => { options => ["on", "off"], default => "on" },
# 2005-03-10 travis@sedsystems.ca -- Bug 199048
......@@ -56,7 +57,10 @@ use constant SETTINGS => {
default => 'cc_unless_role' },
# 2006-08-04 wurblzap@gmail.com -- Bug 322693
skin => { subclass => 'Skin', default => 'standard' },
# 2006-12-10 LpSolit@gmail.com -- Bug 297186
lang => { options => [split(/[\s,]+/, Bugzilla->params->{'languages'})],
default => Bugzilla->params->{'defaultlanguage'} }
}
};
use constant SYSTEM_GROUPS => (
......
......@@ -108,9 +108,10 @@ sub sortAcceptLanguage {
# If no Accept-Language is present it uses the defined default
# Templates may also be found in the extensions/ tree
sub getTemplateIncludePath {
my $lang = Bugzilla->request_cache->{'language'} || "";
# Return cached value if available
my $include_path = Bugzilla->request_cache->{template_include_path};
my $include_path = Bugzilla->request_cache->{"template_include_path_$lang"};
return $include_path if $include_path;
my $templatedir = bz_locations()->{'templatedir'};
......@@ -132,15 +133,16 @@ sub getTemplateIncludePath {
}
}
my @languages = sortAcceptLanguage($languages);
my @accept_language = sortAcceptLanguage($ENV{'HTTP_ACCEPT_LANGUAGE'} || "" );
# If $lang is specified, only consider this language.
my @accept_language = ($lang) || sortAcceptLanguage($ENV{'HTTP_ACCEPT_LANGUAGE'} || "");
my @usedlanguages;
foreach my $lang (@accept_language) {
foreach my $language (@accept_language) {
# Per RFC 1766 and RFC 2616 any language tag matches also its
# primary tag. That is 'en' (accept language) matches 'en-us',
# 'en-uk' etc. but not the otherway round. (This is unfortunately
# not very clearly stated in those RFC; see comment just over 14.5
# in http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4)
if(my @found = grep /^\Q$lang\E(-.+)?$/i, @languages) {
if(my @found = grep /^\Q$language\E(-.+)?$/i, @languages) {
push (@usedlanguages, @found);
}
}
......@@ -180,9 +182,9 @@ sub getTemplateIncludePath {
foreach my $dir (@$include_path) {
push(@dirs, $dir) unless grep ($dir eq $_, @dirs);
}
Bugzilla->request_cache->{template_include_path} = \@dirs;
Bugzilla->request_cache->{"template_include_path_$lang"} = \@dirs;
return Bugzilla->request_cache->{template_include_path};
return Bugzilla->request_cache->{"template_include_path_$lang"};
}
sub put_header {
......@@ -527,7 +529,7 @@ sub create {
# We need a possibility to reset the cache, so that no files from
# the previous language pollute the action.
if ($opts{'clean_cache'}) {
delete Bugzilla->request_cache->{template_include_path};
delete Bugzilla->request_cache->{template_include_path_};
}
# IMPORTANT - If you make any configuration changes here, make sure to
......
......@@ -15,7 +15,7 @@
# Contributor(s): Shane H. W. Travis <travis@sedsystems.ca>
# Max Kanat-Alexander <mkanat@bugzilla.org>
# Marc Schumann <wurblzap@gmail.com>
#
# Frédéric Buclin <LpSolit@gmail.com>
package Bugzilla::User::Setting;
......@@ -128,15 +128,28 @@ sub new {
###############################
sub add_setting {
my ($name, $values, $default_value, $subclass) = @_;
my ($name, $values, $default_value, $subclass, $force_check) = @_;
my $dbh = Bugzilla->dbh;
return if _setting_exists($name);
my $exists = _setting_exists($name);
return if ($exists && !$force_check);
($name && $default_value)
|| ThrowCodeError("setting_info_invalid");
print get_text('install_setting_new', { name => $name }) . "\n";
if ($exists) {
# If this setting exists, we delete it and regenerate it.
$dbh->do('DELETE FROM setting_value WHERE name = ?', undef, $name);
$dbh->do('DELETE FROM setting WHERE name = ?', undef, $name);
# Remove obsolete user preferences for this setting.
my $list = join(', ', map {$dbh->quote($_)} @$values);
$dbh->do("DELETE FROM profile_setting
WHERE setting_name = ? AND setting_value NOT IN ($list)",
undef, $name);
}
else {
print get_text('install_setting_new', { name => $name }) . "\n";
}
$dbh->do(q{INSERT INTO setting (name, default_value, is_enabled, subclass)
VALUES (?, ?, 1, ?)},
undef, ($name, $default_value, $subclass));
......
......@@ -33,6 +33,7 @@ use Bugzilla::Util;
use Bugzilla::Error;
use Bugzilla::Token;
use Bugzilla::User;
use Bugzilla::User::Setting;
my $user = Bugzilla->login(LOGIN_REQUIRED);
my $cgi = Bugzilla->cgi;
......@@ -73,6 +74,7 @@ if ($action eq 'save' && $current_module) {
my @changes = ();
my @module_param_list = "Bugzilla::Config::${current_module}"->get_param_list(1);
my $update_lang_user_pref = 0;
foreach my $i (@module_param_list) {
my $name = $i->{'name'};
my $value = $cgi->param($name);
......@@ -132,8 +134,20 @@ if ($action eq 'save' && $current_module) {
if (($name eq "shutdownhtml") && ($value ne "")) {
$vars->{'shutdown_is_active'} = 1;
}
if ($name eq 'languages') {
$update_lang_user_pref = 1;
}
}
}
if ($update_lang_user_pref) {
# We have to update the list of languages users can choose.
# If some users have selected a language which is no longer available,
# then we delete it (the user pref is reset to the default one).
my @languages = split(/[\s,]+/, Bugzilla->params->{'languages'});
map {trick_taint($_)} @languages;
add_setting('lang', \@languages, Bugzilla->params->{'defaultlanguage'}, undef, 1);
}
$vars->{'message'} = 'parameters_updated';
$vars->{'param_changed'} = \@changes;
......
......@@ -40,5 +40,6 @@
"always" => "Always",
"never" => "Never",
"cc_unless_role" => "Only if I have no role on them",
"lang" => "Language used in email",
}
%]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment