Merge branch 'va/i18n-perl-scripts'

Porcelain scripts written in Perl are getting internationalized.

* va/i18n-perl-scripts:
  i18n: difftool: mark warnings for translation
  i18n: send-email: mark composing message for translation
  i18n: send-email: mark string with interpolation for translation
  i18n: send-email: mark warnings and errors for translation
  i18n: send-email: mark strings for translation
  i18n: add--interactive: mark status words for translation
  i18n: add--interactive: remove %patch_modes entries
  i18n: add--interactive: mark edit_hunk_manually message for translation
  i18n: add--interactive: i18n of help_patch_cmd
  i18n: add--interactive: mark patch prompt for translation
  i18n: add--interactive: mark plural strings
  i18n: clean.c: match string with git-add--interactive.perl
  i18n: add--interactive: mark strings with interpolation for translation
  i18n: add--interactive: mark simple here-documents for translation
  i18n: add--interactive: mark strings for translation
  Git.pm: add subroutines for commenting lines
This commit is contained in:
Junio C Hamano 2016-12-27 00:11:40 -08:00
commit 1d73f8e86d
8 changed files with 408 additions and 218 deletions

View file

@ -2105,7 +2105,8 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \
--keyword=_ --keyword=N_ --keyword="Q_:1,2"
XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \
--keyword=gettextln --keyword=eval_gettextln
XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl
XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \
--keyword=__ --keyword=N__ --keyword="__n:1,2"
LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
LOCALIZED_SH = $(SCRIPT_SH)
LOCALIZED_SH += git-parse-remote.sh

View file

