]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 297186: Send emails in the recipient's locale, not the current user's - Patch...
authorlpsolit%gmail.com <>
Tue, 12 Dec 2006 02:00:46 +0000 (02:00 +0000)
committerlpsolit%gmail.com <>
Tue, 12 Dec 2006 02:00:46 +0000 (02:00 +0000)
Bugzilla.pm
Bugzilla/Bug.pm
Bugzilla/BugMail.pm
Bugzilla/Install.pm
Bugzilla/Template.pm
Bugzilla/User/Setting.pm
editparams.cgi
template/en/default/global/setting-descs.none.tmpl

index 32f731859cdbd1218461ba6bffb85b0e2600eca8..f278adb2e934aaad6c4301d5749c69fbbaa7ac6b 100644 (file)
@@ -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>
 
index f09386a0c1c006c143c7b02bf064a91936273519..469b6ff6066b09a3dc8f65f49e0573a5f9efc419 100755 (executable)
@@ -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 {
index 6ba6b3c7710f58d62760aba14ca2fa89bbb498c1..6e0f57401f211934d4f382103110b435f46d7f7c 100644 (file)
@@ -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;
index c31bb58dff237da8e04645245a558e455ffec45d..218ee63594691c96658973d2d44d23ce7824e48a 100644 (file)
@@ -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 => (
index ed6880b0176686675fb5357498658f3245cac7ce..608d35fcb96271b90df90631613a37dfc67166ad 100644 (file)
@@ -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
index ad39d194bc32bedf3c738709a241da47d9229063..bdc653b9765f7795b954077f0a2209fa3c6016b3 100644 (file)
@@ -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));
index 80b458d909a77e57123c3cb61795dc72af6c87f4..ca74df6853295de8eb2ccfb8a86537b6c5e6964c 100755 (executable)
@@ -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;
 
index 4fb2a031b51be8f164489f69011b999b2e47dd79..e62ec0b63b114ad254b5fb3ca9952e558d9883e5 100644 (file)
@@ -40,5 +40,6 @@
    "always"                           => "Always",
    "never"                            => "Never",
    "cc_unless_role"                   => "Only if I have no role on them",
+   "lang"                             => "Language used in email",
                    } 
 %]