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 {
=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>
}
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 ||
$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);
}
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 {
}
- 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
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;
# 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))
{
\%defmailhead,
\%fielddescription,
\@diffparts,
- $newcomments,
+ $comments{$lang},
$anyprivate,
$start,
$id,
};
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;
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;
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
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 => (
# 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'};
}
}
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);
}
}
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 {
# 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
# 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;
###############################
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));
use Bugzilla::Error;
use Bugzilla::Token;
use Bugzilla::User;
+use Bugzilla::User::Setting;
my $user = Bugzilla->login(LOGIN_REQUIRED);
my $cgi = Bugzilla->cgi;
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);
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;
"always" => "Always",
"never" => "Never",
"cc_unless_role" => "Only if I have no role on them",
+ "lang" => "Language used in email",
}
%]