@ -287,11 +287,11 @@ static void pretty_print_menus(struct string_list *menu_list)
static void prompt_help_cmd(int singleton)
{
clean_print_color(CLEAN_COLOR_HELP);
printf_ln(singleton ?
printf(singleton ?
_("Prompt help:\n"
"1 - select a numbered item\n"
"foo - select item based on unique prefix\n"
" - (empty) select nothing") :
" - (empty) select nothing\n") :
_("Prompt help:\n"
"1 - select a single item\n"
"3-5 - select a range of items\n"
@ -299,7 +299,7 @@ static void prompt_help_cmd(int singleton)
"foo - select item based on unique prefix\n"
"-... - unselect specified items\n"
"* - choose all items\n"
" - (empty) finish selecting"));
" - (empty) finish selecting\n"));
clean_print_color(CLEAN_COLOR_RESET);
}
@ -508,7 +508,7 @@ static int parse_choice(struct menu_stuff *menu_stuff,
if (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||
(is_single && bottom != top)) {
clean_print_color(CLEAN_COLOR_ERROR);
printf_ln(_("Huh (%s)?"), (*ptr)->buf);
printf(_("Huh (%s)?\n"), (*ptr)->buf);
clean_print_color(CLEAN_COLOR_RESET);
continue;
}
@ -774,7 +774,7 @@ static int ask_each_cmd(void)
static int quit_cmd(void)
{
string_list_clear(&del_list, 0);
printf_ln(_("Bye."));
printf(_("Bye.\n"));
return MENU_RETURN_NO_LOOP;
}

View file

@ -4,6 +4,7 @@
use strict;
use warnings;
use Git;
use Git::I18N;
binmode(STDOUT, ":raw");
@ -92,6 +93,7 @@ sub colored {
}
# command line options
my $cmd;
my $patch_mode;
my $patch_mode_revision;
@ -104,9 +106,6 @@ sub colored {
DIFF => 'diff-files -p',
APPLY => sub { apply_patch 'apply --cached', @_; },
APPLY_CHECK => 'apply --cached',
VERB => 'Stage',
TARGET => '',
PARTICIPLE => 'staging',
FILTER => 'file-only',
IS_REVERSE => 0,
},
@ -114,9 +113,6 @@ sub colored {
DIFF => 'diff-index -p HEAD',
APPLY => sub { apply_patch 'apply --cached', @_; },
APPLY_CHECK => 'apply --cached',
VERB => 'Stash',
TARGET => '',
PARTICIPLE => 'stashing',
FILTER => undef,
IS_REVERSE => 0,
},
@ -124,9 +120,6 @@ sub colored {
DIFF => 'diff-index -p --cached',
APPLY => sub { apply_patch 'apply -R --cached', @_; },
APPLY_CHECK => 'apply -R --cached',
VERB => 'Unstage',
TARGET => '',
PARTICIPLE => 'unstaging',
FILTER => 'index-only',
IS_REVERSE => 1,
},
@ -134,9 +127,6 @@ sub colored {
DIFF => 'diff-index -R -p --cached',
APPLY => sub { apply_patch 'apply --cached', @_; },
APPLY_CHECK => 'apply --cached',
VERB => 'Apply',
TARGET => ' to index',
PARTICIPLE => 'applying',
FILTER => 'index-only',
IS_REVERSE => 0,
},
@ -144,9 +134,6 @@ sub colored {
DIFF => 'diff-files -p',
APPLY => sub { apply_patch 'apply -R', @_; },
APPLY_CHECK => 'apply -R',
VERB => 'Discard',
TARGET => ' from worktree',
PARTICIPLE => 'discarding',
FILTER => 'file-only',
IS_REVERSE => 1,
},
@ -154,9 +141,6 @@ sub colored {
DIFF => 'diff-index -p',
APPLY => sub { apply_patch_for_checkout_commit '-R', @_ },
APPLY_CHECK => 'apply -R',
VERB => 'Discard',
TARGET => ' from index and worktree',
PARTICIPLE => 'discarding',
FILTER => undef,
IS_REVERSE => 1,
},
@ -164,15 +148,13 @@ sub colored {
DIFF => 'diff-index -R -p',
APPLY => sub { apply_patch_for_checkout_commit '', @_ },
APPLY_CHECK => 'apply',
VERB => 'Apply',
TARGET => ' to index and worktree',
PARTICIPLE => 'applying',
FILTER => undef,
IS_REVERSE => 0,
},
);
my %patch_mode_flavour = %{$patch_modes{stage}};
$patch_mode = 'stage';
my %patch_mode_flavour = %{$patch_modes{$patch_mode}};
sub run_cmd_pipe {
if ($^O eq 'MSWin32') {
@ -253,8 +235,9 @@ sub list_untracked {
run_cmd_pipe(qw(git ls-files --others --exclude-standard --), @ARGV);
}
my $status_fmt = '%12s %12s %s';
my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');
# TRANSLATORS: you can adjust this to align "git add -i" status menu
my $status_fmt = __('%12s %12s %s');
my $status_head = sprintf($status_fmt, __('staged'), __('unstaged'), __('path'));
{
my $initial;
@ -312,7 +295,7 @@ sub list_modified {
my ($change, $bin);
$file = unquote_path($file);
if ($add eq '-' && $del eq '-') {
$change = 'binary';
$change = __('binary');
$bin = 1;
}
else {
@ -321,7 +304,7 @@ sub list_modified {
$data{$file} = {
INDEX => $change,
BINARY => $bin,
FILE => 'nothing',
FILE => __('nothing'),
}
}
elsif (($adddel, $file) =
@ -337,7 +320,7 @@ sub list_modified {
$file = unquote_path($file);
my ($change, $bin);
if ($add eq '-' && $del eq '-') {
$change = 'binary';
$change = __('binary');
$bin = 1;
}
else {
@ -357,7 +340,7 @@ sub list_modified {
$file = unquote_path($2);
if (!exists $data{$file}) {
$data{$file} = +{
INDEX => 'unchanged',
INDEX => __('unchanged'),
BINARY => 0,
};
}
@ -372,10 +355,10 @@ sub list_modified {
if ($only) {
if ($only eq 'index-only') {
next if ($it->{INDEX} eq 'unchanged');
next if ($it->{INDEX} eq __('unchanged'));
}
if ($only eq 'file-only') {
next if ($it->{FILE} eq 'nothing');
next if ($it->{FILE} eq __('nothing'));
}
}
push @return, +{
@ -613,12 +596,12 @@ sub list_and_choose {
else {
$bottom = $top = find_unique($choice, @stuff);
if (!defined $bottom) {
error_msg "Huh ($choice)?\n";
error_msg sprintf(__("Huh (%s)?\n"), $choice);
next TOPLOOP;
}
}
if ($opts->{SINGLETON} && $bottom != $top) {
error_msg "Huh ($choice)?\n";
error_msg sprintf(__("Huh (%s)?\n"), $choice);
next TOPLOOP;
}
for ($i = $bottom-1; $i <= $top-1; $i++) {
@ -637,7 +620,7 @@ sub list_and_choose {
}
sub singleton_prompt_help_cmd {
print colored $help_color, <<\EOF ;
print colored $help_color, __ <<'EOF' ;
Prompt help:
1 - select a numbered item
foo - select item based on unique prefix
@ -646,7 +629,7 @@ sub singleton_prompt_help_cmd {
}
sub prompt_help_cmd {
print colored $help_color, <<\EOF ;
print colored $help_color, __ <<'EOF' ;
Prompt help:
1 - select a single item
3-5 - select a range of items
@ -667,12 +650,18 @@ sub status_cmd {
sub say_n_paths {
my $did = shift @_;
my $cnt = scalar @_;
print "$did ";
if (1 < $cnt) {
print "$cnt paths\n";
}
else {
print "one path\n";
if ($did eq 'added') {
printf(__n("added %d path\n", "added %d paths\n",
$cnt), $cnt);
} elsif ($did eq 'updated') {
printf(__n("updated %d path\n", "updated %d paths\n",
$cnt), $cnt);
} elsif ($did eq 'reverted') {
printf(__n("reverted %d path\n", "reverted %d paths\n",
$cnt), $cnt);
} else {
printf(__n("touched %d path\n", "touched %d paths\n",
$cnt), $cnt);
}
}
@ -680,7 +669,7 @@ sub update_cmd {
my @mods = list_modified('file-only');
return if (!@mods);
my @update = list_and_choose({ PROMPT => 'Update',
my @update = list_and_choose({ PROMPT => __('Update'),
HEADER => $status_head, },
@mods);
if (@update) {
@ -692,7 +681,7 @@ sub update_cmd {
}
sub revert_cmd {
my @update = list_and_choose({ PROMPT => 'Revert',
my @update = list_and_choose({ PROMPT => __('Revert'),
HEADER => $status_head, },
list_modified());
if (@update) {
@ -715,7 +704,7 @@ sub revert_cmd {
$_->{INDEX_ADDDEL} eq 'create') {
system(qw(git update-index --force-remove --),
$_->{VALUE});
print "note: $_->{VALUE} is untracked now.\n";
printf(__("note: %s is untracked now.\n"), $_->{VALUE});
}
}
}
@ -726,13 +715,13 @@ sub revert_cmd {
}
sub add_untracked_cmd {
my @add = list_and_choose({ PROMPT => 'Add untracked' },
my @add = list_and_choose({ PROMPT => __('Add untracked') },
list_untracked());
if (@add) {
system(qw(git update-index --add --), @add);
say_n_paths('added', @add);
} else {
print "No untracked files.\n";
print __("No untracked files.\n");
}
print "\n";
}
@ -1048,29 +1037,55 @@ sub color_diff {
} @_;
}
my %edit_hunk_manually_modes = (
stage => N__(
"If the patch applies cleanly, the edited hunk will immediately be
marked for staging."),
stash => N__(
"If the patch applies cleanly, the edited hunk will immediately be
marked for stashing."),
reset_head => N__(
"If the patch applies cleanly, the edited hunk will immediately be
marked for unstaging."),
reset_nothead => N__(
"If the patch applies cleanly, the edited hunk will immediately be
marked for applying."),
checkout_index => N__(
"If the patch applies cleanly, the edited hunk will immediately be
marked for discarding"),
checkout_head => N__(
"If the patch applies cleanly, the edited hunk will immediately be
marked for discarding."),
checkout_nothead => N__(
"If the patch applies cleanly, the edited hunk will immediately be
marked for applying."),
);
sub edit_hunk_manually {
my ($oldtext) = @_;
my $hunkfile = $repo->repo_path . "/addp-hunk-edit.diff";
my $fh;
open $fh, '>', $hunkfile
or die "failed to open hunk edit file for writing: " . $!;
print $fh "# Manual hunk edit mode -- see bottom for a quick guide\n";
or die sprintf(__("failed to open hunk edit file for writing: %s"), $!);
print $fh Git::comment_lines __("Manual hunk edit mode -- see bottom for a quick guide.\n");
print $fh @$oldtext;
my $participle = $patch_mode_flavour{PARTICIPLE};
my $is_reverse = $patch_mode_flavour{IS_REVERSE};
my ($remove_plus, $remove_minus) = $is_reverse ? ('-', '+') : ('+', '-');
print $fh <<EOF;
# ---
# To remove '$remove_minus' lines, make them ' ' lines (context).
# To remove '$remove_plus' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for $participle. If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
# then the edit is aborted and the hunk is left unchanged.
my $comment_line_char = Git::get_comment_line_char;
print $fh Git::comment_lines sprintf(__ <<EOF, $remove_minus, $remove_plus, $comment_line_char),
---
To remove '%s' lines, make them ' ' lines (context).
To remove '%s' lines, delete them.
Lines starting with %s will be removed.
EOF
__($edit_hunk_manually_modes{$patch_mode}),
# TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.
__ <<EOF2 ;
If it does not apply cleanly, you will be given an opportunity to
edit again. If all lines of the hunk are removed, then the edit is
aborted and the hunk is left unchanged.
EOF2
close $fh;
chomp(my $editor = run_cmd_pipe(qw(git var GIT_EDITOR)));
@ -1081,8 +1096,8 @@ sub edit_hunk_manually {
}
open $fh, '<', $hunkfile
or die "failed to open hunk edit file for reading: " . $!;
my @newtext = grep { !/^#/ } <$fh>;
or die sprintf(__("failed to open hunk edit file for reading: %s"), $!);
my @newtext = grep { !/^$comment_line_char/ } <$fh>;
close $fh;
unlink $hunkfile;
@ -1166,22 +1181,66 @@ sub edit_hunk_loop {
}
else {
prompt_yesno(
'Your edited hunk does not apply. Edit again '
. '(saying "no" discards!) [y/n]? '
# TRANSLATORS: do not translate [y/n]
# The program will only accept that input
# at this point.
# Consider translating (saying "no" discards!) as
# (saying "n" for "no" discards!) if the translation
# of the word "no" does not start with n.
__('Your edited hunk does not apply. Edit again '
. '(saying "no" discards!) [y/n]? ')
) or return undef;
}
}
}
my %help_patch_modes = (
stage => N__(
"y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file"),
stash => N__(
"y - stash this hunk
n - do not stash this hunk
q - quit; do not stash this hunk or any of the remaining ones
a - stash this hunk and all later hunks in the file
d - do not stash this hunk or any of the later hunks in the file"),
reset_head => N__(
"y - unstage this hunk
n - do not unstage this hunk
q - quit; do not unstage this hunk or any of the remaining ones
a - unstage this hunk and all later hunks in the file
d - do not unstage this hunk or any of the later hunks in the file"),
reset_nothead => N__(
"y - apply this hunk to index
n - do not apply this hunk to index
q - quit; do not apply this hunk or any of the remaining ones
a - apply this hunk and all later hunks in the file
d - do not apply this hunk or any of the later hunks in the file"),
checkout_index => N__(
"y - discard this hunk from worktree
n - do not discard this hunk from worktree
q - quit; do not discard this hunk or any of the remaining ones
a - discard this hunk and all later hunks in the file
d - do not discard this hunk or any of the later hunks in the file"),
checkout_head => N__(
"y - discard this hunk from index and worktree
n - do not discard this hunk from index and worktree
q - quit; do not discard this hunk or any of the remaining ones
a - discard this hunk and all later hunks in the file
d - do not discard this hunk or any of the later hunks in the file"),
checkout_nothead => N__(
"y - apply this hunk to index and worktree
n - do not apply this hunk to index and worktree
q - quit; do not apply this hunk or any of the remaining ones
a - apply this hunk and all later hunks in the file
d - do not apply this hunk or any of the later hunks in the file"),
);
sub help_patch_cmd {
my $verb = lc $patch_mode_flavour{VERB};
my $target = $patch_mode_flavour{TARGET};
print colored $help_color, <<EOF ;
y - $verb this hunk$target
n - do not $verb this hunk$target
q - quit; do not $verb this hunk or any of the remaining ones
a - $verb this hunk and all later hunks in the file
d - do not $verb this hunk or any of the later hunks in the file
print colored $help_color, __($help_patch_modes{$patch_mode}), "\n", __ <<EOF ;
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
@ -1213,11 +1272,11 @@ sub apply_patch_for_checkout_commit {
run_git_apply 'apply '.$reverse, @_;
return 1;
} elsif (!$applies_index) {
print colored $error_color, "The selected hunks do not apply to the index!\n";
if (prompt_yesno "Apply them to the worktree anyway? ") {
print colored $error_color, __("The selected hunks do not apply to the index!\n");
if (prompt_yesno __("Apply them to the worktree anyway? ")) {
return run_git_apply 'apply '.$reverse, @_;
} else {
print colored $error_color, "Nothing was applied.\n";
print colored $error_color, __("Nothing was applied.\n");
return 0;
}
} else {
@ -1228,7 +1287,7 @@ sub apply_patch_for_checkout_commit {
sub patch_update_cmd {
my @all_mods = list_modified($patch_mode_flavour{FILTER});
error_msg "ignoring unmerged: $_->{VALUE}\n"
error_msg sprintf(__("ignoring unmerged: %s\n"), $_->{VALUE})
for grep { $_->{UNMERGED} } @all_mods;
@all_mods = grep { !$_->{UNMERGED} } @all_mods;
@ -1237,9 +1296,9 @@ sub patch_update_cmd {
if (!@mods) {
if (@all_mods) {
print STDERR "Only binary files changed.\n";
print STDERR __("Only binary files changed.\n");
} else {
print STDERR "No changes.\n";
print STDERR __("No changes.\n");
}
return 0;
}
@ -1247,7 +1306,7 @@ sub patch_update_cmd {
@them = @mods;
}
else {
@them = list_and_choose({ PROMPT => 'Patch update',
@them = list_and_choose({ PROMPT => __('Patch update'),
HEADER => $status_head, },
@mods);
}
@ -1297,6 +1356,44 @@ sub display_hunks {
return $i;
}
my %patch_update_prompt_modes = (
stage => {
mode => N__("Stage mode change [y,n,q,a,d,/%s,?]? "),
deletion => N__("Stage deletion [y,n,q,a,d,/%s,?]? "),
hunk => N__("Stage this hunk [y,n,q,a,d,/%s,?]? "),
},
stash => {
mode => N__("Stash mode change [y,n,q,a,d,/%s,?]? "),
deletion => N__("Stash deletion [y,n,q,a,d,/%s,?]? "),
hunk => N__("Stash this hunk [y,n,q,a,d,/%s,?]? "),
},
reset_head => {
mode => N__("Unstage mode change [y,n,q,a,d,/%s,?]? "),
deletion => N__("Unstage deletion [y,n,q,a,d,/%s,?]? "),
hunk => N__("Unstage this hunk [y,n,q,a,d,/%s,?]? "),
},
reset_nothead => {
mode => N__("Apply mode change to index [y,n,q,a,d,/%s,?]? "),
deletion => N__("Apply deletion to index [y,n,q,a,d,/%s,?]? "),
hunk => N__("Apply this hunk to index [y,n,q,a,d,/%s,?]? "),
},
checkout_index => {
mode => N__("Discard mode change from worktree [y,n,q,a,d,/%s,?]? "),
deletion => N__("Discard deletion from worktree [y,n,q,a,d,/%s,?]? "),
hunk => N__("Discard this hunk from worktree [y,n,q,a,d,/%s,?]? "),
},
checkout_head => {
mode => N__("Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? "),
deletion => N__("Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? "),
hunk => N__("Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? "),
},
checkout_nothead => {
mode => N__("Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? "),
deletion => N__("Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? "),
hunk => N__("Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? "),
},
);
sub patch_update_file {
my $quit = 0;
my ($ix, $num);
@ -1369,12 +1466,9 @@ sub patch_update_file {
for (@{$hunk[$ix]{DISPLAY}}) {
print;
}
print colored $prompt_color, $patch_mode_flavour{VERB},
($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' :
$hunk[$ix]{TYPE} eq 'deletion' ? ' deletion' :
' this hunk'),
$patch_mode_flavour{TARGET},
" [y,n,q,a,d,/$other,?]? ";
print colored $prompt_color,
sprintf(__($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}), $other);
my $line = prompt_single_character;
last unless defined $line;
if ($line) {
@ -1397,12 +1491,12 @@ sub patch_update_file {
my $response = $1;
my $no = $ix > 10 ? $ix - 10 : 0;
while ($response eq '') {
my $extra = "";
$no = display_hunks(\@hunk, $no);
if ($no < $num) {
$extra = " (<ret> to see more)";
print __("go to which hunk (<ret> to see more)? ");
} else {
print __("go to which hunk? ");
}
print "go to which hunk$extra? ";
$response = <STDIN>;
if (!defined $response) {
$response = '';
@ -1410,11 +1504,13 @@ sub patch_update_file {
chomp $response;
}
if ($response !~ /^\s*\d+\s*$/) {
error_msg "Invalid number: '$response'\n";
error_msg sprintf(__("Invalid number: '%s'\n"),
$response);
} elsif (0 < $response && $response <= $num) {
$ix = $response - 1;
} else {
error_msg "Sorry, only $num hunks available.\n";
error_msg sprintf(__n("Sorry, only %d hunk available.\n",
"Sorry, only %d hunks available.\n", $num), $num);
}
next;
}
@ -1439,7 +1535,7 @@ sub patch_update_file {
elsif ($line =~ m|^/(.*)|) {
my $regex = $1;
if ($1 eq "") {
print colored $prompt_color, "search for regex? ";
print colored $prompt_color, __("search for regex? ");
$regex = <STDIN>;
if (defined $regex) {
chomp $regex;
@ -1452,7 +1548,7 @@ sub patch_update_file {
if ($@) {
my ($err,$exp) = ($@, $1);
$err =~ s/ at .*git-add--interactive line \d+, <STDIN> line \d+.*$//;
error_msg "Malformed search regexp $exp: $err\n";
error_msg sprintf(__("Malformed search regexp %s: %s\n"), $exp, $err);
next;
}
my $iy = $ix;
@ -1462,7 +1558,7 @@ sub patch_update_file {
$iy++;
$iy = 0 if ($iy >= $num);
if ($ix == $iy) {
error_msg "No hunk matches the given pattern\n";
error_msg __("No hunk matches the given pattern\n");
last;
}
}
@ -1474,7 +1570,7 @@ sub patch_update_file {
$ix--;
}
else {
error_msg "No previous hunk\n";
error_msg __("No previous hunk\n");
}
next;
}
@ -1483,7 +1579,7 @@ sub patch_update_file {
$ix++;
}
else {
error_msg "No next hunk\n";
error_msg __("No next hunk\n");
}
next;
}
@ -1496,21 +1592,23 @@ sub patch_update_file {
}
}
else {
error_msg "No previous hunk\n";
error_msg __("No previous hunk\n");
}
next;
}
elsif ($line =~ /^j/) {
if ($other !~ /j/) {
error_msg "No next hunk\n";
error_msg __("No next hunk\n");
next;
}
}
elsif ($other =~ /s/ && $line =~ /^s/) {
my @split = split_hunk($hunk[$ix]{TEXT}, $hunk[$ix]{DISPLAY});
if (1 < @split) {
print colored $header_color, "Split into ",
scalar(@split), " hunks.\n";
print colored $header_color, sprintf(
__n("Split into %d hunk.\n",
"Split into %d hunks.\n",
scalar(@split)), scalar(@split));
}
splice (@hunk, $ix, 1, @split);
$num = scalar @hunk;
@ -1560,23 +1658,25 @@ sub diff_cmd {
my @mods = list_modified('index-only');
@mods = grep { !($_->{BINARY}) } @mods;
return if (!@mods);
my (@them) = list_and_choose({ PROMPT => 'Review diff',
my (@them) = list_and_choose({ PROMPT => __('Review diff'),
IMMEDIATE => 1,
HEADER => $status_head, },
@mods);
return if (!@them);
my $reference = is_initial_commit() ? get_empty_tree() : 'HEAD';
my $reference = (is_initial_commit()) ? get_empty_tree() : 'HEAD';
system(qw(git diff -p --cached), $reference, '--',
map { $_->{VALUE} } @them);
}
sub quit_cmd {
print "Bye.\n";
print __("Bye.\n");
exit(0);
}
sub help_cmd {
print colored $help_color, <<\EOF ;
# TRANSLATORS: please do not translate the command names
# 'status', 'update', 'revert', etc.
print colored $help_color, __ <<'EOF' ;
status - show paths with changes
update - add working tree state to the staged set of changes
revert - revert staged set of changes back to the HEAD version
@ -1594,39 +1694,40 @@ sub process_args {
if ($1 eq 'reset') {
$patch_mode = 'reset_head';
$patch_mode_revision = 'HEAD';
$arg = shift @ARGV or die "missing --";
$arg = shift @ARGV or die __("missing --");
if ($arg ne '--') {
$patch_mode_revision = $arg;
$patch_mode = ($arg eq 'HEAD' ?
'reset_head' : 'reset_nothead');
$arg = shift @ARGV or die "missing --";
$arg = shift @ARGV or die __("missing --");
}
} elsif ($1 eq 'checkout') {
$arg = shift @ARGV or die "missing --";
$arg = shift @ARGV or die __("missing --");
if ($arg eq '--') {
$patch_mode = 'checkout_index';
} else {
$patch_mode_revision = $arg;
$patch_mode = ($arg eq 'HEAD' ?
'checkout_head' : 'checkout_nothead');
$arg = shift @ARGV or die "missing --";
$arg = shift @ARGV or die __("missing --");
}
} elsif ($1 eq 'stage' or $1 eq 'stash') {
$patch_mode = $1;
$arg = shift @ARGV or die "missing --";
$arg = shift @ARGV or die __("missing --");
} else {
die "unknown --patch mode: $1";
die sprintf(__("unknown --patch mode: %s"), $1);
}
} else {
$patch_mode = 'stage';
$arg = shift @ARGV or die "missing --";
$arg = shift @ARGV or die __("missing --");
}
die "invalid argument $arg, expecting --"
unless $arg eq "--";
die sprintf(__("invalid argument %s, expecting --"),
$arg) unless $arg eq "--";
%patch_mode_flavour = %{$patch_modes{$patch_mode}};
$cmd = 1;
}
elsif ($arg ne "--") {
die "invalid argument $arg, expecting --";
die sprintf(__("invalid argument %s, expecting --"), $arg);
}
}
@ -1641,10 +1742,10 @@ sub main_loop {
[ 'help', \&help_cmd, ],
);
while (1) {
my ($it) = list_and_choose({ PROMPT => 'What now',
my ($it) = list_and_choose({ PROMPT => __('What now'),
SINGLETON => 1,
LIST_FLAT => 4,
HEADER => '*** Commands ***',
HEADER => __('*** Commands ***'),
ON_EOF => \&quit_cmd,
IMMEDIATE => 1 }, @cmd);
if ($it) {
@ -1660,7 +1761,7 @@ sub main_loop {
process_args();
refresh();
if ($patch_mode) {
if ($cmd) {
patch_update_cmd();
}
else {

View file

@ -22,6 +22,7 @@
use File::Temp qw(tempdir);
use Getopt::Long qw(:config pass_through);
use Git;
use Git::I18N;
sub usage
{
@ -122,7 +123,7 @@ sub setup_dir_diff
my $i = 0;
while ($i < $#rawdiff) {
if ($rawdiff[$i] =~ /^::/) {
warn << 'EOF';
warn __ <<'EOF';
Combined diff formats ('-c' and '--cc') are not supported in
directory diff mode ('-d' and '--dir-diff').
EOF
@ -342,7 +343,7 @@ sub main
if (length($opts{difftool_cmd}) > 0) {
$ENV{GIT_DIFF_TOOL} = $opts{difftool_cmd};
} else {
print "No <tool> given for --tool=<tool>\n";
print __("No <tool> given for --tool=<tool>\n");
usage(1);
}
}
@ -350,7 +351,7 @@ sub main
if (length($opts{extcmd}) > 0) {
$ENV{GIT_DIFFTOOL_EXTCMD} = $opts{extcmd};
} else {
print "No <cmd> given for --extcmd=<cmd>\n";
print __("No <cmd> given for --extcmd=<cmd>\n");
usage(1);
}
}
@ -423,11 +424,11 @@ sub dir_diff
}
if (exists $wt_modified{$file} and exists $tmp_modified{$file}) {
my $errmsg = "warning: Both files modified: ";
$errmsg .= "'$workdir/$file' and '$b/$file'.\n";
$errmsg .= "warning: Working tree file has been left.\n";
$errmsg .= "warning:\n";
warn $errmsg;
warn sprintf(__(
"warning: Both files modified:\n" .
"'%s/%s' and '%s/%s'.\n" .
"warning: Working tree file has been left.\n" .
"warning:\n"), $workdir, $file, $b, $file);
$error = 1;
} elsif (exists $tmp_modified{$file}) {
my $mode = stat("$b/$file")->mode;
@ -439,8 +440,9 @@ sub dir_diff
}
}
if ($error) {
warn "warning: Temporary files exist in '$tmpdir'.\n";
warn "warning: You may want to cleanup or recover these.\n";
warn sprintf(__(
"warning: Temporary files exist in '%s'.\n" .
"warning: You may want to cleanup or recover these.\n"), $tmpdir);
exit(1);
} else {
exit_cleanup($tmpdir, $rc);

View file

@ -28,6 +28,7 @@
use File::Spec::Functions qw(catfile);
use Error qw(:try);
use Git;
use Git::I18N;
Getopt::Long::Configure qw/ pass_through /;
@ -117,20 +118,20 @@ sub format_2822_time {
my $localmin = $localtm[1] + $localtm[2] * 60;
my $gmtmin = $gmttm[1] + $gmttm[2] * 60;
if ($localtm[0] != $gmttm[0]) {
die "local zone differs from GMT by a non-minute interval\n";
die __("local zone differs from GMT by a non-minute interval\n");
}
if ((($gmttm[6] + 1) % 7) == $localtm[6]) {
$localmin += 1440;
} elsif ((($gmttm[6] - 1) % 7) == $localtm[6]) {
$localmin -= 1440;
} elsif ($gmttm[6] != $localtm[6]) {
die "local time offset greater than or equal to 24 hours\n";
die __("local time offset greater than or equal to 24 hours\n");
}
my $offset = $localmin - $gmtmin;
my $offhour = $offset / 60;
my $offmin = abs($offset % 60);
if (abs($offhour) >= 24) {
die ("local time offset greater than or equal to 24 hours\n");
die __("local time offset greater than or equal to 24 hours\n");
}
return sprintf("%s, %2d %s %d %02d:%02d:%02d %s%02d%02d",
@ -198,13 +199,13 @@ sub do_edit {
map {
system('sh', '-c', $editor.' "$@"', $editor, $_);
if (($? & 127) || ($? >> 8)) {
die("the editor exited uncleanly, aborting everything");
die(__("the editor exited uncleanly, aborting everything"));
}
} @_;
} else {
system('sh', '-c', $editor.' "$@"', $editor, @_);
if (($? & 127) || ($? >> 8)) {
die("the editor exited uncleanly, aborting everything");
die(__("the editor exited uncleanly, aborting everything"));
}
}
}
@ -278,10 +279,13 @@ sub signal_handler {
# tmp files from --compose
if (defined $compose_filename) {
if (-e $compose_filename) {
print "'$compose_filename' contains an intermediate version of the email you were composing.\n";
printf __("'%s' contains an intermediate version ".
"of the email you were composing.\n"),
$compose_filename;
}
if (-e ($compose_filename . ".final")) {
print "'$compose_filename.final' contains the composed email.\n"
printf __("'%s.final' contains the composed email.\n"),
$compose_filename;
}
}
@ -298,7 +302,7 @@ sub signal_handler {
my $rc = GetOptions("h" => \$help,
"dump-aliases" => \$dump_aliases);
usage() unless $rc;
die "--dump-aliases incompatible with other options\n"
die __("--dump-aliases incompatible with other options\n")
if !$help and $dump_aliases and @ARGV;
$rc = GetOptions(
"sender|from=s" => \$sender,
@ -361,7 +365,7 @@ sub signal_handler {
usage();
}
die "Cannot run git format-patch from outside a repository\n"
die __("Cannot run git format-patch from outside a repository\n")
if $format_patch and not $repo;
# Now, let's fill any that aren't set in with defaults:
@ -430,7 +434,7 @@ sub read_config {
my(%suppress_cc);
if (@suppress_cc) {
foreach my $entry (@suppress_cc) {
die "Unknown --suppress-cc field: '$entry'\n"
die sprintf(__("Unknown --suppress-cc field: '%s'\n"), $entry)
unless $entry =~ /^(?:all|cccmd|cc|author|self|sob|body|bodycc)$/;
$suppress_cc{$entry} = 1;
}
@ -459,7 +463,7 @@ sub read_config {
if ($confirm_unconfigured) {
$confirm = scalar %suppress_cc ? 'compose' : 'auto';
};
die "Unknown --confirm setting: '$confirm'\n"
die sprintf(__("Unknown --confirm setting: '%s'\n"), $confirm)
unless $confirm =~ /^(?:auto|cc|compose|always|never)/;
# Debugging, print out the suppressions.
@ -491,16 +495,16 @@ sub split_addrs {
sub parse_sendmail_alias {
local $_ = shift;
if (/"/) {
print STDERR "warning: sendmail alias with quotes is not supported: $_\n";
printf STDERR __("warning: sendmail alias with quotes is not supported: %s\n"), $_;
} elsif (/:include:/) {
print STDERR "warning: `:include:` not supported: $_\n";
printf STDERR __("warning: `:include:` not supported: %s\n"), $_;
} elsif (/[\/|]/) {
print STDERR "warning: `/file` or `|pipe` redirection not supported: $_\n";
printf STDERR __("warning: `/file` or `|pipe` redirection not supported: %s\n"), $_;
} elsif (/^(\S+?)\s*:\s*(.+)$/) {
my ($alias, $addr) = ($1, $2);
$aliases{$alias} = [ split_addrs($addr) ];
} else {
print STDERR "warning: sendmail line is not recognized: $_\n";
printf STDERR __("warning: sendmail line is not recognized: %s\n"), $_;
}
}
@ -581,11 +585,11 @@ sub is_format_patch_arg {
if (defined($format_patch)) {
return $format_patch;
}
die(<<EOF);
File '$f' exists but it could also be the range of commits
die sprintf(__ <<EOF, $f, $f);
File '%s' exists but it could also be the range of commits
to produce patches for. Please disambiguate by...
* Saying "./$f" if you mean a file; or
* Saying "./%s" if you mean a file; or
* Giving --format-patch option if you mean a range.
EOF
} catch Git::Error::Command with {
@ -603,7 +607,7 @@ sub is_format_patch_arg {
@ARGV = ();
} elsif (-d $f and !is_format_patch_arg($f)) {
opendir my $dh, $f
or die "Failed to opendir $f: $!";
or die sprintf(__("Failed to opendir %s: %s"), $f, $!);
push @files, grep { -f $_ } map { catfile($f, $_) }
sort readdir $dh;
@ -616,7 +620,7 @@ sub is_format_patch_arg {
}
if (@rev_list_opts) {
die "Cannot run git format-patch from outside a repository\n"
die __("Cannot run git format-patch from outside a repository\n")
unless $repo;
push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);
}
@ -627,7 +631,8 @@ sub is_format_patch_arg {
foreach my $f (@files) {
unless (-p $f) {
my $error = validate_patch($f);
$error and die "fatal: $f: $error\nwarning: no patches were sent\n";
$error and die sprintf(__("fatal: %s: %s\nwarning: no patches were sent\n"),
$f, $error);
}
}
}
@ -637,7 +642,7 @@ sub is_format_patch_arg {
print $_,"\n" for (@files);
}
} else {
print STDERR "\nNo patch files specified!\n\n";
print STDERR __("\nNo patch files specified!\n\n");
usage();
}
@ -650,7 +655,7 @@ sub get_patch_subject {
return "GIT: $1\n";
}
close $fh;
die "No subject line in $fn ?";
die sprintf(__("No subject line in %s?"), $fn);
}
if ($compose) {
@ -660,25 +665,27 @@ sub get_patch_subject {
tempfile(".gitsendemail.msg.XXXXXX", DIR => $repo->repo_path()) :
tempfile(".gitsendemail.msg.XXXXXX", DIR => "."))[1];
open my $c, ">", $compose_filename
or die "Failed to open for writing $compose_filename: $!";
or die sprintf(__("Failed to open for writing %s: %s"), $compose_filename, $!);
my $tpl_sender = $sender || $repoauthor || $repocommitter || '';
my $tpl_subject = $initial_subject || '';
my $tpl_reply_to = $initial_reply_to || '';
print $c <<EOT;
print $c <<EOT1, Git::prefix_lines("GIT: ", __ <<EOT2), <<EOT3;
From $tpl_sender # This line is ignored.
GIT: Lines beginning in "GIT:" will be removed.
GIT: Consider including an overall diffstat or table of contents
GIT: for the patch you are writing.
GIT:
GIT: Clear the body content if you don't wish to send a summary.
EOT1
Lines beginning in "GIT:" will be removed.
Consider including an overall diffstat or table of contents
for the patch you are writing.
Clear the body content if you don't wish to send a summary.
EOT2
From: $tpl_sender
Subject: $tpl_subject
In-Reply-To: $tpl_reply_to
EOT
EOT3
for my $f (@files) {
print $c get_patch_subject($f);
}
@ -691,10 +698,10 @@ sub get_patch_subject {
}
open my $c2, ">", $compose_filename . ".final"
or die "Failed to open $compose_filename.final : " . $!;
or die sprintf(__("Failed to open %s.final: %s"), $compose_filename, $!);
open $c, "<", $compose_filename
or die "Failed to open $compose_filename : " . $!;
or die sprintf(__("Failed to open %s: %s"), $compose_filename, $!);
my $need_8bit_cte = file_has_nonascii($compose_filename);
my $in_body = 0;
@ -729,7 +736,7 @@ sub get_patch_subject {
$sender = $1;
next;
} elsif (/^(?:To|Cc|Bcc):/i) {
print "To/Cc/Bcc fields are not interpreted yet, they have been ignored\n";
print __("To/Cc/Bcc fields are not interpreted yet, they have been ignored\n");
next;
}
print $c2 $_;
@ -738,7 +745,7 @@ sub get_patch_subject {
close $c2;
if ($summary_empty) {
print "Summary email is empty, skipping it\n";
print __("Summary email is empty, skipping it\n");
$compose = -1;
}
} elsif ($annotate) {
@ -768,7 +775,9 @@ sub ask {
return $resp;
}
if ($confirm_only) {
my $yesno = $term->readline("Are you sure you want to use <$resp> [y/N]? ");
my $yesno = $term->readline(
# TRANSLATORS: please keep [y/N] as is.
sprintf(__("Are you sure you want to use <%s> [y/N]? "), $resp));
if (defined $yesno && $yesno =~ /y/i) {
return $resp;
}
@ -797,12 +806,12 @@ sub file_declares_8bit_cte {
}
if (!defined $auto_8bit_encoding && scalar %broken_encoding) {
print "The following files are 8bit, but do not declare " .
"a Content-Transfer-Encoding.\n";
print __("The following files are 8bit, but do not declare " .
"a Content-Transfer-Encoding.\n");
foreach my $f (sort keys %broken_encoding) {
print " $f\n";
}
$auto_8bit_encoding = ask("Which 8bit encoding should I declare [UTF-8]? ",
$auto_8bit_encoding = ask(__("Which 8bit encoding should I declare [UTF-8]? "),
valid_re => qr/.{4}/, confirm_only => 1,
default => "UTF-8");
}
@ -810,9 +819,9 @@ sub file_declares_8bit_cte {
if (!$force) {
for my $f (@files) {
if (get_patch_subject($f) =~ /\Q*** SUBJECT HERE ***\E/) {
die "Refusing to send because the patch\n\t$f\n"
die sprintf(__("Refusing to send because the patch\n\t%s\n"
. "has the template subject '*** SUBJECT HERE ***'. "
. "Pass --force if you really want to send.\n";
. "Pass --force if you really want to send.\n"), $f);
}
}
}
@ -829,7 +838,7 @@ sub file_declares_8bit_cte {
# But it's a no-op to run sanitize_address on an already sanitized address.
$sender = sanitize_address($sender);
my $to_whom = "To whom should the emails be sent (if anyone)?";
my $to_whom = __("To whom should the emails be sent (if anyone)?");
my $prompting = 0;
if (!@initial_to && !defined $to_cmd) {
my $to = ask("$to_whom ",
@ -847,7 +856,7 @@ sub expand_aliases {
sub expand_one_alias {
my $alias = shift;
if ($EXPANDED_ALIASES{$alias}) {
die "fatal: alias '$alias' expands to itself\n";
die sprintf(__("fatal: alias '%s' expands to itself\n"), $alias);
}
local $EXPANDED_ALIASES{$alias} = 1;
return $aliases{$alias} ? expand_aliases(@{$aliases{$alias}}) : $alias;
@ -859,7 +868,7 @@ sub expand_one_alias {
if ($thread && !defined $initial_reply_to && $prompting) {
$initial_reply_to = ask(
"Message-ID to be used as In-Reply-To for the first email (if any)? ",
__("Message-ID to be used as In-Reply-To for the first email (if any)? "),
default => "",
valid_re => qr/\@.*\./, confirm_only => 1);
}
@ -909,7 +918,7 @@ sub extract_valid_address {
sub extract_valid_address_or_die {
my $address = shift;
$address = extract_valid_address($address);
die "error: unable to extract a valid address from: $address\n"
die sprintf(__("error: unable to extract a valid address from: %s\n"), $address)
if !$address;
return $address;
}
@ -917,8 +926,11 @@ sub extract_valid_address_or_die {
sub validate_address {
my $address = shift;
while (!extract_valid_address($address)) {
print STDERR "error: unable to extract a valid address from: $address\n";
$_ = ask("What to do with this address? ([q]uit|[d]rop|[e]dit): ",
printf STDERR __("error: unable to extract a valid address from: %s\n"), $address;
# TRANSLATORS: Make sure to include [q] [d] [e] in your
# translation. The program will only accept English input
# at this point.
$_ = ask(__("What to do with this address? ([q]uit|[d]rop|[e]dit): "),
valid_re => qr/^(?:quit|q|drop|d|edit|e)/i,
default => 'q');
if (/^d/i) {
@ -1219,7 +1231,7 @@ sub ssl_verify_params {
return (SSL_verify_mode => SSL_VERIFY_PEER(),
SSL_ca_file => $smtp_ssl_cert_path);
} else {
die "CA path \"$smtp_ssl_cert_path\" does not exist";
die sprintf(__("CA path \"%s\" does not exist"), $smtp_ssl_cert_path);
}
}
@ -1293,20 +1305,26 @@ sub send_message {
if ($needs_confirm eq "inform") {
$confirm_unconfigured = 0; # squelch this message for the rest of this run
$ask_default = "y"; # assume yes on EOF since user hasn't explicitly asked for confirmation
print " The Cc list above has been expanded by additional\n";
print " addresses found in the patch commit message. By default\n";
print " send-email prompts before sending whenever this occurs.\n";
print " This behavior is controlled by the sendemail.confirm\n";
print " configuration setting.\n";
print "\n";
print " For additional information, run 'git send-email --help'.\n";
print " To retain the current behavior, but squelch this message,\n";
print " run 'git config --global sendemail.confirm auto'.\n\n";
print __ <<EOF ;
The Cc list above has been expanded by additional
addresses found in the patch commit message. By default
send-email prompts before sending whenever this occurs.
This behavior is controlled by the sendemail.confirm
configuration setting.
For additional information, run 'git send-email --help'.
To retain the current behavior, but squelch this message,
run 'git config --global sendemail.confirm auto'.
EOF
}
$_ = ask("Send this email? ([y]es|[n]o|[q]uit|[a]ll): ",
# TRANSLATORS: Make sure to include [y] [n] [q] [a] in your
# translation. The program will only accept English input
# at this point.
$_ = ask(__("Send this email? ([y]es|[n]o|[q]uit|[a]ll): "),
valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
default => $ask_default);
die "Send this email reply required" unless defined $_;
die __("Send this email reply required") unless defined $_;
if (/^n/i) {
return 0;
} elsif (/^q/i) {
@ -1332,7 +1350,7 @@ sub send_message {
} else {
if (!defined $smtp_server) {
die "The required SMTP server is not properly defined."
die __("The required SMTP server is not properly defined.")
}
if ($smtp_encryption eq 'ssl') {
@ -1376,14 +1394,14 @@ sub send_message {
# supported commands
$smtp->hello($smtp_domain);
} else {
die "Server does not support STARTTLS! ".$smtp->message;
die sprintf(__("Server does not support STARTTLS! %s"), $smtp->message);
}
}
}
if (!$smtp) {
die "Unable to initialize SMTP properly. Check config and use --smtp-debug. ",
"VALUES: server=$smtp_server ",
die __("Unable to initialize SMTP properly. Check config and use --smtp-debug."),
" VALUES: server=$smtp_server ",
"encryption=$smtp_encryption ",
"hello=$smtp_domain",
defined $smtp_server_port ? " port=$smtp_server_port" : "";
@ -1400,12 +1418,12 @@ sub send_message {
$smtp->datasend("$line") or die $smtp->message;
}
$smtp->dataend() or die $smtp->message;
$smtp->code =~ /250|200/ or die "Failed to send $subject\n".$smtp->message;
$smtp->code =~ /250|200/ or die sprintf(__("Failed to send %s\n"), $subject).$smtp->message;
}
if ($quiet) {
printf (($dry_run ? "Dry-" : "")."Sent %s\n", $subject);
printf($dry_run ? __("Dry-Sent %s\n") : __("Sent %s\n"), $subject);
} else {
print (($dry_run ? "Dry-" : "")."OK. Log says:\n");
print($dry_run ? __("Dry-OK. Log says:\n") : __("OK. Log says:\n"));
if (!file_name_is_absolute($smtp_server)) {
print "Server: $smtp_server\n";
print "MAIL FROM:<$raw_from>\n";
@ -1417,10 +1435,10 @@ sub send_message {
}
print $header, "\n";
if ($smtp) {
print "Result: ", $smtp->code, ' ',
print __("Result: "), $smtp->code, ' ',
($smtp->message =~ /\n([^\n]+\n)$/s), "\n";
} else {
print "Result: OK\n";
print __("Result: OK\n");
}
}
@ -1433,7 +1451,7 @@ sub send_message {
$message_num = 0;
foreach my $t (@files) {
open my $fh, "<", $t or die "can't open file $t";
open my $fh, "<", $t or die sprintf(__("can't open file %s"), $t);
my $author = undef;
my $sauthor = undef;
@ -1480,13 +1498,13 @@ sub send_message {
$sauthor = sanitize_address($author);
next if $suppress_cc{'author'};
next if $suppress_cc{'self'} and $sauthor eq $sender;
printf("(mbox) Adding cc: %s from line '%s'\n",
printf(__("(mbox) Adding cc: %s from line '%s'\n"),
$1, $_) unless $quiet;
push @cc, $1;
}
elsif (/^To:\s+(.*)$/i) {
foreach my $addr (parse_address_line($1)) {
printf("(mbox) Adding to: %s from line '%s'\n",
printf(__("(mbox) Adding to: %s from line '%s'\n"),
$addr, $_) unless $quiet;
push @to, $addr;
}
@ -1500,7 +1518,7 @@ sub send_message {
} else {
next if ($suppress_cc{'cc'});
}
printf("(mbox) Adding cc: %s from line '%s'\n",
printf(__("(mbox) Adding cc: %s from line '%s'\n"),
$addr, $_) unless $quiet;
push @cc, $addr;
}
@ -1534,7 +1552,7 @@ sub send_message {
# So let's support that, too.
$input_format = 'lots';
if (@cc == 0 && !$suppress_cc{'cc'}) {
printf("(non-mbox) Adding cc: %s from line '%s'\n",
printf(__("(non-mbox) Adding cc: %s from line '%s'\n"),
$_, $_) unless $quiet;
push @cc, $_;
} elsif (!defined $subject) {
@ -1557,7 +1575,7 @@ sub send_message {
next if $suppress_cc{'bodycc'} and $what =~ /Cc/i;
}
push @cc, $c;
printf("(body) Adding cc: %s from line '%s'\n",
printf(__("(body) Adding cc: %s from line '%s'\n"),
$c, $_) unless $quiet;
}
}
@ -1655,18 +1673,18 @@ sub recipients_cmd {
my @addresses = ();
open my $fh, "-|", "$cmd \Q$file\E"
or die "($prefix) Could not execute '$cmd'";
or die sprintf(__("(%s) Could not execute '%s'"), $prefix, $cmd);
while (my $address = <$fh>) {
$address =~ s/^\s*//g;
$address =~ s/\s*$//g;
$address = sanitize_address($address);
next if ($address eq $sender and $suppress_cc{'self'});
push @addresses, $address;
printf("($prefix) Adding %s: %s from: '%s'\n",
$what, $address, $cmd) unless $quiet;
printf(__("(%s) Adding %s: %s from: '%s'\n"),
$prefix, $what, $address, $cmd) unless $quiet;
}
close $fh
or die "($prefix) failed to close pipe to '$cmd'";
or die sprintf(__("(%s) failed to close pipe to '%s'"), $prefix, $cmd);
return @addresses;
}
@ -1693,7 +1711,7 @@ sub apply_transfer_encoding {
$message = MIME::Base64::decode($message)
if ($from eq 'base64');
die "cannot send message as 7bit"
die __("cannot send message as 7bit")
if ($to eq '7bit' and $message =~ /[^[:ascii:]]/);
return $message
if ($to eq '7bit' or $to eq '8bit');
@ -1701,7 +1719,7 @@ sub apply_transfer_encoding {
if ($to eq 'quoted-printable');
return MIME::Base64::encode($message, "\n")
if ($to eq 'base64');
die "invalid transfer encoding";
die __("invalid transfer encoding");
}
sub unique_email_list {
@ -1720,10 +1738,10 @@ sub unique_email_list {
sub validate_patch {
my $fn = shift;
open(my $fh, '<', $fn)
or die "unable to open $fn: $!\n";
or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
while (my $line = <$fh>) {
if (length($line) > 998) {
return "$.: patch contains a line longer than 998 characters";
return sprintf(__("%s: patch contains a line longer than 998 characters"), $.);
}
}
return;
@ -1739,10 +1757,11 @@ sub handle_backup {
(substr($file, 0, $lastlen) eq $last) &&
($suffix = substr($file, $lastlen)) !~ /^[a-z0-9]/i) {
if (defined $known_suffix && $suffix eq $known_suffix) {
print "Skipping $file with backup suffix '$known_suffix'.\n";
printf(__("Skipping %s with backup suffix '%s'.\n"), $file, $known_suffix);
$skip = 1;
} else {
my $answer = ask("Do you really want to send $file? (y|N): ",
# TRANSLATORS: please keep "[y|N]" as is.
my $answer = ask(sprintf(__("Do you really want to send %s? [y|N]: "), $file),
valid_re => qr/^(?:y|n)/i,
default => 'n');
$skip = ($answer ne 'y');
@ -1770,7 +1789,7 @@ sub handle_backup_files {
sub file_has_nonascii {
my $fn = shift;
open(my $fh, '<', $fn)
or die "unable to open $fn: $!\n";
or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
while (my $line = <$fh>) {
return 1 if $line =~ /[^[:ascii:]]/;
}
@ -1780,7 +1799,7 @@ sub file_has_nonascii {
sub body_or_subject_has_nonascii {
my $fn = shift;
open(my $fh, '<', $fn)
or die "unable to open $fn: $!\n";
or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
while (my $line = <$fh>) {
last if $line =~ /^$/;
return 1 if $line =~ /^Subject.*[^[:ascii:]]/;

View file

@ -1438,6 +1438,44 @@ sub END {
} # %TEMP_* Lexical Context
=item prefix_lines ( PREFIX, STRING [, STRING... ])
Prefixes lines in C<STRING> with C<PREFIX>.
=cut
sub prefix_lines {
my $prefix = shift;
my $string = join("\n", @_);
$string =~ s/^/$prefix/mg;
return $string;
}
=item get_comment_line_char ( )
Gets the core.commentchar configuration value.
The value falls-back to '#' if core.commentchar is set to 'auto'.
=cut
sub get_comment_line_char {
my $comment_line_char = config("core.commentchar") || '#';
$comment_line_char = '#' if ($comment_line_char eq 'auto');
$comment_line_char = '#' if (length($comment_line_char) != 1);
return $comment_line_char;
}
=item comment_lines ( STRING [, STRING... ])
Comments lines following core.commentchar configuration.
=cut
sub comment_lines {
my $comment_line_char = get_comment_line_char;
return prefix_lines("$comment_line_char ", @_);
}
=back
=head1 ERROR HANDLING

View file

@ -13,7 +13,7 @@ BEGIN
}
}
our @EXPORT = qw(__);
our @EXPORT = qw(__ __n N__);
our @EXPORT_OK = @EXPORT;
sub __bootstrap_locale_messages {
@ -44,6 +44,7 @@ BEGIN
eval {
__bootstrap_locale_messages();
*__ = \&Locale::Messages::gettext;
*__n = \&Locale::Messages::ngettext;
1;
} or do {
# Tell test.pl that we couldn't load the gettext library.
@ -51,7 +52,10 @@ BEGIN
# Just a fall-through no-op
*__ = sub ($) { $_[0] };
*__n = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };
};
sub N__($) { return shift; }
}
1;
@ -70,6 +74,9 @@ =head1 SYNOPSIS
printf __("The following error occurred: %s\n"), $error;
printf __n("commited %d file\n", "commited %d files\n", $files), $files;
=head1 DESCRIPTION
Git's internal Perl interface to gettext via L<Locale::Messages>. If
@ -87,6 +94,16 @@ =head2 __($)
L<Locale::Messages>'s gettext function if all goes well, otherwise our
passthrough fallback function.
=head2 __n($$$)
L<Locale::Messages>'s ngettext function or passthrough fallback function.
=head2 N__($)
No-operation that only returns its argument. Use this if you want xgettext to
extract the text to the pot template but do not want to trigger retrival of the
translation at run time.
=head1 AUTHOR
E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>

View file

@ -4,7 +4,7 @@
use strict;
use warnings;
use POSIX qw(:locale_h);
use Test::More tests => 8;
use Test::More tests => 13;
use Git::I18N;
my $has_gettext_library = $Git::I18N::__HAS_LIBRARY;
@ -31,6 +31,8 @@
# more gettext wrapper functions.
my %prototypes = (qw(
__ $
__n $$$
N__ $
));
while (my ($sub, $proto) = each %prototypes) {
is(prototype(\&{"Git::I18N::$sub"}), $proto, "sanity: $sub has a $proto prototype");
@ -46,6 +48,16 @@
my ($got, $expect) = (('TEST: A Perl test string') x 2);
is(__($got), $expect, "Passing a string through __() in the C locale works");
my ($got_singular, $got_plural, $expect_singular, $expect_plural) =
(('TEST: 1 file', 'TEST: n files') x 2);
is(__n($got_singular, $got_plural, 1), $expect_singular,
"Get singular string through __n() in C locale");
is(__n($got_singular, $got_plural, 2), $expect_plural,
"Get plural string through __n() in C locale");
is(N__($got), $expect, "Passing a string through N__() in the C locale works");
}
# Test a basic message on different locales