{"thread":{"id":"44227","subject":"[PATCH v3 00/14] Mark strings in Perl scripts for translation","startedAt":"2016-10-05T17:21:44Z","lastAt":"2016-11-09T23:16:55Z","messageCount":63,"participants":["Vasco Almeida","Jakub Narębski","Junio C Hamano"],"isPatch":true,"patchVersion":3,"patchTotal":14},"messages":[{"id":"303395","messageId":"20161005172110.30801-1-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":null,"subject":"[PATCH v3 00/14] Mark strings in Perl scripts for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:20:56Z","receivedAt":"2016-10-05T17:21:44Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark messages in some perl scripts for translation.\n\nThanks for the reviews of Junio Hamano and Jakub Narębski.  Although I think\nJakub Narębski's suggestions are overall good, I am not willing to go that path\nbecause I cannot see huge benefits from them given what we already have and\nalso I lack Perl skills.\n\nInterdiff bellow.\n\nVasco Almeida (14):\n  i18n: add--interactive: mark strings for translation\n  i18n: add--interactive: mark simple here-documents for translation\n  i18n: add--interactive: mark strings with interpolation for\n    translation\n  i18n: clean.c: match string with git-add--interactive.perl\n  i18n: add--interactive: mark plural strings\n  i18n: add--interactive: mark patch prompt for translation\n  i18n: add--interactive: i18n of help_patch_cmd\n  i18n: add--interactive: mark edit_hunk_manually message for\n    translation\n  i18n: add--interactive: remove %patch_modes entries\n  i18n: add--interactive: mark status words for translation\n  i18n: send-email: mark strings for translation\n  i18n: send-email: mark warnings and errors for translation\n  i18n: send-email: mark string with interpolation for translation\n  i18n: difftool: mark warnings for translation\n\n Makefile                  |   3 +-\n builtin/clean.c           |  10 +-\n git-add--interactive.perl | 318 ++++++++++++++++++++++++++++++----------------\n git-difftool.perl         |  22 ++--\n git-send-email.perl       | 176 +++++++++++++------------\n perl/Git/I18N.pm          |   9 +-\n t/t0202/test.pl           |  11 +-\n 7 files changed, 340 insertions(+), 209 deletions(-)\n\n\ndiff --git a/Makefile b/Makefile\nindex fc29d85..4ef0344 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -2112,7 +2112,7 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \\\n XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \\\n \t--keyword=gettextln --keyword=eval_gettextln\n XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \\\n-\t--keyword=__ --keyword=\"Q__:1,2\"\n+\t--keyword=__ --keyword=\"__n:1,2\"\n LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)\n LOCALIZED_SH = $(SCRIPT_SH)\n LOCALIZED_SH += git-parse-remote.sh\ndiff --git a/builtin/clean.c b/builtin/clean.c\nindex 0371010..d6bc3aa 100644\n--- a/builtin/clean.c\n+++ b/builtin/clean.c\n@@ -287,11 +287,11 @@ static void pretty_print_menus(struct string_list *menu_list)\n static void prompt_help_cmd(int singleton)\n {\n \tclean_print_color(CLEAN_COLOR_HELP);\n-\tprintf_ln(singleton ?\n+\tprintf(singleton ?\n \t\t  _(\"Prompt help:\\n\"\n \t\t    \"1          - select a numbered item\\n\"\n \t\t    \"foo        - select item based on unique prefix\\n\"\n-\t\t    \"           - (empty) select nothing\") :\n+\t\t    \"           - (empty) select nothing\\n\") :\n \t\t  _(\"Prompt help:\\n\"\n \t\t    \"1          - select a single item\\n\"\n \t\t    \"3-5        - select a range of items\\n\"\n@@ -299,7 +299,7 @@ static void prompt_help_cmd(int singleton)\n \t\t    \"foo        - select item based on unique prefix\\n\"\n \t\t    \"-...       - unselect specified items\\n\"\n \t\t    \"*          - choose all items\\n\"\n-\t\t    \"           - (empty) finish selecting\"));\n+\t\t    \"           - (empty) finish selecting\\n\"));\n \tclean_print_color(CLEAN_COLOR_RESET);\n }\n \n@@ -508,7 +508,7 @@ static int parse_choice(struct menu_stuff *menu_stuff,\n \t\tif (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||\n \t\t    (is_single && bottom != top)) {\n \t\t\tclean_print_color(CLEAN_COLOR_ERROR);\n-\t\t\tprintf_ln(_(\"Huh (%s)?\"), (*ptr)->buf);\n+\t\t\tprintf(_(\"Huh (%s)?\\n\"), (*ptr)->buf);\n \t\t\tclean_print_color(CLEAN_COLOR_RESET);\n \t\t\tcontinue;\n \t\t}\n@@ -774,7 +774,7 @@ static int ask_each_cmd(void)\n static int quit_cmd(void)\n {\n \tstring_list_clear(&del_list, 0);\n-\tprintf_ln(_(\"Bye.\"));\n+\tprintf(_(\"Bye.\\n\"));\n \treturn MENU_RETURN_NO_LOOP;\n }\n \ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex b72cc97..0b4a27c 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -106,9 +106,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-files -p',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Stage',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'staging',\n \t\tFILTER => 'file-only',\n \t\tIS_REVERSE => 0,\n \t},\n@@ -116,9 +113,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p HEAD',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Stash',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'stashing',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 0,\n \t},\n@@ -126,9 +120,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p --cached',\n \t\tAPPLY => sub { apply_patch 'apply -R --cached', @_; },\n \t\tAPPLY_CHECK => 'apply -R --cached',\n-\t\tVERB => 'Unstage',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'unstaging',\n \t\tFILTER => 'index-only',\n \t\tIS_REVERSE => 1,\n \t},\n@@ -136,9 +127,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -R -p --cached',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Apply',\n-\t\tTARGET => ' to index',\n-\t\tPARTICIPLE => 'applying',\n \t\tFILTER => 'index-only',\n \t\tIS_REVERSE => 0,\n \t},\n@@ -146,9 +134,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-files -p',\n \t\tAPPLY => sub { apply_patch 'apply -R', @_; },\n \t\tAPPLY_CHECK => 'apply -R',\n-\t\tVERB => 'Discard',\n-\t\tTARGET => ' from worktree',\n-\t\tPARTICIPLE => 'discarding',\n \t\tFILTER => 'file-only',\n \t\tIS_REVERSE => 1,\n \t},\n@@ -156,9 +141,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p',\n \t\tAPPLY => sub { apply_patch_for_checkout_commit '-R', @_ },\n \t\tAPPLY_CHECK => 'apply -R',\n-\t\tVERB => 'Discard',\n-\t\tTARGET => ' from index and worktree',\n-\t\tPARTICIPLE => 'discarding',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 1,\n \t},\n@@ -166,9 +148,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -R -p',\n \t\tAPPLY => sub { apply_patch_for_checkout_commit '', @_ },\n \t\tAPPLY_CHECK => 'apply',\n-\t\tVERB => 'Apply',\n-\t\tTARGET => ' to index and worktree',\n-\t\tPARTICIPLE => 'applying',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 0,\n \t},\n@@ -256,7 +235,8 @@ sub list_untracked {\n \trun_cmd_pipe(qw(git ls-files --others --exclude-standard --), @ARGV);\n }\n \n-my $status_fmt = '%12s %12s %s';\n+# TRANSLATORS: you can adjust this to align \"git add -i\" status menu\n+my $status_fmt = __('%12s %12s %s');\n my $status_head = sprintf($status_fmt, __('staged'), __('unstaged'), __('path'));\n \n {\n@@ -315,7 +295,7 @@ sub list_modified {\n \t\t\tmy ($change, $bin);\n \t\t\t$file = unquote_path($file);\n \t\t\tif ($add eq '-' && $del eq '-') {\n-\t\t\t\t$change = 'binary';\n+\t\t\t\t$change = __('binary');\n \t\t\t\t$bin = 1;\n \t\t\t}\n \t\t\telse {\n@@ -324,7 +304,7 @@ sub list_modified {\n \t\t\t$data{$file} = {\n \t\t\t\tINDEX => $change,\n \t\t\t\tBINARY => $bin,\n-\t\t\t\tFILE => 'nothing',\n+\t\t\t\tFILE => __('nothing'),\n \t\t\t}\n \t\t}\n \t\telsif (($adddel, $file) =\n@@ -340,7 +320,7 @@ sub list_modified {\n \t\t\t$file = unquote_path($file);\n \t\t\tmy ($change, $bin);\n \t\t\tif ($add eq '-' && $del eq '-') {\n-\t\t\t\t$change = 'binary';\n+\t\t\t\t$change = __('binary');\n \t\t\t\t$bin = 1;\n \t\t\t}\n \t\t\telse {\n@@ -360,7 +340,7 @@ sub list_modified {\n \t\t\t$file = unquote_path($2);\n \t\t\tif (!exists $data{$file}) {\n \t\t\t\t$data{$file} = +{\n-\t\t\t\t\tINDEX => 'unchanged',\n+\t\t\t\t\tINDEX => __('unchanged'),\n \t\t\t\t\tBINARY => 0,\n \t\t\t\t};\n \t\t\t}\n@@ -375,10 +355,10 @@ sub list_modified {\n \n \t\tif ($only) {\n \t\t\tif ($only eq 'index-only') {\n-\t\t\t\tnext if ($it->{INDEX} eq 'unchanged');\n+\t\t\t\tnext if ($it->{INDEX} eq __('unchanged'));\n \t\t\t}\n \t\t\tif ($only eq 'file-only') {\n-\t\t\t\tnext if ($it->{FILE} eq 'nothing');\n+\t\t\t\tnext if ($it->{FILE} eq __('nothing'));\n \t\t\t}\n \t\t}\n \t\tpush @return, +{\n@@ -621,7 +601,7 @@ sub list_and_choose {\n \t\t\t\t}\n \t\t\t}\n \t\t\tif ($opts->{SINGLETON} && $bottom != $top) {\n-\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\\n\"), $choice);\n+\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\"), $choice);\n \t\t\t\tnext TOPLOOP;\n \t\t\t}\n \t\t\tfor ($i = $bottom-1; $i <= $top-1; $i++) {\n@@ -640,25 +620,25 @@ sub list_and_choose {\n }\n \n sub singleton_prompt_help_cmd {\n-\tprint colored $help_color, __(\n-\"Prompt help:\n+\tprint colored $help_color, __ <<'EOF' ;\n+Prompt help:\n 1          - select a numbered item\n foo        - select item based on unique prefix\n-           - (empty) select nothing\"),\n-\"\\n\";\n+           - (empty) select nothing\n+EOF\n }\n \n sub prompt_help_cmd {\n-\tprint colored $help_color, __(\n-\"Prompt help:\n+\tprint colored $help_color, __ <<'EOF' ;\n+Prompt help:\n 1          - select a single item\n 3-5        - select a range of items\n 2-3,6-9    - select multiple ranges\n foo        - select item based on unique prefix\n -...       - unselect specified items\n *          - choose all items\n-           - (empty) finish selecting\"),\n-\"\\n\";\n+           - (empty) finish selecting\n+EOF\n }\n \n sub status_cmd {\n@@ -671,16 +651,16 @@ sub say_n_paths {\n \tmy $did = shift @_;\n \tmy $cnt = scalar @_;\n \tif ($did eq 'added') {\n-\t\tprintf(Q__(\"added one path\\n\", \"added %d paths\\n\",\n+\t\tprintf(__n(\"added %d path\\n\", \"added %d paths\\n\",\n \t\t\t   $cnt), $cnt);\n \t} elsif ($did eq 'updated') {\n-\t\tprintf(Q__(\"updated one path\\n\", \"updated %d paths\\n\",\n+\t\tprintf(__n(\"updated %d path\\n\", \"updated %d paths\\n\",\n \t\t\t   $cnt), $cnt);\n-\t} elsif ($did eq 'reversed') {\n-\t\tprintf(Q__(\"reversed one path\\n\", \"reversed %d paths\\n\",\n+\t} elsif ($did eq 'reverted') {\n+\t\tprintf(__n(\"reverted %d path\\n\", \"reverted %d paths\\n\",\n \t\t\t   $cnt), $cnt);\n \t} else {\n-\t\tprintf(Q__(\"touched one path\\n\", \"touched %d paths\\n\",\n+\t\tprintf(__n(\"touched %d path\\n\", \"touched %d paths\\n\",\n \t\t\t   $cnt), $cnt);\n \t}\n }\n@@ -1057,6 +1037,30 @@ sub color_diff {\n \t} @_;\n }\n \n+my %edit_hunk_manually_modes = (\n+\tstage => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for staging.\"),\n+\tstash => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for stashing.\"),\n+\treset_head => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for unstaging.\"),\n+\treset_nothead => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for applying.\"),\n+\tcheckout_index => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for discarding\"),\n+\tcheckout_head => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for discarding.\"),\n+\tcheckout_nothead => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for applying.\"),\n+);\n+\n sub edit_hunk_manually {\n \tmy ($oldtext) = @_;\n \n@@ -1073,51 +1077,12 @@ sub edit_hunk_manually {\n # To remove '%s' lines, make them ' ' lines (context).\n # To remove '%s' lines, delete them.\n # Lines starting with # will be removed.\n-#\"), $remove_minus, $remove_plus),\n-\"\\n\";\n-\tif ($patch_mode eq 'stage') {\n-\t\tprint $fh __(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for staging. If it does not apply cleanly, you will be given\n-# an opportunity to edit again. If all lines of the hunk are removed,\n-# then the edit is aborted and the hunk is left unchanged.\");\n-\t} elsif ($patch_mode eq 'stash') {\n-\t\tprint $fh __(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for stashing. If it does not apply cleanly, you will be given\n-# an opportunity to edit again. If all lines of the hunk are removed,\n-# then the edit is aborted and the hunk is left unchanged.\");\n-\t} elsif ($patch_mode eq 'reset_head') {\n-\t\tprint $fh __(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for unstaging. If it does not apply cleanly, you will be given\n+#\\n\"), $remove_minus, $remove_plus),\n+$edit_hunk_manually_modes{$patch_mode}, __(\n+# TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.\n+\" If it does not apply cleanly, you will be given\n # an opportunity to edit again. If all lines of the hunk are removed,\n-# then the edit is aborted and the hunk is left unchanged.\");\n-\t} elsif ($patch_mode eq 'reset_nothead') {\n-\t\tprint $fh __(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for applying. If it does not apply cleanly, you will be given\n-# an opportunity to edit again. If all lines of the hunk are removed,\n-# then the edit is aborted and the hunk is left unchanged.\");\n-\t} elsif ($patch_mode eq 'checkout_index') {\n-\t\tprint $fh __(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for discarding. If it does not apply cleanly, you will be given\n-# an opportunity to edit again. If all lines of the hunk are removed,\n-# then the edit is aborted and the hunk is left unchanged.\");\n-\t} elsif ($patch_mode eq 'checkout_head') {\n-\t\tprint $fh __(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for discarding. If it does not apply cleanly, you will be given\n-# an opportunity to edit again. If all lines of the hunk are removed,\n-# then the edit is aborted and the hunk is left unchanged.\");\n-\t} elsif ($patch_mode eq 'checkout_nothead') {\n-\t\tprint $fh __(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for applying. If it does not apply cleanly, you will be given\n-# an opportunity to edit again. If all lines of the hunk are removed,\n-# then the edit is aborted and the hunk is left unchanged.\");\n-\t}\n+# then the edit is aborted and the hunk is left unchanged.\\n\");\n \tclose $fh;\n \n \tchomp(my $editor = run_cmd_pipe(qw(git var GIT_EDITOR)));\n@@ -1216,6 +1181,9 @@ sub edit_hunk_loop {\n \t\t\t\t# TRANSLATORS: do not translate [y/n]\n \t\t\t\t# The program will only accept that input\n \t\t\t\t# at this point.\n+\t\t\t\t# Consider translating (saying \"no\" discards!) as\n+\t\t\t\t# (saying \"n\" for \"no\" discards!) if the translation\n+\t\t\t\t# of the word \"no\" does not start with n.\n \t\t\t\t__('Your edited hunk does not apply. Edit again '\n \t\t\t\t   . '(saying \"no\" discards!) [y/n]? ')\n \t\t\t\t) or return undef;\n@@ -1223,59 +1191,54 @@ sub edit_hunk_loop {\n \t}\n }\n \n-sub help_patch_cmd {\n-\tif ($patch_mode eq 'stage') {\n-\t\tprint colored $help_color, __(\n+my %help_patch_modes = (\n+\tstage => __(\n \"y - stage this hunk\n n - do not stage this hunk\n q - quit; do not stage this hunk or any of the remaining ones\n a - stage this hunk and all later hunks in the file\n-d - do not stage this hunk or any of the later hunks in the file\");\n-\t} elsif ($patch_mode eq 'stash') {\n-\t\tprint colored $help_color, __(\n+d - do not stage this hunk or any of the later hunks in the file\"),\n+\tstash => __(\n \"y - stash this hunk\n n - do not stash this hunk\n q - quit; do not stash this hunk or any of the remaining ones\n a - stash this hunk and all later hunks in the file\n-d - do not stash this hunk or any of the later hunks in the file\");\n-\t} elsif ($patch_mode eq 'reset_head') {\n-\t\tprint colored $help_color, __(\n+d - do not stash this hunk or any of the later hunks in the file\"),\n+\treset_head => __(\n \"y - unstage this hunk\n n - do not unstage this hunk\n q - quit; do not unstage this hunk or any of the remaining ones\n a - unstage this hunk and all later hunks in the file\n-d - do not unstage this hunk or any of the later hunks in the file\");\n-\t} elsif ($patch_mode eq 'reset_nothead') {\n-\t\tprint colored $help_color, __(\n+d - do not unstage this hunk or any of the later hunks in the file\"),\n+\treset_nothead => __(\n \"y - apply this hunk to index\n n - do not apply this hunk to index\n q - quit; do not apply this hunk or any of the remaining ones\n a - apply this hunk and all later hunks in the file\n-d - do not apply this hunk or any of the later hunks in the file\");\n-\t} elsif ($patch_mode eq 'checkout_index') {\n-\t\tprint colored $help_color, __(\n+d - do not apply this hunk or any of the later hunks in the file\"),\n+\tcheckout_index => __(\n \"y - discard this hunk from worktree\n n - do not discard this hunk from worktree\n q - quit; do not discard this hunk or any of the remaining ones\n a - discard this hunk and all later hunks in the file\n-d - do not discard this hunk or any of the later hunks in the file\");\n-\t} elsif ($patch_mode eq 'checkout_head') {\n-\t\tprint colored $help_color, __(\n+d - do not discard this hunk or any of the later hunks in the file\"),\n+\tcheckout_head => __(\n \"y - discard this hunk from index and worktree\n n - do not discard this hunk from index and worktree\n q - quit; do not discard this hunk or any of the remaining ones\n a - discard this hunk and all later hunks in the file\n-d - do not discard this hunk or any of the later hunks in the file\");\n-\t} elsif ($patch_mode eq 'checkout_nothead') {\n-\t\tprint colored $help_color, __(\n+d - do not discard this hunk or any of the later hunks in the file\"),\n+\tcheckout_nothead => __(\n \"y - apply this hunk to index and worktree\n n - do not apply this hunk to index and worktree\n q - quit; do not apply this hunk or any of the remaining ones\n a - apply this hunk and all later hunks in the file\n-d - do not apply this hunk or any of the later hunks in the file\");\n-\t}\n-\tprint colored $help_color, \"\\n\", __(\n-\"g - select a hunk to go to\n+d - do not apply this hunk or any of the later hunks in the file\"),\n+);\n+\n+sub help_patch_cmd {\n+\tprint colored $help_color, $help_patch_modes{$patch_mode}, \"\\n\", __ <<EOF ;\n+g - select a hunk to go to\n / - search for a hunk matching the given regex\n j - leave this hunk undecided, see next undecided hunk\n J - leave this hunk undecided, see next hunk\n@@ -1283,8 +1246,8 @@ k - leave this hunk undecided, see previous undecided hunk\n K - leave this hunk undecided, see previous hunk\n s - split the current hunk into smaller hunks\n e - manually edit the current hunk\n-? - print help\"),\n-\"\\n\";\n+? - print help\n+EOF\n }\n \n sub apply_patch {\n@@ -1390,6 +1353,44 @@ sub display_hunks {\n \treturn $i;\n }\n \n+my %patch_update_prompt_modes = (\n+\tstage => {\n+\t\tmode => __(\"Stage mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Stage deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Stage this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tstash => {\n+\t\tmode => __(\"Stash mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Stash deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Stash this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\treset_head => {\n+\t\tmode => __(\"Unstage mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Unstage deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Unstage this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\treset_nothead => {\n+\t\tmode => __(\"Apply mode change to index [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Apply deletion to index [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Apply this hunk to index [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_index => {\n+\t\tmode => __(\"Discard mode change from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Discard deletion from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Discard this hunk from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_head => {\n+\t\tmode => __(\"Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_nothead => {\n+\t\tmode => __(\"Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+);\n+\n sub patch_update_file {\n \tmy $quit = 0;\n \tmy ($ix, $num);\n@@ -1462,84 +1463,9 @@ sub patch_update_file {\n \t\tfor (@{$hunk[$ix]{DISPLAY}}) {\n \t\t\tprint;\n \t\t}\n-\t\tif ($patch_mode eq 'stage') {\n-\t\t\tif ($hunk[$ix]{TYPE} eq 'mode') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Stage mode change [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} elsif ($hunk[$ix]{TYPE} eq 'deletion') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Stage deletion [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} else {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Stage this hunk [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t}\n-\t\t} elsif ($patch_mode eq 'stash') {\n-\t\t\tif ($hunk[$ix]{TYPE} eq 'mode') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Stash mode change [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} elsif ($hunk[$ix]{TYPE} eq 'deletion') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Stash deletion [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} else {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Stash this hunk [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t}\n-\t\t} elsif ($patch_mode eq 'reset_head') {\n-\t\t\tif ($hunk[$ix]{TYPE} eq 'mode') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Unstage mode change [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} elsif ($hunk[$ix]{TYPE} eq 'deletion') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Unstage deletion [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} else {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Unstage this hunk [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t}\n-\t\t} elsif ($patch_mode eq 'reset_nothead') {\n-\t\t\tif ($hunk[$ix]{TYPE} eq 'mode') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Apply mode change to index [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} elsif ($hunk[$ix]{TYPE} eq 'deletion') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Apply deletion to index [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} else {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Apply this hunk to index [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t}\n-\t\t} elsif ($patch_mode eq 'checkout_index') {\n-\t\t\tif ($hunk[$ix]{TYPE} eq 'mode') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Discard mode change from worktree [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} elsif ($hunk[$ix]{TYPE} eq 'deletion') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Discard deletion from worktree [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} else {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Discard this hunk from worktree [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t}\n-\t\t} elsif ($patch_mode eq 'checkout_head') {\n-\t\t\tif ($hunk[$ix]{TYPE} eq 'mode') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} elsif ($hunk[$ix]{TYPE} eq 'deletion') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} else {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t}\n-\t\t} elsif ($patch_mode eq 'checkout_nothead') {\n-\t\t\tif ($hunk[$ix]{TYPE} eq 'mode') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} elsif ($hunk[$ix]{TYPE} eq 'deletion') {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t} else {\n-\t\t\t  print colored $prompt_color,\n-\t\t\t    sprintf(__(\"Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? \"), $other);\n-\t\t\t}\n-\t\t}\n+\t\tprint colored $prompt_color,\n+\t\t\tsprintf($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}, $other);\n+\n \t\tmy $line = prompt_single_character;\n \t\tlast unless defined $line;\n \t\tif ($line) {\n@@ -1580,8 +1506,8 @@ sub patch_update_file {\n \t\t\t\t} elsif (0 < $response && $response <= $num) {\n \t\t\t\t\t$ix = $response - 1;\n \t\t\t\t} else {\n-\t\t\t\t\terror_msg sprintf(__(\"Sorry, only %s hunks available.\\n\"),\n-\t\t\t\t\t\t\t     $num);\n+\t\t\t\t\terror_msg sprintf(__n(\"Sorry, only %d hunk available.\\n\",\n+\t\t\t\t\t\t\t      \"Sorry, only %d hunks available.\\n\", $num), $num);\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n@@ -1677,7 +1603,7 @@ sub patch_update_file {\n \t\t\t\tmy @split = split_hunk($hunk[$ix]{TEXT}, $hunk[$ix]{DISPLAY});\n \t\t\t\tif (1 < @split) {\n \t\t\t\t\tprint colored $header_color, sprintf(\n-\t\t\t\t\t\tQ__(\"Split into %d hunk.\\n\",\n+\t\t\t\t\t\t__n(\"Split into %d hunk.\\n\",\n \t\t\t\t\t\t    \"Split into %d hunks.\\n\",\n \t\t\t\t\t\t    scalar(@split)), scalar(@split));\n \t\t\t\t}\n@@ -1745,14 +1671,16 @@ sub quit_cmd {\n }\n \n sub help_cmd {\n-\tprint colored $help_color, __(\n-\"status        - show paths with changes\n+# TRANSLATORS: please do not translate the command names\n+# 'status', 'update', 'revert', etc.\n+\tprint colored $help_color, __ <<'EOF' ;\n+status        - show paths with changes\n update        - add working tree state to the staged set of changes\n revert        - revert staged set of changes back to the HEAD version\n patch         - pick hunks and update selectively\n diff\t      - view diff between HEAD and index\n-add untracked - add contents of untracked files to the staged set of changes\"),\n-\"\\n\";\n+add untracked - add contents of untracked files to the staged set of changes\n+EOF\n }\n \n sub process_args {\ndiff --git a/git-difftool.perl b/git-difftool.perl\nindex 0140c66..8d3632e 100755\n--- a/git-difftool.perl\n+++ b/git-difftool.perl\n@@ -339,7 +339,7 @@ sub main\n \t\tif (length($opts{difftool_cmd}) > 0) {\n \t\t\t$ENV{GIT_DIFF_TOOL} = $opts{difftool_cmd};\n \t\t} else {\n-\t\t\tprint \"No <tool> given for --tool=<tool>\\n\";\n+\t\t\tprint __(\"No <tool> given for --tool=<tool>\\n\");\n \t\t\tusage(1);\n \t\t}\n \t}\n@@ -347,7 +347,7 @@ sub main\n \t\tif (length($opts{extcmd}) > 0) {\n \t\t\t$ENV{GIT_DIFFTOOL_EXTCMD} = $opts{extcmd};\n \t\t} else {\n-\t\t\tprint \"No <cmd> given for --extcmd=<cmd>\\n\";\n+\t\t\tprint __(\"No <cmd> given for --extcmd=<cmd>\\n\");\n \t\t\tusage(1);\n \t\t}\n \t}\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex d4c72a9..5c01425 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -772,8 +772,8 @@ sub ask {\n \t\t\treturn $resp;\n \t\t}\n \t\tif ($confirm_only) {\n-\t\t\t# TRANSLATORS: Keep [y/N] as is.\n \t\t\tmy $yesno = $term->readline(\n+\t\t\t\t# TRANSLATORS: please keep [y/N] as is.\n \t\t\t\tsprintf(__(\"Are you sure you want to use <%s> [y/N]? \"), $resp));\n \t\t\tif (defined $yesno && $yesno =~ /y/i) {\n \t\t\t\treturn $resp;\n@@ -816,9 +816,9 @@ if (!defined $auto_8bit_encoding && scalar %broken_encoding) {\n if (!$force) {\n \tfor my $f (@files) {\n \t\tif (get_patch_subject($f) =~ /\\Q*** SUBJECT HERE ***\\E/) {\n-\t\t\tdie \"Refusing to send because the patch\\n\\t$f\\n\"\n+\t\t\tdie sprintf(__(\"Refusing to send because the patch\\n\\t%s\\n\"\n \t\t\t\t. \"has the template subject '*** SUBJECT HERE ***'. \"\n-\t\t\t\t. \"Pass --force if you really want to send.\\n\";\n+\t\t\t\t. \"Pass --force if you really want to send.\\n\"), $f);\n \t\t}\n \t}\n }\n@@ -1311,8 +1311,7 @@ Message-Id: $message_id\n \n     For additional information, run 'git send-email --help'.\n     To retain the current behavior, but squelch this message,\n-    run 'git config --global sendemail.confirm auto'.\"),\n-\"\\n\\n\";\n+    run 'git config --global sendemail.confirm auto'.\"), \"\\n\\n\";\n \t\t}\n \t\t# TRANSLATORS: Make sure to include [y] [n] [q] [a] in your\n \t\t# translation. The program will only accept English input\n@@ -1396,8 +1395,8 @@ Message-Id: $message_id\n \t\t}\n \n \t\tif (!$smtp) {\n-\t\t\tdie \"Unable to initialize SMTP properly. Check config and use --smtp-debug. \",\n-\t\t\t    \"VALUES: server=$smtp_server \",\n+\t\t\tdie __(\"Unable to initialize SMTP properly. Check config and use --smtp-debug.\"),\n+\t\t\t    \" VALUES: server=$smtp_server \",\n \t\t\t    \"encryption=$smtp_encryption \",\n \t\t\t    \"hello=$smtp_domain\",\n \t\t\t    defined $smtp_server_port ? \" port=$smtp_server_port\" : \"\";\n@@ -1414,12 +1413,12 @@ Message-Id: $message_id\n \t\t\t$smtp->datasend(\"$line\") or die $smtp->message;\n \t\t}\n \t\t$smtp->dataend() or die $smtp->message;\n-\t\t$smtp->code =~ /250|200/ or die \"Failed to send $subject\\n\".$smtp->message;\n+\t\t$smtp->code =~ /250|200/ or die sprintf(__(\"Failed to send %s\\n\"), $subject).$smtp->message;\n \t}\n \tif ($quiet) {\n-\t\tprintf (($dry_run ? \"Dry-\" : \"\"). __(\"Sent %s\\n\"), $subject);\n+\t\tprintf($dry_run ? __(\"Dry-Sent %s\\n\") : __(\"Sent %s\\n\"), $subject);\n \t} else {\n-\t\tprint (($dry_run ? \"Dry-\" : \"\"). __(\"OK. Log says:\\n\"));\n+\t\tprint($dry_run ? __(\"Dry-OK. Log says:\\n\") : __(\"OK. Log says:\\n\"));\n \t\tif (!file_name_is_absolute($smtp_server)) {\n \t\t\tprint \"Server: $smtp_server\\n\";\n \t\t\tprint \"MAIL FROM:<$raw_from>\\n\";\n@@ -1669,7 +1668,7 @@ sub recipients_cmd {\n \n \tmy @addresses = ();\n \topen my $fh, \"-|\", \"$cmd \\Q$file\\E\"\n-\t    or die \"($prefix) Could not execute '$cmd'\";\n+\t    or die sprintf(__(\"(%s) Could not execute '%s'\"), $prefix, $cmd);\n \twhile (my $address = <$fh>) {\n \t\t$address =~ s/^\\s*//g;\n \t\t$address =~ s/\\s*$//g;\n@@ -1753,10 +1752,11 @@ sub handle_backup {\n \t    (substr($file, 0, $lastlen) eq $last) &&\n \t    ($suffix = substr($file, $lastlen)) !~ /^[a-z0-9]/i) {\n \t\tif (defined $known_suffix && $suffix eq $known_suffix) {\n-\t\t\tprint \"Skipping $file with backup suffix '$known_suffix'.\\n\";\n+\t\t\tprintf(__(\"Skipping %s with backup suffix '%s'.\\n\"), $file, $known_suffix);\n \t\t\t$skip = 1;\n \t\t} else {\n-\t\t\tmy $answer = ask(\"Do you really want to send $file? (y|N): \",\n+\t\t\t# TRANSLATORS: please keep \"[y|N]\" as is.\n+\t\t\tmy $answer = ask(sprintf(__(\"Do you really want to send %s? [y|N]: \"), $file),\n \t\t\t\t\t valid_re => qr/^(?:y|n)/i,\n \t\t\t\t\t default => 'n');\n \t\t\t$skip = ($answer ne 'y');\ndiff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm\nindex 5a75dd5..3f7ac25 100644\n--- a/perl/Git/I18N.pm\n+++ b/perl/Git/I18N.pm\n@@ -13,7 +13,7 @@ BEGIN {\n \t}\n }\n \n-our @EXPORT = qw(__ Q__);\n+our @EXPORT = qw(__ __n);\n our @EXPORT_OK = @EXPORT;\n \n sub __bootstrap_locale_messages {\n@@ -44,7 +44,7 @@ BEGIN\n \teval {\n \t\t__bootstrap_locale_messages();\n \t\t*__ = \\&Locale::Messages::gettext;\n-\t\t*Q__ = \\&Locale::Messages::ngettext;\n+\t\t*__n = \\&Locale::Messages::ngettext;\n \t\t1;\n \t} or do {\n \t\t# Tell test.pl that we couldn't load the gettext library.\n@@ -52,7 +52,7 @@ BEGIN\n \n \t\t# Just a fall-through no-op\n \t\t*__ = sub ($) { $_[0] };\n-\t\t*Q__ = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };\n+\t\t*__n = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };\n \t};\n }\n \n@@ -72,6 +72,8 @@ Git::I18N - Perl interface to Git's Gettext localizations\n \n \tprintf __(\"The following error occurred: %s\\n\"), $error;\n \n+\tprintf __n(\"commited %d file\", \"commited %d files\", $files), $files;\n+\n =head1 DESCRIPTION\n \n Git's internal Perl interface to gettext via L<Locale::Messages>. If\n@@ -89,6 +91,9 @@ it.\n L<Locale::Messages>'s gettext function if all goes well, otherwise our\n passthrough fallback function.\n \n+=head2 __n($$$)\n+L<Locale::Messages>'s ngettext function or passthrough fallback function.\n+\n =head1 AUTHOR\n \n E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>\ndiff --git a/t/t0202/test.pl b/t/t0202/test.pl\nindex 98aa9a3..4101833 100755\n--- a/t/t0202/test.pl\n+++ b/t/t0202/test.pl\n@@ -31,7 +31,7 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \t# more gettext wrapper functions.\n \tmy %prototypes = (qw(\n \t\t__\t$\n-\t\tQ__\t$$$\n+\t\t__n\t$$$\n \t));\n \twhile (my ($sub, $proto) = each %prototypes) {\n \t\tis(prototype(\\&{\"Git::I18N::$sub\"}), $proto, \"sanity: $sub has a $proto prototype\");\n@@ -51,10 +51,10 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \tmy ($got_singular, $got_plural, $expect_singular, $expect_plural) =\n \t\t(('TEST: 1 file', 'TEST: n files') x 2);\n \n-\tis(Q__($got_singular, $got_plural, 1), $expect_singular,\n-\t\t\"Get singular string through Q__() in C locale\");\n-\tis(Q__($got_singular, $got_plural, 2), $expect_plural,\n-\t\t\"Get plural string through Q__() in C locale\");\n+\tis(__n($got_singular, $got_plural, 1), $expect_singular,\n+\t\t\"Get singular string through __n() in C locale\");\n+\tis(__n($got_singular, $got_plural, 2), $expect_plural,\n+\t\t\"Get plural string through __n() in C locale\");\n }\n \n # Test a basic message on different locales\n\n-- \n2.7.4\n\n"},{"id":"303396","messageId":"20161005172110.30801-3-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 02/14] i18n: add--interactive: mark simple here-documents for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:20:58Z","receivedAt":"2016-10-05T17:22:01Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark messages in here-document without interpolation for translation.\n\nThe here-document delimiter \\EOF, which is the same as 'EOF', indicate\nthat the text is to be treated literally without interpolation of its\ncontent.  Unfortunately xgettext is not able to extract here documents\nwith delimiter \\EOF but it is with delimiter enclosed in single quotes.\nThen change \\EOF to 'EOF', although in this case does not make\ndifference what variation of here-document to use since there is nothing\nto interpolate.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 8 +++++---\n 1 file changed, 5 insertions(+), 3 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex da0255b..3c10ced 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -639,7 +639,7 @@ sub list_and_choose {\n }\n \n sub singleton_prompt_help_cmd {\n-\tprint colored $help_color, <<\\EOF ;\n+\tprint colored $help_color, __ <<'EOF' ;\n Prompt help:\n 1          - select a numbered item\n foo        - select item based on unique prefix\n@@ -648,7 +648,7 @@ EOF\n }\n \n sub prompt_help_cmd {\n-\tprint colored $help_color, <<\\EOF ;\n+\tprint colored $help_color, __ <<'EOF' ;\n Prompt help:\n 1          - select a single item\n 3-5        - select a range of items\n@@ -1584,7 +1584,9 @@ sub quit_cmd {\n }\n \n sub help_cmd {\n-\tprint colored $help_color, <<\\EOF ;\n+# TRANSLATORS: please do not translate the command names\n+# 'status', 'update', 'revert', etc.\n+\tprint colored $help_color, __ <<'EOF' ;\n status        - show paths with changes\n update        - add working tree state to the staged set of changes\n revert        - revert staged set of changes back to the HEAD version\n-- \n2.7.4\n\n"},{"id":"303397","messageId":"20161005172110.30801-5-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 04/14] i18n: clean.c: match string with git-add--interactive.perl","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:21:00Z","receivedAt":"2016-10-05T17:22:04Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Change strings for help to match the ones in git-add--interactive.perl.\nThe strings now represent one entry to translate each rather then two\nentries each different only by an ending newline character.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n builtin/clean.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/clean.c b/builtin/clean.c\nindex 0371010..d6bc3aa 100644\n--- a/builtin/clean.c\n+++ b/builtin/clean.c\n@@ -287,11 +287,11 @@ static void pretty_print_menus(struct string_list *menu_list)\n static void prompt_help_cmd(int singleton)\n {\n \tclean_print_color(CLEAN_COLOR_HELP);\n-\tprintf_ln(singleton ?\n+\tprintf(singleton ?\n \t\t  _(\"Prompt help:\\n\"\n \t\t    \"1          - select a numbered item\\n\"\n \t\t    \"foo        - select item based on unique prefix\\n\"\n-\t\t    \"           - (empty) select nothing\") :\n+\t\t    \"           - (empty) select nothing\\n\") :\n \t\t  _(\"Prompt help:\\n\"\n \t\t    \"1          - select a single item\\n\"\n \t\t    \"3-5        - select a range of items\\n\"\n@@ -299,7 +299,7 @@ static void prompt_help_cmd(int singleton)\n \t\t    \"foo        - select item based on unique prefix\\n\"\n \t\t    \"-...       - unselect specified items\\n\"\n \t\t    \"*          - choose all items\\n\"\n-\t\t    \"           - (empty) finish selecting\"));\n+\t\t    \"           - (empty) finish selecting\\n\"));\n \tclean_print_color(CLEAN_COLOR_RESET);\n }\n \n@@ -508,7 +508,7 @@ static int parse_choice(struct menu_stuff *menu_stuff,\n \t\tif (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||\n \t\t    (is_single && bottom != top)) {\n \t\t\tclean_print_color(CLEAN_COLOR_ERROR);\n-\t\t\tprintf_ln(_(\"Huh (%s)?\"), (*ptr)->buf);\n+\t\t\tprintf(_(\"Huh (%s)?\\n\"), (*ptr)->buf);\n \t\t\tclean_print_color(CLEAN_COLOR_RESET);\n \t\t\tcontinue;\n \t\t}\n@@ -774,7 +774,7 @@ static int ask_each_cmd(void)\n static int quit_cmd(void)\n {\n \tstring_list_clear(&del_list, 0);\n-\tprintf_ln(_(\"Bye.\"));\n+\tprintf(_(\"Bye.\\n\"));\n \treturn MENU_RETURN_NO_LOOP;\n }\n \n-- \n2.7.4\n\n"},{"id":"303398","messageId":"20161005172110.30801-6-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 05/14] i18n: add--interactive: mark plural strings","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:21:01Z","receivedAt":"2016-10-05T17:22:06Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark plural strings for translation.  Unfold each action case in one\nentire sentence.\n\nPass new keyword for xgettext to extract.\n\nUpdate test to include new subroutine __n() for plural strings handling.\n\nUpdate documentation to include a description of the new __n() subroutine.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n\nOn the present re-roll, change name __Q to __n following the\nLocale::Message convention.\nAdd documentation about __n().\n\n Makefile                  |  3 ++-\n git-add--interactive.perl | 27 ++++++++++++++++++---------\n perl/Git/I18N.pm          |  9 ++++++++-\n t/t0202/test.pl           | 11 ++++++++++-\n 4 files changed, 38 insertions(+), 12 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 1aad150..4ef0344 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -2111,7 +2111,8 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \\\n \t--keyword=_ --keyword=N_ --keyword=\"Q_:1,2\"\n XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \\\n \t--keyword=gettextln --keyword=eval_gettextln\n-XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl\n+XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \\\n+\t--keyword=__ --keyword=\"__n:1,2\"\n LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)\n LOCALIZED_SH = $(SCRIPT_SH)\n LOCALIZED_SH += git-parse-remote.sh\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 50bcf94..6bbde2d 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -669,12 +669,18 @@ sub status_cmd {\n sub say_n_paths {\n \tmy $did = shift @_;\n \tmy $cnt = scalar @_;\n-\tprint \"$did \";\n-\tif (1 < $cnt) {\n-\t\tprint \"$cnt paths\\n\";\n-\t}\n-\telse {\n-\t\tprint \"one path\\n\";\n+\tif ($did eq 'added') {\n+\t\tprintf(__n(\"added %d path\\n\", \"added %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n+\t} elsif ($did eq 'updated') {\n+\t\tprintf(__n(\"updated %d path\\n\", \"updated %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n+\t} elsif ($did eq 'reverted') {\n+\t\tprintf(__n(\"reverted %d path\\n\", \"reverted %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n+\t} else {\n+\t\tprintf(__n(\"touched %d path\\n\", \"touched %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n \t}\n }\n \n@@ -1423,7 +1429,8 @@ sub patch_update_file {\n \t\t\t\t} elsif (0 < $response && $response <= $num) {\n \t\t\t\t\t$ix = $response - 1;\n \t\t\t\t} else {\n-\t\t\t\t\terror_msg \"Sorry, only $num hunks available.\\n\";\n+\t\t\t\t\terror_msg sprintf(__n(\"Sorry, only %d hunk available.\\n\",\n+\t\t\t\t\t\t\t      \"Sorry, only %d hunks available.\\n\", $num), $num);\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n@@ -1518,8 +1525,10 @@ sub patch_update_file {\n \t\t\telsif ($other =~ /s/ && $line =~ /^s/) {\n \t\t\t\tmy @split = split_hunk($hunk[$ix]{TEXT}, $hunk[$ix]{DISPLAY});\n \t\t\t\tif (1 < @split) {\n-\t\t\t\t\tprint colored $header_color, \"Split into \",\n-\t\t\t\t\tscalar(@split), \" hunks.\\n\";\n+\t\t\t\t\tprint colored $header_color, sprintf(\n+\t\t\t\t\t\t__n(\"Split into %d hunk.\\n\",\n+\t\t\t\t\t\t    \"Split into %d hunks.\\n\",\n+\t\t\t\t\t\t    scalar(@split)), scalar(@split));\n \t\t\t\t}\n \t\t\t\tsplice (@hunk, $ix, 1, @split);\n \t\t\t\t$num = scalar @hunk;\ndiff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm\nindex f889fd6..3f7ac25 100644\n--- a/perl/Git/I18N.pm\n+++ b/perl/Git/I18N.pm\n@@ -13,7 +13,7 @@ BEGIN {\n \t}\n }\n \n-our @EXPORT = qw(__);\n+our @EXPORT = qw(__ __n);\n our @EXPORT_OK = @EXPORT;\n \n sub __bootstrap_locale_messages {\n@@ -44,6 +44,7 @@ BEGIN\n \teval {\n \t\t__bootstrap_locale_messages();\n \t\t*__ = \\&Locale::Messages::gettext;\n+\t\t*__n = \\&Locale::Messages::ngettext;\n \t\t1;\n \t} or do {\n \t\t# Tell test.pl that we couldn't load the gettext library.\n@@ -51,6 +52,7 @@ BEGIN\n \n \t\t# Just a fall-through no-op\n \t\t*__ = sub ($) { $_[0] };\n+\t\t*__n = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };\n \t};\n }\n \n@@ -70,6 +72,8 @@ Git::I18N - Perl interface to Git's Gettext localizations\n \n \tprintf __(\"The following error occurred: %s\\n\"), $error;\n \n+\tprintf __n(\"commited %d file\", \"commited %d files\", $files), $files;\n+\n =head1 DESCRIPTION\n \n Git's internal Perl interface to gettext via L<Locale::Messages>. If\n@@ -87,6 +91,9 @@ it.\n L<Locale::Messages>'s gettext function if all goes well, otherwise our\n passthrough fallback function.\n \n+=head2 __n($$$)\n+L<Locale::Messages>'s ngettext function or passthrough fallback function.\n+\n =head1 AUTHOR\n \n E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>\ndiff --git a/t/t0202/test.pl b/t/t0202/test.pl\nindex 2c10cb4..4101833 100755\n--- a/t/t0202/test.pl\n+++ b/t/t0202/test.pl\n@@ -4,7 +4,7 @@ use lib (split(/:/, $ENV{GITPERLLIB}));\n use strict;\n use warnings;\n use POSIX qw(:locale_h);\n-use Test::More tests => 8;\n+use Test::More tests => 11;\n use Git::I18N;\n \n my $has_gettext_library = $Git::I18N::__HAS_LIBRARY;\n@@ -31,6 +31,7 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \t# more gettext wrapper functions.\n \tmy %prototypes = (qw(\n \t\t__\t$\n+\t\t__n\t$$$\n \t));\n \twhile (my ($sub, $proto) = each %prototypes) {\n \t\tis(prototype(\\&{\"Git::I18N::$sub\"}), $proto, \"sanity: $sub has a $proto prototype\");\n@@ -46,6 +47,14 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \tmy ($got, $expect) = (('TEST: A Perl test string') x 2);\n \n \tis(__($got), $expect, \"Passing a string through __() in the C locale works\");\n+\n+\tmy ($got_singular, $got_plural, $expect_singular, $expect_plural) =\n+\t\t(('TEST: 1 file', 'TEST: n files') x 2);\n+\n+\tis(__n($got_singular, $got_plural, 1), $expect_singular,\n+\t\t\"Get singular string through __n() in C locale\");\n+\tis(__n($got_singular, $got_plural, 2), $expect_plural,\n+\t\t\"Get plural string through __n() in C locale\");\n }\n \n # Test a basic message on different locales\n-- \n2.7.4\n\n"},{"id":"303399","messageId":"20161005172110.30801-4-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 03/14] i18n: add--interactive: mark strings with interpolation for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:20:59Z","receivedAt":"2016-10-05T17:22:07Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Since at this point Git::I18N.perl lacks support for Perl i18n\nplaceholder substitution, use of sprintf following die or error_msg is\nnecessary for placeholder substitution take place.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 23 ++++++++++++-----------\n 1 file changed, 12 insertions(+), 11 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 3c10ced..50bcf94 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -615,12 +615,12 @@ sub list_and_choose {\n \t\t\telse {\n \t\t\t\t$bottom = $top = find_unique($choice, @stuff);\n \t\t\t\tif (!defined $bottom) {\n-\t\t\t\t\terror_msg \"Huh ($choice)?\\n\";\n+\t\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\\n\"), $choice);\n \t\t\t\t\tnext TOPLOOP;\n \t\t\t\t}\n \t\t\t}\n \t\t\tif ($opts->{SINGLETON} && $bottom != $top) {\n-\t\t\t\terror_msg \"Huh ($choice)?\\n\";\n+\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\"), $choice);\n \t\t\t\tnext TOPLOOP;\n \t\t\t}\n \t\t\tfor ($i = $bottom-1; $i <= $top-1; $i++) {\n@@ -1056,7 +1056,7 @@ sub edit_hunk_manually {\n \tmy $hunkfile = $repo->repo_path . \"/addp-hunk-edit.diff\";\n \tmy $fh;\n \topen $fh, '>', $hunkfile\n-\t\tor die \"failed to open hunk edit file for writing: \" . $!;\n+\t\tor die sprintf(__(\"failed to open hunk edit file for writing: %s\"), $!);\n \tprint $fh \"# Manual hunk edit mode -- see bottom for a quick guide\\n\";\n \tprint $fh @$oldtext;\n \tmy $participle = $patch_mode_flavour{PARTICIPLE};\n@@ -1083,7 +1083,7 @@ EOF\n \t}\n \n \topen $fh, '<', $hunkfile\n-\t\tor die \"failed to open hunk edit file for reading: \" . $!;\n+\t\tor die sprintf(__(\"failed to open hunk edit file for reading: %s\"), $!);\n \tmy @newtext = grep { !/^#/ } <$fh>;\n \tclose $fh;\n \tunlink $hunkfile;\n@@ -1236,7 +1236,7 @@ sub apply_patch_for_checkout_commit {\n \n sub patch_update_cmd {\n \tmy @all_mods = list_modified($patch_mode_flavour{FILTER});\n-\terror_msg \"ignoring unmerged: $_->{VALUE}\\n\"\n+\terror_msg sprintf(__(\"ignoring unmerged: %s\\n\"), $_->{VALUE})\n \t\tfor grep { $_->{UNMERGED} } @all_mods;\n \t@all_mods = grep { !$_->{UNMERGED} } @all_mods;\n \n@@ -1418,7 +1418,8 @@ sub patch_update_file {\n \t\t\t\t\tchomp $response;\n \t\t\t\t}\n \t\t\t\tif ($response !~ /^\\s*\\d+\\s*$/) {\n-\t\t\t\t\terror_msg \"Invalid number: '$response'\\n\";\n+\t\t\t\t\terror_msg sprintf(__(\"Invalid number: '%s'\\n\"),\n+\t\t\t\t\t\t\t     $response);\n \t\t\t\t} elsif (0 < $response && $response <= $num) {\n \t\t\t\t\t$ix = $response - 1;\n \t\t\t\t} else {\n@@ -1460,7 +1461,7 @@ sub patch_update_file {\n \t\t\t\tif ($@) {\n \t\t\t\t\tmy ($err,$exp) = ($@, $1);\n \t\t\t\t\t$err =~ s/ at .*git-add--interactive line \\d+, <STDIN> line \\d+.*$//;\n-\t\t\t\t\terror_msg \"Malformed search regexp $exp: $err\\n\";\n+\t\t\t\t\terror_msg sprintf(__(\"Malformed search regexp %s: %s\\n\"), $exp, $err);\n \t\t\t\t\tnext;\n \t\t\t\t}\n \t\t\t\tmy $iy = $ix;\n@@ -1625,18 +1626,18 @@ sub process_args {\n \t\t\t\t$patch_mode = $1;\n \t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t} else {\n-\t\t\t\tdie \"unknown --patch mode: $1\";\n+\t\t\t\tdie sprintf(__(\"unknown --patch mode: %s\"), $1);\n \t\t\t}\n \t\t} else {\n \t\t\t$patch_mode = 'stage';\n \t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t}\n-\t\tdie \"invalid argument $arg, expecting --\"\n-\t\t    unless $arg eq \"--\";\n+\t\tdie sprintf(__(\"invalid argument %s, expecting --\"),\n+\t\t\t       $arg) unless $arg eq \"--\";\n \t\t%patch_mode_flavour = %{$patch_modes{$patch_mode}};\n \t}\n \telsif ($arg ne \"--\") {\n-\t\tdie \"invalid argument $arg, expecting --\";\n+\t\tdie sprintf(__(\"invalid argument %s, expecting --\"), $arg);\n \t}\n }\n \n-- \n2.7.4\n\n"},{"id":"303400","messageId":"20161005172110.30801-2-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 01/14] i18n: add--interactive: mark strings for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:20:57Z","receivedAt":"2016-10-05T17:22:16Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark simple strings (without interpolation) for translation.\n\nBrackets around first parameter of ternary operator is necessary because\notherwise xgettext fails to extract strings marked for translation from\nthe rest of the file.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 74 ++++++++++++++++++++++++++---------------------\n 1 file changed, 41 insertions(+), 33 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex ee3d812..da0255b 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -4,6 +4,7 @@ use 5.008;\n use strict;\n use warnings;\n use Git;\n+use Git::I18N;\n \n binmode(STDOUT, \":raw\");\n \n@@ -253,8 +254,9 @@ sub list_untracked {\n \trun_cmd_pipe(qw(git ls-files --others --exclude-standard --), @ARGV);\n }\n \n-my $status_fmt = '%12s %12s %s';\n-my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');\n+# TRANSLATORS: you can adjust this to align \"git add -i\" status menu\n+my $status_fmt = __('%12s %12s %s');\n+my $status_head = sprintf($status_fmt, __('staged'), __('unstaged'), __('path'));\n \n {\n \tmy $initial;\n@@ -680,7 +682,7 @@ sub update_cmd {\n \tmy @mods = list_modified('file-only');\n \treturn if (!@mods);\n \n-\tmy @update = list_and_choose({ PROMPT => 'Update',\n+\tmy @update = list_and_choose({ PROMPT => __('Update'),\n \t\t\t\t       HEADER => $status_head, },\n \t\t\t\t     @mods);\n \tif (@update) {\n@@ -692,7 +694,7 @@ sub update_cmd {\n }\n \n sub revert_cmd {\n-\tmy @update = list_and_choose({ PROMPT => 'Revert',\n+\tmy @update = list_and_choose({ PROMPT => __('Revert'),\n \t\t\t\t       HEADER => $status_head, },\n \t\t\t\t     list_modified());\n \tif (@update) {\n@@ -726,13 +728,13 @@ sub revert_cmd {\n }\n \n sub add_untracked_cmd {\n-\tmy @add = list_and_choose({ PROMPT => 'Add untracked' },\n+\tmy @add = list_and_choose({ PROMPT => __('Add untracked') },\n \t\t\t\t  list_untracked());\n \tif (@add) {\n \t\tsystem(qw(git update-index --add --), @add);\n \t\tsay_n_paths('added', @add);\n \t} else {\n-\t\tprint \"No untracked files.\\n\";\n+\t\tprint __(\"No untracked files.\\n\");\n \t}\n \tprint \"\\n\";\n }\n@@ -1166,8 +1168,14 @@ sub edit_hunk_loop {\n \t\t}\n \t\telse {\n \t\t\tprompt_yesno(\n-\t\t\t\t'Your edited hunk does not apply. Edit again '\n-\t\t\t\t. '(saying \"no\" discards!) [y/n]? '\n+\t\t\t\t# TRANSLATORS: do not translate [y/n]\n+\t\t\t\t# The program will only accept that input\n+\t\t\t\t# at this point.\n+\t\t\t\t# Consider translating (saying \"no\" discards!) as\n+\t\t\t\t# (saying \"n\" for \"no\" discards!) if the translation\n+\t\t\t\t# of the word \"no\" does not start with n.\n+\t\t\t\t__('Your edited hunk does not apply. Edit again '\n+\t\t\t\t   . '(saying \"no\" discards!) [y/n]? ')\n \t\t\t\t) or return undef;\n \t\t}\n \t}\n@@ -1213,11 +1221,11 @@ sub apply_patch_for_checkout_commit {\n \t\trun_git_apply 'apply '.$reverse, @_;\n \t\treturn 1;\n \t} elsif (!$applies_index) {\n-\t\tprint colored $error_color, \"The selected hunks do not apply to the index!\\n\";\n-\t\tif (prompt_yesno \"Apply them to the worktree anyway? \") {\n+\t\tprint colored $error_color, __(\"The selected hunks do not apply to the index!\\n\");\n+\t\tif (prompt_yesno __(\"Apply them to the worktree anyway? \")) {\n \t\t\treturn run_git_apply 'apply '.$reverse, @_;\n \t\t} else {\n-\t\t\tprint colored $error_color, \"Nothing was applied.\\n\";\n+\t\t\tprint colored $error_color, __(\"Nothing was applied.\\n\");\n \t\t\treturn 0;\n \t\t}\n \t} else {\n@@ -1237,9 +1245,9 @@ sub patch_update_cmd {\n \n \tif (!@mods) {\n \t\tif (@all_mods) {\n-\t\t\tprint STDERR \"Only binary files changed.\\n\";\n+\t\t\tprint STDERR __(\"Only binary files changed.\\n\");\n \t\t} else {\n-\t\t\tprint STDERR \"No changes.\\n\";\n+\t\t\tprint STDERR __(\"No changes.\\n\");\n \t\t}\n \t\treturn 0;\n \t}\n@@ -1397,12 +1405,12 @@ sub patch_update_file {\n \t\t\t\tmy $response = $1;\n \t\t\t\tmy $no = $ix > 10 ? $ix - 10 : 0;\n \t\t\t\twhile ($response eq '') {\n-\t\t\t\t\tmy $extra = \"\";\n \t\t\t\t\t$no = display_hunks(\\@hunk, $no);\n \t\t\t\t\tif ($no < $num) {\n-\t\t\t\t\t\t$extra = \" (<ret> to see more)\";\n+\t\t\t\t\t\tprint __(\"go to which hunk (<ret> to see more)? \");\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tprint __(\"go to which hunk? \");\n \t\t\t\t\t}\n-\t\t\t\t\tprint \"go to which hunk$extra? \";\n \t\t\t\t\t$response = <STDIN>;\n \t\t\t\t\tif (!defined $response) {\n \t\t\t\t\t\t$response = '';\n@@ -1439,7 +1447,7 @@ sub patch_update_file {\n \t\t\telsif ($line =~ m|^/(.*)|) {\n \t\t\t\tmy $regex = $1;\n \t\t\t\tif ($1 eq \"\") {\n-\t\t\t\t\tprint colored $prompt_color, \"search for regex? \";\n+\t\t\t\t\tprint colored $prompt_color, __(\"search for regex? \");\n \t\t\t\t\t$regex = <STDIN>;\n \t\t\t\t\tif (defined $regex) {\n \t\t\t\t\t\tchomp $regex;\n@@ -1462,7 +1470,7 @@ sub patch_update_file {\n \t\t\t\t\t$iy++;\n \t\t\t\t\t$iy = 0 if ($iy >= $num);\n \t\t\t\t\tif ($ix == $iy) {\n-\t\t\t\t\t\terror_msg \"No hunk matches the given pattern\\n\";\n+\t\t\t\t\t\terror_msg __(\"No hunk matches the given pattern\\n\");\n \t\t\t\t\t\tlast;\n \t\t\t\t\t}\n \t\t\t\t}\n@@ -1474,7 +1482,7 @@ sub patch_update_file {\n \t\t\t\t\t$ix--;\n \t\t\t\t}\n \t\t\t\telse {\n-\t\t\t\t\terror_msg \"No previous hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No previous hunk\\n\");\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n@@ -1483,7 +1491,7 @@ sub patch_update_file {\n \t\t\t\t\t$ix++;\n \t\t\t\t}\n \t\t\t\telse {\n-\t\t\t\t\terror_msg \"No next hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No next hunk\\n\");\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n@@ -1496,13 +1504,13 @@ sub patch_update_file {\n \t\t\t\t\t}\n \t\t\t\t}\n \t\t\t\telse {\n-\t\t\t\t\terror_msg \"No previous hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No previous hunk\\n\");\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n \t\t\telsif ($line =~ /^j/) {\n \t\t\t\tif ($other !~ /j/) {\n-\t\t\t\t\terror_msg \"No next hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No next hunk\\n\");\n \t\t\t\t\tnext;\n \t\t\t\t}\n \t\t\t}\n@@ -1560,18 +1568,18 @@ sub diff_cmd {\n \tmy @mods = list_modified('index-only');\n \t@mods = grep { !($_->{BINARY}) } @mods;\n \treturn if (!@mods);\n-\tmy (@them) = list_and_choose({ PROMPT => 'Review diff',\n+\tmy (@them) = list_and_choose({ PROMPT => __('Review diff'),\n \t\t\t\t     IMMEDIATE => 1,\n \t\t\t\t     HEADER => $status_head, },\n \t\t\t\t   @mods);\n \treturn if (!@them);\n-\tmy $reference = is_initial_commit() ? get_empty_tree() : 'HEAD';\n+\tmy $reference = (is_initial_commit()) ? get_empty_tree() : 'HEAD';\n \tsystem(qw(git diff -p --cached), $reference, '--',\n \t\tmap { $_->{VALUE} } @them);\n }\n \n sub quit_cmd {\n-\tprint \"Bye.\\n\";\n+\tprint __(\"Bye.\\n\");\n \texit(0);\n }\n \n@@ -1594,32 +1602,32 @@ sub process_args {\n \t\t\tif ($1 eq 'reset') {\n \t\t\t\t$patch_mode = 'reset_head';\n \t\t\t\t$patch_mode_revision = 'HEAD';\n-\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\tif ($arg ne '--') {\n \t\t\t\t\t$patch_mode_revision = $arg;\n \t\t\t\t\t$patch_mode = ($arg eq 'HEAD' ?\n \t\t\t\t\t\t       'reset_head' : 'reset_nothead');\n-\t\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\t}\n \t\t\t} elsif ($1 eq 'checkout') {\n-\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\tif ($arg eq '--') {\n \t\t\t\t\t$patch_mode = 'checkout_index';\n \t\t\t\t} else {\n \t\t\t\t\t$patch_mode_revision = $arg;\n \t\t\t\t\t$patch_mode = ($arg eq 'HEAD' ?\n \t\t\t\t\t\t       'checkout_head' : 'checkout_nothead');\n-\t\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\t}\n \t\t\t} elsif ($1 eq 'stage' or $1 eq 'stash') {\n \t\t\t\t$patch_mode = $1;\n-\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t} else {\n \t\t\t\tdie \"unknown --patch mode: $1\";\n \t\t\t}\n \t\t} else {\n \t\t\t$patch_mode = 'stage';\n-\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t}\n \t\tdie \"invalid argument $arg, expecting --\"\n \t\t    unless $arg eq \"--\";\n@@ -1641,10 +1649,10 @@ sub main_loop {\n \t\t   [ 'help', \\&help_cmd, ],\n \t);\n \twhile (1) {\n-\t\tmy ($it) = list_and_choose({ PROMPT => 'What now',\n+\t\tmy ($it) = list_and_choose({ PROMPT => __('What now'),\n \t\t\t\t\t     SINGLETON => 1,\n \t\t\t\t\t     LIST_FLAT => 4,\n-\t\t\t\t\t     HEADER => '*** Commands ***',\n+\t\t\t\t\t     HEADER => __('*** Commands ***'),\n \t\t\t\t\t     ON_EOF => \\&quit_cmd,\n \t\t\t\t\t     IMMEDIATE => 1 }, @cmd);\n \t\tif ($it) {\n-- \n2.7.4\n\n"},{"id":"303401","messageId":"20161005172110.30801-7-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 06/14] i18n: add--interactive: mark patch prompt for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:21:02Z","receivedAt":"2016-10-05T17:22:19Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark prompt message assembled in place for translation, unfolding each\nuse case for each entry in the %patch_modes hash table.\n\nPreviously, this script relied on whether $patch_mode was set to run the\ncommand patch_update_cmd() or show status and loop the main loop. Now,\nit uses $cmd to indicate we must run patch_update_cmd() and $patch_mode\nis used to tell which flavor of the %patch_modes are we on.  This is\nintroduced in order to be able to mark and unfold the message prompt\nknowing in which context we are.\n\nThe tracking of context was done previously by point %patch_mode_flavour\nhash table to the correct entry of %patch_modes, focusing only on value\nof %patch_modes. Now, we are also interested in the key ('staged',\n'stash', 'checkout_head', ...).\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 54 ++++++++++++++++++++++++++++++++++++++++-------\n 1 file changed, 46 insertions(+), 8 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 6bbde2d..c8d5093 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -93,6 +93,7 @@ sub colored {\n }\n \n # command line options\n+my $cmd;\n my $patch_mode;\n my $patch_mode_revision;\n \n@@ -173,7 +174,8 @@ my %patch_modes = (\n \t},\n );\n \n-my %patch_mode_flavour = %{$patch_modes{stage}};\n+$patch_mode = 'stage';\n+my %patch_mode_flavour = %{$patch_modes{$patch_mode}};\n \n sub run_cmd_pipe {\n \tif ($^O eq 'MSWin32') {\n@@ -1311,6 +1313,44 @@ sub display_hunks {\n \treturn $i;\n }\n \n+my %patch_update_prompt_modes = (\n+\tstage => {\n+\t\tmode => __(\"Stage mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Stage deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Stage this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tstash => {\n+\t\tmode => __(\"Stash mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Stash deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Stash this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\treset_head => {\n+\t\tmode => __(\"Unstage mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Unstage deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Unstage this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\treset_nothead => {\n+\t\tmode => __(\"Apply mode change to index [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Apply deletion to index [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Apply this hunk to index [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_index => {\n+\t\tmode => __(\"Discard mode change from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Discard deletion from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Discard this hunk from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_head => {\n+\t\tmode => __(\"Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_nothead => {\n+\t\tmode => __(\"Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => __(\"Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => __(\"Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+);\n+\n sub patch_update_file {\n \tmy $quit = 0;\n \tmy ($ix, $num);\n@@ -1383,12 +1423,9 @@ sub patch_update_file {\n \t\tfor (@{$hunk[$ix]{DISPLAY}}) {\n \t\t\tprint;\n \t\t}\n-\t\tprint colored $prompt_color, $patch_mode_flavour{VERB},\n-\t\t  ($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' :\n-\t\t   $hunk[$ix]{TYPE} eq 'deletion' ? ' deletion' :\n-\t\t   ' this hunk'),\n-\t\t  $patch_mode_flavour{TARGET},\n-\t\t  \" [y,n,q,a,d,/$other,?]? \";\n+\t\tprint colored $prompt_color,\n+\t\t\tsprintf($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}, $other);\n+\n \t\tmy $line = prompt_single_character;\n \t\tlast unless defined $line;\n \t\tif ($line) {\n@@ -1644,6 +1681,7 @@ sub process_args {\n \t\tdie sprintf(__(\"invalid argument %s, expecting --\"),\n \t\t\t       $arg) unless $arg eq \"--\";\n \t\t%patch_mode_flavour = %{$patch_modes{$patch_mode}};\n+\t\t$cmd = 1;\n \t}\n \telsif ($arg ne \"--\") {\n \t\tdie sprintf(__(\"invalid argument %s, expecting --\"), $arg);\n@@ -1680,7 +1718,7 @@ sub main_loop {\n \n process_args();\n refresh();\n-if ($patch_mode) {\n+if ($cmd) {\n \tpatch_update_cmd();\n }\n else {\n-- \n2.7.4\n\n"},{"id":"303402","messageId":"20161005172110.30801-8-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 07/14] i18n: add--interactive: i18n of help_patch_cmd","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:21:03Z","receivedAt":"2016-10-05T17:22:21Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark help message of help_patch_cmd for translation.  The message must\nbe unfolded to be free of variables so we can have high quality\ntranslations.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 54 ++++++++++++++++++++++++++++++++++++++++-------\n 1 file changed, 46 insertions(+), 8 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex c8d5093..35967fe 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -1189,15 +1189,53 @@ sub edit_hunk_loop {\n \t}\n }\n \n+my %help_patch_modes = (\n+\tstage => __(\n+\"y - stage this hunk\n+n - do not stage this hunk\n+q - quit; do not stage this hunk or any of the remaining ones\n+a - stage this hunk and all later hunks in the file\n+d - do not stage this hunk or any of the later hunks in the file\"),\n+\tstash => __(\n+\"y - stash this hunk\n+n - do not stash this hunk\n+q - quit; do not stash this hunk or any of the remaining ones\n+a - stash this hunk and all later hunks in the file\n+d - do not stash this hunk or any of the later hunks in the file\"),\n+\treset_head => __(\n+\"y - unstage this hunk\n+n - do not unstage this hunk\n+q - quit; do not unstage this hunk or any of the remaining ones\n+a - unstage this hunk and all later hunks in the file\n+d - do not unstage this hunk or any of the later hunks in the file\"),\n+\treset_nothead => __(\n+\"y - apply this hunk to index\n+n - do not apply this hunk to index\n+q - quit; do not apply this hunk or any of the remaining ones\n+a - apply this hunk and all later hunks in the file\n+d - do not apply this hunk or any of the later hunks in the file\"),\n+\tcheckout_index => __(\n+\"y - discard this hunk from worktree\n+n - do not discard this hunk from worktree\n+q - quit; do not discard this hunk or any of the remaining ones\n+a - discard this hunk and all later hunks in the file\n+d - do not discard this hunk or any of the later hunks in the file\"),\n+\tcheckout_head => __(\n+\"y - discard this hunk from index and worktree\n+n - do not discard this hunk from index and worktree\n+q - quit; do not discard this hunk or any of the remaining ones\n+a - discard this hunk and all later hunks in the file\n+d - do not discard this hunk or any of the later hunks in the file\"),\n+\tcheckout_nothead => __(\n+\"y - apply this hunk to index and worktree\n+n - do not apply this hunk to index and worktree\n+q - quit; do not apply this hunk or any of the remaining ones\n+a - apply this hunk and all later hunks in the file\n+d - do not apply this hunk or any of the later hunks in the file\"),\n+);\n+\n sub help_patch_cmd {\n-\tmy $verb = lc $patch_mode_flavour{VERB};\n-\tmy $target = $patch_mode_flavour{TARGET};\n-\tprint colored $help_color, <<EOF ;\n-y - $verb this hunk$target\n-n - do not $verb this hunk$target\n-q - quit; do not $verb this hunk or any of the remaining ones\n-a - $verb this hunk and all later hunks in the file\n-d - do not $verb this hunk or any of the later hunks in the file\n+\tprint colored $help_color, $help_patch_modes{$patch_mode}, \"\\n\", __ <<EOF ;\n g - select a hunk to go to\n / - search for a hunk matching the given regex\n j - leave this hunk undecided, see next undecided hunk\n-- \n2.7.4\n\n"},{"id":"303403","messageId":"20161005172110.30801-9-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 08/14] i18n: add--interactive: mark edit_hunk_manually message for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:21:04Z","receivedAt":"2016-10-05T17:22:23Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark message of edit_hunk_manually displayed in the editing file when\nuser chooses 'e' option.  The message had to be unfolded to allow\ntranslation of the $participle verb.\n\nSome messages end up being exactly the same for some uses cases, but\nleft it for easier change in the future, e.g., wanting to change wording\nof one particular use case.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 45 ++++++++++++++++++++++++++++++++++-----------\n 1 file changed, 34 insertions(+), 11 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 35967fe..5356d5a 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -1058,6 +1058,30 @@ sub color_diff {\n \t} @_;\n }\n \n+my %edit_hunk_manually_modes = (\n+\tstage => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for staging.\"),\n+\tstash => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for stashing.\"),\n+\treset_head => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for unstaging.\"),\n+\treset_nothead => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for applying.\"),\n+\tcheckout_index => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for discarding\"),\n+\tcheckout_head => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for discarding.\"),\n+\tcheckout_nothead => __(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for applying.\"),\n+);\n+\n sub edit_hunk_manually {\n \tmy ($oldtext) = @_;\n \n@@ -1065,22 +1089,21 @@ sub edit_hunk_manually {\n \tmy $fh;\n \topen $fh, '>', $hunkfile\n \t\tor die sprintf(__(\"failed to open hunk edit file for writing: %s\"), $!);\n-\tprint $fh \"# Manual hunk edit mode -- see bottom for a quick guide\\n\";\n+\tprint $fh __(\"# Manual hunk edit mode -- see bottom for a quick guide\\n\");\n \tprint $fh @$oldtext;\n-\tmy $participle = $patch_mode_flavour{PARTICIPLE};\n \tmy $is_reverse = $patch_mode_flavour{IS_REVERSE};\n \tmy ($remove_plus, $remove_minus) = $is_reverse ? ('-', '+') : ('+', '-');\n-\tprint $fh <<EOF;\n-# ---\n-# To remove '$remove_minus' lines, make them ' ' lines (context).\n-# To remove '$remove_plus' lines, delete them.\n+\tprint $fh sprintf(__(\n+\"# ---\n+# To remove '%s' lines, make them ' ' lines (context).\n+# To remove '%s' lines, delete them.\n # Lines starting with # will be removed.\n-#\n-# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for $participle. If it does not apply cleanly, you will be given\n+#\\n\"), $remove_minus, $remove_plus),\n+$edit_hunk_manually_modes{$patch_mode}, __(\n+# TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.\n+\" If it does not apply cleanly, you will be given\n # an opportunity to edit again. If all lines of the hunk are removed,\n-# then the edit is aborted and the hunk is left unchanged.\n-EOF\n+# then the edit is aborted and the hunk is left unchanged.\\n\");\n \tclose $fh;\n \n \tchomp(my $editor = run_cmd_pipe(qw(git var GIT_EDITOR)));\n-- \n2.7.4\n\n"},{"id":"303404","messageId":"20161005172110.30801-10-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 09/14] i18n: add--interactive: remove %patch_modes entries","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:21:05Z","receivedAt":"2016-10-05T17:22:26Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Remove unnecessary entries from %patch_modes. After the i18n conversion,\nthese entries are not used anymore.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 21 ---------------------\n 1 file changed, 21 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 5356d5a..e81939f 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -106,9 +106,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-files -p',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Stage',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'staging',\n \t\tFILTER => 'file-only',\n \t\tIS_REVERSE => 0,\n \t},\n@@ -116,9 +113,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p HEAD',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Stash',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'stashing',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 0,\n \t},\n@@ -126,9 +120,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p --cached',\n \t\tAPPLY => sub { apply_patch 'apply -R --cached', @_; },\n \t\tAPPLY_CHECK => 'apply -R --cached',\n-\t\tVERB => 'Unstage',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'unstaging',\n \t\tFILTER => 'index-only',\n \t\tIS_REVERSE => 1,\n \t},\n@@ -136,9 +127,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -R -p --cached',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Apply',\n-\t\tTARGET => ' to index',\n-\t\tPARTICIPLE => 'applying',\n \t\tFILTER => 'index-only',\n \t\tIS_REVERSE => 0,\n \t},\n@@ -146,9 +134,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-files -p',\n \t\tAPPLY => sub { apply_patch 'apply -R', @_; },\n \t\tAPPLY_CHECK => 'apply -R',\n-\t\tVERB => 'Discard',\n-\t\tTARGET => ' from worktree',\n-\t\tPARTICIPLE => 'discarding',\n \t\tFILTER => 'file-only',\n \t\tIS_REVERSE => 1,\n \t},\n@@ -156,9 +141,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p',\n \t\tAPPLY => sub { apply_patch_for_checkout_commit '-R', @_ },\n \t\tAPPLY_CHECK => 'apply -R',\n-\t\tVERB => 'Discard',\n-\t\tTARGET => ' from index and worktree',\n-\t\tPARTICIPLE => 'discarding',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 1,\n \t},\n@@ -166,9 +148,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -R -p',\n \t\tAPPLY => sub { apply_patch_for_checkout_commit '', @_ },\n \t\tAPPLY_CHECK => 'apply',\n-\t\tVERB => 'Apply',\n-\t\tTARGET => ' to index and worktree',\n-\t\tPARTICIPLE => 'applying',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 0,\n \t},\n-- \n2.7.4\n\n"},{"id":"303405","messageId":"20161005172110.30801-11-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 10/14] i18n: add--interactive: mark status words for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:21:06Z","receivedAt":"2016-10-05T17:22:28Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark words 'nothing', 'unchanged' and 'binary' used to display what has\nbeen staged or not, in \"git add -i\" status command.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex e81939f..0b4a27c 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -295,7 +295,7 @@ sub list_modified {\n \t\t\tmy ($change, $bin);\n \t\t\t$file = unquote_path($file);\n \t\t\tif ($add eq '-' && $del eq '-') {\n-\t\t\t\t$change = 'binary';\n+\t\t\t\t$change = __('binary');\n \t\t\t\t$bin = 1;\n \t\t\t}\n \t\t\telse {\n@@ -304,7 +304,7 @@ sub list_modified {\n \t\t\t$data{$file} = {\n \t\t\t\tINDEX => $change,\n \t\t\t\tBINARY => $bin,\n-\t\t\t\tFILE => 'nothing',\n+\t\t\t\tFILE => __('nothing'),\n \t\t\t}\n \t\t}\n \t\telsif (($adddel, $file) =\n@@ -320,7 +320,7 @@ sub list_modified {\n \t\t\t$file = unquote_path($file);\n \t\t\tmy ($change, $bin);\n \t\t\tif ($add eq '-' && $del eq '-') {\n-\t\t\t\t$change = 'binary';\n+\t\t\t\t$change = __('binary');\n \t\t\t\t$bin = 1;\n \t\t\t}\n \t\t\telse {\n@@ -340,7 +340,7 @@ sub list_modified {\n \t\t\t$file = unquote_path($2);\n \t\t\tif (!exists $data{$file}) {\n \t\t\t\t$data{$file} = +{\n-\t\t\t\t\tINDEX => 'unchanged',\n+\t\t\t\t\tINDEX => __('unchanged'),\n \t\t\t\t\tBINARY => 0,\n \t\t\t\t};\n \t\t\t}\n@@ -355,10 +355,10 @@ sub list_modified {\n \n \t\tif ($only) {\n \t\t\tif ($only eq 'index-only') {\n-\t\t\t\tnext if ($it->{INDEX} eq 'unchanged');\n+\t\t\t\tnext if ($it->{INDEX} eq __('unchanged'));\n \t\t\t}\n \t\t\tif ($only eq 'file-only') {\n-\t\t\t\tnext if ($it->{FILE} eq 'nothing');\n+\t\t\t\tnext if ($it->{FILE} eq __('nothing'));\n \t\t\t}\n \t\t}\n \t\tpush @return, +{\n-- \n2.7.4\n\n"},{"id":"303406","messageId":"20161005172110.30801-12-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 11/14] i18n: send-email: mark strings for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:21:07Z","receivedAt":"2016-10-05T17:22:33Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark strings often displayed to the user for translation.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-send-email.perl | 52 ++++++++++++++++++++++++++++++----------------------\n 1 file changed, 30 insertions(+), 22 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex da81be4..78eb59b 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -28,6 +28,7 @@ use File::Temp qw/ tempdir tempfile /;\n use File::Spec::Functions qw(catfile);\n use Error qw(:try);\n use Git;\n+use Git::I18N;\n \n Getopt::Long::Configure qw/ pass_through /;\n \n@@ -797,12 +798,12 @@ foreach my $f (@files) {\n }\n \n if (!defined $auto_8bit_encoding && scalar %broken_encoding) {\n-\tprint \"The following files are 8bit, but do not declare \" .\n-\t\t\"a Content-Transfer-Encoding.\\n\";\n+\tprint __(\"The following files are 8bit, but do not declare \" .\n+\t\t \"a Content-Transfer-Encoding.\\n\");\n \tforeach my $f (sort keys %broken_encoding) {\n \t\tprint \"    $f\\n\";\n \t}\n-\t$auto_8bit_encoding = ask(\"Which 8bit encoding should I declare [UTF-8]? \",\n+\t$auto_8bit_encoding = ask(__(\"Which 8bit encoding should I declare [UTF-8]? \"),\n \t\t\t\t  valid_re => qr/.{4}/, confirm_only => 1,\n \t\t\t\t  default => \"UTF-8\");\n }\n@@ -829,7 +830,7 @@ if (defined $sender) {\n # But it's a no-op to run sanitize_address on an already sanitized address.\n $sender = sanitize_address($sender);\n \n-my $to_whom = \"To whom should the emails be sent (if anyone)?\";\n+my $to_whom = __(\"To whom should the emails be sent (if anyone)?\");\n my $prompting = 0;\n if (!@initial_to && !defined $to_cmd) {\n \tmy $to = ask(\"$to_whom \",\n@@ -859,7 +860,7 @@ sub expand_one_alias {\n \n if ($thread && !defined $initial_reply_to && $prompting) {\n \t$initial_reply_to = ask(\n-\t\t\"Message-ID to be used as In-Reply-To for the first email (if any)? \",\n+\t\t__(\"Message-ID to be used as In-Reply-To for the first email (if any)? \"),\n \t\tdefault => \"\",\n \t\tvalid_re => qr/\\@.*\\./, confirm_only => 1);\n }\n@@ -918,7 +919,10 @@ sub validate_address {\n \tmy $address = shift;\n \twhile (!extract_valid_address($address)) {\n \t\tprint STDERR \"error: unable to extract a valid address from: $address\\n\";\n-\t\t$_ = ask(\"What to do with this address? ([q]uit|[d]rop|[e]dit): \",\n+\t\t# TRANSLATORS: Make sure to include [q] [d] [e] in your\n+\t\t# translation. The program will only accept English input\n+\t\t# at this point.\n+\t\t$_ = ask(__(\"What to do with this address? ([q]uit|[d]rop|[e]dit): \"),\n \t\t\tvalid_re => qr/^(?:quit|q|drop|d|edit|e)/i,\n \t\t\tdefault => 'q');\n \t\tif (/^d/i) {\n@@ -1293,17 +1297,21 @@ Message-Id: $message_id\n \t\tif ($needs_confirm eq \"inform\") {\n \t\t\t$confirm_unconfigured = 0; # squelch this message for the rest of this run\n \t\t\t$ask_default = \"y\"; # assume yes on EOF since user hasn't explicitly asked for confirmation\n-\t\t\tprint \"    The Cc list above has been expanded by additional\\n\";\n-\t\t\tprint \"    addresses found in the patch commit message. By default\\n\";\n-\t\t\tprint \"    send-email prompts before sending whenever this occurs.\\n\";\n-\t\t\tprint \"    This behavior is controlled by the sendemail.confirm\\n\";\n-\t\t\tprint \"    configuration setting.\\n\";\n-\t\t\tprint \"\\n\";\n-\t\t\tprint \"    For additional information, run 'git send-email --help'.\\n\";\n-\t\t\tprint \"    To retain the current behavior, but squelch this message,\\n\";\n-\t\t\tprint \"    run 'git config --global sendemail.confirm auto'.\\n\\n\";\n+\t\t\tprint __(\n+\"    The Cc list above has been expanded by additional\n+    addresses found in the patch commit message. By default\n+    send-email prompts before sending whenever this occurs.\n+    This behavior is controlled by the sendemail.confirm\n+    configuration setting.\n+\n+    For additional information, run 'git send-email --help'.\n+    To retain the current behavior, but squelch this message,\n+    run 'git config --global sendemail.confirm auto'.\"), \"\\n\\n\";\n \t\t}\n-\t\t$_ = ask(\"Send this email? ([y]es|[n]o|[q]uit|[a]ll): \",\n+\t\t# TRANSLATORS: Make sure to include [y] [n] [q] [a] in your\n+\t\t# translation. The program will only accept English input\n+\t\t# at this point.\n+\t\t$_ = ask(__(\"Send this email? ([y]es|[n]o|[q]uit|[a]ll): \"),\n \t\t         valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,\n \t\t         default => $ask_default);\n \t\tdie \"Send this email reply required\" unless defined $_;\n@@ -1405,7 +1413,7 @@ Message-Id: $message_id\n \tif ($quiet) {\n \t\tprintf (($dry_run ? \"Dry-\" : \"\").\"Sent %s\\n\", $subject);\n \t} else {\n-\t\tprint (($dry_run ? \"Dry-\" : \"\").\"OK. Log says:\\n\");\n+\t\tprint($dry_run ? __(\"Dry-OK. Log says:\\n\") : __(\"OK. Log says:\\n\"));\n \t\tif (!file_name_is_absolute($smtp_server)) {\n \t\t\tprint \"Server: $smtp_server\\n\";\n \t\t\tprint \"MAIL FROM:<$raw_from>\\n\";\n@@ -1480,13 +1488,13 @@ foreach my $t (@files) {\n \t\t\t\t$sauthor = sanitize_address($author);\n \t\t\t\tnext if $suppress_cc{'author'};\n \t\t\t\tnext if $suppress_cc{'self'} and $sauthor eq $sender;\n-\t\t\t\tprintf(\"(mbox) Adding cc: %s from line '%s'\\n\",\n+\t\t\t\tprintf(__(\"(mbox) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t\t$1, $_) unless $quiet;\n \t\t\t\tpush @cc, $1;\n \t\t\t}\n \t\t\telsif (/^To:\\s+(.*)$/i) {\n \t\t\t\tforeach my $addr (parse_address_line($1)) {\n-\t\t\t\t\tprintf(\"(mbox) Adding to: %s from line '%s'\\n\",\n+\t\t\t\t\tprintf(__(\"(mbox) Adding to: %s from line '%s'\\n\"),\n \t\t\t\t\t\t$addr, $_) unless $quiet;\n \t\t\t\t\tpush @to, $addr;\n \t\t\t\t}\n@@ -1500,7 +1508,7 @@ foreach my $t (@files) {\n \t\t\t\t\t} else {\n \t\t\t\t\t\tnext if ($suppress_cc{'cc'});\n \t\t\t\t\t}\n-\t\t\t\t\tprintf(\"(mbox) Adding cc: %s from line '%s'\\n\",\n+\t\t\t\t\tprintf(__(\"(mbox) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t\t\t$addr, $_) unless $quiet;\n \t\t\t\t\tpush @cc, $addr;\n \t\t\t\t}\n@@ -1534,7 +1542,7 @@ foreach my $t (@files) {\n \t\t\t# So let's support that, too.\n \t\t\t$input_format = 'lots';\n \t\t\tif (@cc == 0 && !$suppress_cc{'cc'}) {\n-\t\t\t\tprintf(\"(non-mbox) Adding cc: %s from line '%s'\\n\",\n+\t\t\t\tprintf(__(\"(non-mbox) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t\t$_, $_) unless $quiet;\n \t\t\t\tpush @cc, $_;\n \t\t\t} elsif (!defined $subject) {\n@@ -1557,7 +1565,7 @@ foreach my $t (@files) {\n \t\t\t\tnext if $suppress_cc{'bodycc'} and $what =~ /Cc/i;\n \t\t\t}\n \t\t\tpush @cc, $c;\n-\t\t\tprintf(\"(body) Adding cc: %s from line '%s'\\n\",\n+\t\t\tprintf(__(\"(body) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t$c, $_) unless $quiet;\n \t\t}\n \t}\n-- \n2.7.4\n\n"},{"id":"303407","messageId":"20161005172110.30801-13-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 12/14] i18n: send-email: mark warnings and errors for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:21:08Z","receivedAt":"2016-10-05T17:22:39Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark warnings, errors and other messages for translation.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-send-email.perl | 34 +++++++++++++++++-----------------\n 1 file changed, 17 insertions(+), 17 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 78eb59b..982c6c0 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -118,20 +118,20 @@ sub format_2822_time {\n \tmy $localmin = $localtm[1] + $localtm[2] * 60;\n \tmy $gmtmin = $gmttm[1] + $gmttm[2] * 60;\n \tif ($localtm[0] != $gmttm[0]) {\n-\t\tdie \"local zone differs from GMT by a non-minute interval\\n\";\n+\t\tdie __(\"local zone differs from GMT by a non-minute interval\\n\");\n \t}\n \tif ((($gmttm[6] + 1) % 7) == $localtm[6]) {\n \t\t$localmin += 1440;\n \t} elsif ((($gmttm[6] - 1) % 7) == $localtm[6]) {\n \t\t$localmin -= 1440;\n \t} elsif ($gmttm[6] != $localtm[6]) {\n-\t\tdie \"local time offset greater than or equal to 24 hours\\n\";\n+\t\tdie __(\"local time offset greater than or equal to 24 hours\\n\");\n \t}\n \tmy $offset = $localmin - $gmtmin;\n \tmy $offhour = $offset / 60;\n \tmy $offmin = abs($offset % 60);\n \tif (abs($offhour) >= 24) {\n-\t\tdie (\"local time offset greater than or equal to 24 hours\\n\");\n+\t\tdie __(\"local time offset greater than or equal to 24 hours\\n\");\n \t}\n \n \treturn sprintf(\"%s, %2d %s %d %02d:%02d:%02d %s%02d%02d\",\n@@ -199,13 +199,13 @@ sub do_edit {\n \t\tmap {\n \t\t\tsystem('sh', '-c', $editor.' \"$@\"', $editor, $_);\n \t\t\tif (($? & 127) || ($? >> 8)) {\n-\t\t\t\tdie(\"the editor exited uncleanly, aborting everything\");\n+\t\t\t\tdie(__(\"the editor exited uncleanly, aborting everything\"));\n \t\t\t}\n \t\t} @_;\n \t} else {\n \t\tsystem('sh', '-c', $editor.' \"$@\"', $editor, @_);\n \t\tif (($? & 127) || ($? >> 8)) {\n-\t\t\tdie(\"the editor exited uncleanly, aborting everything\");\n+\t\t\tdie(__(\"the editor exited uncleanly, aborting everything\"));\n \t\t}\n \t}\n }\n@@ -299,7 +299,7 @@ my $help;\n my $rc = GetOptions(\"h\" => \\$help,\n                     \"dump-aliases\" => \\$dump_aliases);\n usage() unless $rc;\n-die \"--dump-aliases incompatible with other options\\n\"\n+die __(\"--dump-aliases incompatible with other options\\n\")\n     if !$help and $dump_aliases and @ARGV;\n $rc = GetOptions(\n \t\t    \"sender|from=s\" => \\$sender,\n@@ -362,7 +362,7 @@ unless ($rc) {\n     usage();\n }\n \n-die \"Cannot run git format-patch from outside a repository\\n\"\n+die __(\"Cannot run git format-patch from outside a repository\\n\")\n \tif $format_patch and not $repo;\n \n # Now, let's fill any that aren't set in with defaults:\n@@ -617,7 +617,7 @@ while (defined(my $f = shift @ARGV)) {\n }\n \n if (@rev_list_opts) {\n-\tdie \"Cannot run git format-patch from outside a repository\\n\"\n+\tdie __(\"Cannot run git format-patch from outside a repository\\n\")\n \t\tunless $repo;\n \tpush @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);\n }\n@@ -638,7 +638,7 @@ if (@files) {\n \t\tprint $_,\"\\n\" for (@files);\n \t}\n } else {\n-\tprint STDERR \"\\nNo patch files specified!\\n\\n\";\n+\tprint STDERR __(\"\\nNo patch files specified!\\n\\n\");\n \tusage();\n }\n \n@@ -730,7 +730,7 @@ EOT\n \t\t\t$sender = $1;\n \t\t\tnext;\n \t\t} elsif (/^(?:To|Cc|Bcc):/i) {\n-\t\t\tprint \"To/Cc/Bcc fields are not interpreted yet, they have been ignored\\n\";\n+\t\t\tprint __(\"To/Cc/Bcc fields are not interpreted yet, they have been ignored\\n\");\n \t\t\tnext;\n \t\t}\n \t\tprint $c2 $_;\n@@ -739,7 +739,7 @@ EOT\n \tclose $c2;\n \n \tif ($summary_empty) {\n-\t\tprint \"Summary email is empty, skipping it\\n\";\n+\t\tprint __(\"Summary email is empty, skipping it\\n\");\n \t\t$compose = -1;\n \t}\n } elsif ($annotate) {\n@@ -1314,7 +1314,7 @@ Message-Id: $message_id\n \t\t$_ = ask(__(\"Send this email? ([y]es|[n]o|[q]uit|[a]ll): \"),\n \t\t         valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,\n \t\t         default => $ask_default);\n-\t\tdie \"Send this email reply required\" unless defined $_;\n+\t\tdie __(\"Send this email reply required\") unless defined $_;\n \t\tif (/^n/i) {\n \t\t\treturn 0;\n \t\t} elsif (/^q/i) {\n@@ -1340,7 +1340,7 @@ Message-Id: $message_id\n \t} else {\n \n \t\tif (!defined $smtp_server) {\n-\t\t\tdie \"The required SMTP server is not properly defined.\"\n+\t\t\tdie __(\"The required SMTP server is not properly defined.\")\n \t\t}\n \n \t\tif ($smtp_encryption eq 'ssl') {\n@@ -1425,10 +1425,10 @@ Message-Id: $message_id\n \t\t}\n \t\tprint $header, \"\\n\";\n \t\tif ($smtp) {\n-\t\t\tprint \"Result: \", $smtp->code, ' ',\n+\t\t\tprint __(\"Result: \"), $smtp->code, ' ',\n \t\t\t\t($smtp->message =~ /\\n([^\\n]+\\n)$/s), \"\\n\";\n \t\t} else {\n-\t\t\tprint \"Result: OK\\n\";\n+\t\t\tprint __(\"Result: OK\\n\");\n \t\t}\n \t}\n \n@@ -1701,7 +1701,7 @@ sub apply_transfer_encoding {\n \t$message = MIME::Base64::decode($message)\n \t\tif ($from eq 'base64');\n \n-\tdie \"cannot send message as 7bit\"\n+\tdie __(\"cannot send message as 7bit\")\n \t\tif ($to eq '7bit' and $message =~ /[^[:ascii:]]/);\n \treturn $message\n \t\tif ($to eq '7bit' or $to eq '8bit');\n@@ -1709,7 +1709,7 @@ sub apply_transfer_encoding {\n \t\tif ($to eq 'quoted-printable');\n \treturn MIME::Base64::encode($message, \"\\n\")\n \t\tif ($to eq 'base64');\n-\tdie \"invalid transfer encoding\";\n+\tdie __(\"invalid transfer encoding\");\n }\n \n sub unique_email_list {\n-- \n2.7.4\n\n"},{"id":"303408","messageId":"20161005172110.30801-14-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 13/14] i18n: send-email: mark string with interpolation for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:21:09Z","receivedAt":"2016-10-05T17:22:45Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark warnings, errors and other messages that are interpolated for\ntranslation.\n\nWe call sprintf() before calling die() and in few other circumstances in\norder to replace the values on the placeholders.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n\nI changed (y|N) to [y|N] around line 1750 to match with the others\nquestions style.\n\n git-send-email.perl | 90 ++++++++++++++++++++++++++++-------------------------\n 1 file changed, 48 insertions(+), 42 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 982c6c0..5c01425 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -279,10 +279,13 @@ sub signal_handler {\n \t# tmp files from --compose\n \tif (defined $compose_filename) {\n \t\tif (-e $compose_filename) {\n-\t\t\tprint \"'$compose_filename' contains an intermediate version of the email you were composing.\\n\";\n+\t\t\tprintf __(\"'%s' contains an intermediate version \".\n+\t\t\t\t  \"of the email you were composing.\\n\"),\n+\t\t\t\t  $compose_filename;\n \t\t}\n \t\tif (-e ($compose_filename . \".final\")) {\n-\t\t\tprint \"'$compose_filename.final' contains the composed email.\\n\"\n+\t\t\tprintf __(\"'%s.final' contains the composed email.\\n\"),\n+\t\t\t\t  $compose_filename;\n \t\t}\n \t}\n \n@@ -431,7 +434,7 @@ $smtp_encryption = '' unless (defined $smtp_encryption);\n my(%suppress_cc);\n if (@suppress_cc) {\n \tforeach my $entry (@suppress_cc) {\n-\t\tdie \"Unknown --suppress-cc field: '$entry'\\n\"\n+\t\tdie sprintf(__(\"Unknown --suppress-cc field: '%s'\\n\"), $entry)\n \t\t\tunless $entry =~ /^(?:all|cccmd|cc|author|self|sob|body|bodycc)$/;\n \t\t$suppress_cc{$entry} = 1;\n \t}\n@@ -460,7 +463,7 @@ my $confirm_unconfigured = !defined $confirm;\n if ($confirm_unconfigured) {\n \t$confirm = scalar %suppress_cc ? 'compose' : 'auto';\n };\n-die \"Unknown --confirm setting: '$confirm'\\n\"\n+die sprintf(__(\"Unknown --confirm setting: '%s'\\n\"), $confirm)\n \tunless $confirm =~ /^(?:auto|cc|compose|always|never)/;\n \n # Debugging, print out the suppressions.\n@@ -492,16 +495,16 @@ my %aliases;\n sub parse_sendmail_alias {\n \tlocal $_ = shift;\n \tif (/\"/) {\n-\t\tprint STDERR \"warning: sendmail alias with quotes is not supported: $_\\n\";\n+\t\tprintf STDERR __(\"warning: sendmail alias with quotes is not supported: %s\\n\"), $_;\n \t} elsif (/:include:/) {\n-\t\tprint STDERR \"warning: `:include:` not supported: $_\\n\";\n+\t\tprintf STDERR __(\"warning: `:include:` not supported: %s\\n\"), $_;\n \t} elsif (/[\\/|]/) {\n-\t\tprint STDERR \"warning: `/file` or `|pipe` redirection not supported: $_\\n\";\n+\t\tprintf STDERR __(\"warning: `/file` or `|pipe` redirection not supported: %s\\n\"), $_;\n \t} elsif (/^(\\S+?)\\s*:\\s*(.+)$/) {\n \t\tmy ($alias, $addr) = ($1, $2);\n \t\t$aliases{$alias} = [ split_addrs($addr) ];\n \t} else {\n-\t\tprint STDERR \"warning: sendmail line is not recognized: $_\\n\";\n+\t\tprintf STDERR __(\"warning: sendmail line is not recognized: %s\\n\"), $_;\n \t}\n }\n \n@@ -582,13 +585,12 @@ sub is_format_patch_arg {\n \t\tif (defined($format_patch)) {\n \t\t\treturn $format_patch;\n \t\t}\n-\t\tdie(<<EOF);\n-File '$f' exists but it could also be the range of commits\n+\t\tdie sprintf(__(\n+\"File '%s' exists but it could also be the range of commits\n to produce patches for.  Please disambiguate by...\n \n-    * Saying \"./$f\" if you mean a file; or\n-    * Giving --format-patch option if you mean a range.\n-EOF\n+    * Saying \\\"./%s\\\" if you mean a file; or\n+    * Giving --format-patch option if you mean a range.\"), $f, $f);\n \t} catch Git::Error::Command with {\n \t\t# Not a valid revision.  Treat it as a filename.\n \t\treturn 0;\n@@ -604,7 +606,7 @@ while (defined(my $f = shift @ARGV)) {\n \t\t@ARGV = ();\n \t} elsif (-d $f and !is_format_patch_arg($f)) {\n \t\topendir my $dh, $f\n-\t\t\tor die \"Failed to opendir $f: $!\";\n+\t\t\tor die sprintf(__(\"Failed to opendir %s: %s\"), $f, $!);\n \n \t\tpush @files, grep { -f $_ } map { catfile($f, $_) }\n \t\t\t\tsort readdir $dh;\n@@ -628,7 +630,8 @@ if ($validate) {\n \tforeach my $f (@files) {\n \t\tunless (-p $f) {\n \t\t\tmy $error = validate_patch($f);\n-\t\t\t$error and die \"fatal: $f: $error\\nwarning: no patches were sent\\n\";\n+\t\t\t$error and die sprintf(__(\"fatal: %s: %s\\nwarning: no patches were sent\\n\"),\n+\t\t\t\t\t\t  $f, $error);\n \t\t}\n \t}\n }\n@@ -651,7 +654,7 @@ sub get_patch_subject {\n \t\treturn \"GIT: $1\\n\";\n \t}\n \tclose $fh;\n-\tdie \"No subject line in $fn ?\";\n+\tdie sprintf(__(\"No subject line in %s ?\"), $fn);\n }\n \n if ($compose) {\n@@ -661,7 +664,7 @@ if ($compose) {\n \t\ttempfile(\".gitsendemail.msg.XXXXXX\", DIR => $repo->repo_path()) :\n \t\ttempfile(\".gitsendemail.msg.XXXXXX\", DIR => \".\"))[1];\n \topen my $c, \">\", $compose_filename\n-\t\tor die \"Failed to open for writing $compose_filename: $!\";\n+\t\tor die sprintf(__(\"Failed to open for writing %s: %s\"), $compose_filename, $!);\n \n \n \tmy $tpl_sender = $sender || $repoauthor || $repocommitter || '';\n@@ -692,10 +695,10 @@ EOT\n \t}\n \n \topen my $c2, \">\", $compose_filename . \".final\"\n-\t\tor die \"Failed to open $compose_filename.final : \" . $!;\n+\t\tor die sprintf(__(\"Failed to open %s.final : %s\"), $compose_filename, $!);\n \n \topen $c, \"<\", $compose_filename\n-\t\tor die \"Failed to open $compose_filename : \" . $!;\n+\t\tor die sprintf(__(\"Failed to open %s : %s\"), $compose_filename, $!);\n \n \tmy $need_8bit_cte = file_has_nonascii($compose_filename);\n \tmy $in_body = 0;\n@@ -769,7 +772,9 @@ sub ask {\n \t\t\treturn $resp;\n \t\t}\n \t\tif ($confirm_only) {\n-\t\t\tmy $yesno = $term->readline(\"Are you sure you want to use <$resp> [y/N]? \");\n+\t\t\tmy $yesno = $term->readline(\n+\t\t\t\t# TRANSLATORS: please keep [y/N] as is.\n+\t\t\t\tsprintf(__(\"Are you sure you want to use <%s> [y/N]? \"), $resp));\n \t\t\tif (defined $yesno && $yesno =~ /y/i) {\n \t\t\t\treturn $resp;\n \t\t\t}\n@@ -811,9 +816,9 @@ if (!defined $auto_8bit_encoding && scalar %broken_encoding) {\n if (!$force) {\n \tfor my $f (@files) {\n \t\tif (get_patch_subject($f) =~ /\\Q*** SUBJECT HERE ***\\E/) {\n-\t\t\tdie \"Refusing to send because the patch\\n\\t$f\\n\"\n+\t\t\tdie sprintf(__(\"Refusing to send because the patch\\n\\t%s\\n\"\n \t\t\t\t. \"has the template subject '*** SUBJECT HERE ***'. \"\n-\t\t\t\t. \"Pass --force if you really want to send.\\n\";\n+\t\t\t\t. \"Pass --force if you really want to send.\\n\"), $f);\n \t\t}\n \t}\n }\n@@ -848,7 +853,7 @@ my %EXPANDED_ALIASES;\n sub expand_one_alias {\n \tmy $alias = shift;\n \tif ($EXPANDED_ALIASES{$alias}) {\n-\t\tdie \"fatal: alias '$alias' expands to itself\\n\";\n+\t\tdie sprintf(__(\"fatal: alias '%s' expands to itself\\n\"), $alias);\n \t}\n \tlocal $EXPANDED_ALIASES{$alias} = 1;\n \treturn $aliases{$alias} ? expand_aliases(@{$aliases{$alias}}) : $alias;\n@@ -910,7 +915,7 @@ sub extract_valid_address {\n sub extract_valid_address_or_die {\n \tmy $address = shift;\n \t$address = extract_valid_address($address);\n-\tdie \"error: unable to extract a valid address from: $address\\n\"\n+\tdie sprintf(__(\"error: unable to extract a valid address from: %s\\n\"), $address)\n \t\tif !$address;\n \treturn $address;\n }\n@@ -918,7 +923,7 @@ sub extract_valid_address_or_die {\n sub validate_address {\n \tmy $address = shift;\n \twhile (!extract_valid_address($address)) {\n-\t\tprint STDERR \"error: unable to extract a valid address from: $address\\n\";\n+\t\tprintf STDERR __(\"error: unable to extract a valid address from: %s\\n\"), $address;\n \t\t# TRANSLATORS: Make sure to include [q] [d] [e] in your\n \t\t# translation. The program will only accept English input\n \t\t# at this point.\n@@ -1223,7 +1228,7 @@ sub ssl_verify_params {\n \t\treturn (SSL_verify_mode => SSL_VERIFY_PEER(),\n \t\t\tSSL_ca_file => $smtp_ssl_cert_path);\n \t} else {\n-\t\tdie \"CA path \\\"$smtp_ssl_cert_path\\\" does not exist\";\n+\t\tdie sprintf(__(\"CA path \\\"%s\\\" does not exist\"), $smtp_ssl_cert_path);\n \t}\n }\n \n@@ -1384,14 +1389,14 @@ Message-Id: $message_id\n \t\t\t\t\t# supported commands\n \t\t\t\t\t$smtp->hello($smtp_domain);\n \t\t\t\t} else {\n-\t\t\t\t\tdie \"Server does not support STARTTLS! \".$smtp->message;\n+\t\t\t\t\tdie sprintf(__(\"Server does not support STARTTLS! %s\"), $smtp->message);\n \t\t\t\t}\n \t\t\t}\n \t\t}\n \n \t\tif (!$smtp) {\n-\t\t\tdie \"Unable to initialize SMTP properly. Check config and use --smtp-debug. \",\n-\t\t\t    \"VALUES: server=$smtp_server \",\n+\t\t\tdie __(\"Unable to initialize SMTP properly. Check config and use --smtp-debug.\"),\n+\t\t\t    \" VALUES: server=$smtp_server \",\n \t\t\t    \"encryption=$smtp_encryption \",\n \t\t\t    \"hello=$smtp_domain\",\n \t\t\t    defined $smtp_server_port ? \" port=$smtp_server_port\" : \"\";\n@@ -1408,10 +1413,10 @@ Message-Id: $message_id\n \t\t\t$smtp->datasend(\"$line\") or die $smtp->message;\n \t\t}\n \t\t$smtp->dataend() or die $smtp->message;\n-\t\t$smtp->code =~ /250|200/ or die \"Failed to send $subject\\n\".$smtp->message;\n+\t\t$smtp->code =~ /250|200/ or die sprintf(__(\"Failed to send %s\\n\"), $subject).$smtp->message;\n \t}\n \tif ($quiet) {\n-\t\tprintf (($dry_run ? \"Dry-\" : \"\").\"Sent %s\\n\", $subject);\n+\t\tprintf($dry_run ? __(\"Dry-Sent %s\\n\") : __(\"Sent %s\\n\"), $subject);\n \t} else {\n \t\tprint($dry_run ? __(\"Dry-OK. Log says:\\n\") : __(\"OK. Log says:\\n\"));\n \t\tif (!file_name_is_absolute($smtp_server)) {\n@@ -1441,7 +1446,7 @@ $subject = $initial_subject;\n $message_num = 0;\n \n foreach my $t (@files) {\n-\topen my $fh, \"<\", $t or die \"can't open file $t\";\n+\topen my $fh, \"<\", $t or die sprintf(__(\"can't open file %s\"), $t);\n \n \tmy $author = undef;\n \tmy $sauthor = undef;\n@@ -1663,18 +1668,18 @@ sub recipients_cmd {\n \n \tmy @addresses = ();\n \topen my $fh, \"-|\", \"$cmd \\Q$file\\E\"\n-\t    or die \"($prefix) Could not execute '$cmd'\";\n+\t    or die sprintf(__(\"(%s) Could not execute '%s'\"), $prefix, $cmd);\n \twhile (my $address = <$fh>) {\n \t\t$address =~ s/^\\s*//g;\n \t\t$address =~ s/\\s*$//g;\n \t\t$address = sanitize_address($address);\n \t\tnext if ($address eq $sender and $suppress_cc{'self'});\n \t\tpush @addresses, $address;\n-\t\tprintf(\"($prefix) Adding %s: %s from: '%s'\\n\",\n-\t\t       $what, $address, $cmd) unless $quiet;\n+\t\tprintf(__(\"(%s) Adding %s: %s from: '%s'\\n\"),\n+\t\t       $prefix, $what, $address, $cmd) unless $quiet;\n \t\t}\n \tclose $fh\n-\t    or die \"($prefix) failed to close pipe to '$cmd'\";\n+\t    or die sprintf(__(\"(%s) failed to close pipe to '%s'\"), $prefix, $cmd);\n \treturn @addresses;\n }\n \n@@ -1728,10 +1733,10 @@ sub unique_email_list {\n sub validate_patch {\n \tmy $fn = shift;\n \topen(my $fh, '<', $fn)\n-\t\tor die \"unable to open $fn: $!\\n\";\n+\t\tor die sprintf(__(\"unable to open %s: %s\\n\"), $fn, $!);\n \twhile (my $line = <$fh>) {\n \t\tif (length($line) > 998) {\n-\t\t\treturn \"$.: patch contains a line longer than 998 characters\";\n+\t\t\treturn sprintf(__(\"%s: patch contains a line longer than 998 characters\"), $.);\n \t\t}\n \t}\n \treturn;\n@@ -1747,10 +1752,11 @@ sub handle_backup {\n \t    (substr($file, 0, $lastlen) eq $last) &&\n \t    ($suffix = substr($file, $lastlen)) !~ /^[a-z0-9]/i) {\n \t\tif (defined $known_suffix && $suffix eq $known_suffix) {\n-\t\t\tprint \"Skipping $file with backup suffix '$known_suffix'.\\n\";\n+\t\t\tprintf(__(\"Skipping %s with backup suffix '%s'.\\n\"), $file, $known_suffix);\n \t\t\t$skip = 1;\n \t\t} else {\n-\t\t\tmy $answer = ask(\"Do you really want to send $file? (y|N): \",\n+\t\t\t# TRANSLATORS: please keep \"[y|N]\" as is.\n+\t\t\tmy $answer = ask(sprintf(__(\"Do you really want to send %s? [y|N]: \"), $file),\n \t\t\t\t\t valid_re => qr/^(?:y|n)/i,\n \t\t\t\t\t default => 'n');\n \t\t\t$skip = ($answer ne 'y');\n@@ -1778,7 +1784,7 @@ sub handle_backup_files {\n sub file_has_nonascii {\n \tmy $fn = shift;\n \topen(my $fh, '<', $fn)\n-\t\tor die \"unable to open $fn: $!\\n\";\n+\t\tor die sprintf(__(\"unable to open %s: %s\\n\"), $fn, $!);\n \twhile (my $line = <$fh>) {\n \t\treturn 1 if $line =~ /[^[:ascii:]]/;\n \t}\n@@ -1788,7 +1794,7 @@ sub file_has_nonascii {\n sub body_or_subject_has_nonascii {\n \tmy $fn = shift;\n \topen(my $fh, '<', $fn)\n-\t\tor die \"unable to open $fn: $!\\n\";\n+\t\tor die sprintf(__(\"unable to open %s: %s\\n\"), $fn, $!);\n \twhile (my $line = <$fh>) {\n \t\tlast if $line =~ /^$/;\n \t\treturn 1 if $line =~ /^Subject.*[^[:ascii:]]/;\n-- \n2.7.4\n\n"},{"id":"303409","messageId":"20161005172110.30801-15-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v3 14/14] i18n: difftool: mark warnings for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-05T17:21:10Z","receivedAt":"2016-10-05T17:22:49Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-difftool.perl | 22 ++++++++++++----------\n 1 file changed, 12 insertions(+), 10 deletions(-)\n\ndiff --git a/git-difftool.perl b/git-difftool.perl\nindex a5790d0..8d3632e 100755\n--- a/git-difftool.perl\n+++ b/git-difftool.perl\n@@ -22,6 +22,7 @@ use File::Path qw(mkpath rmtree);\n use File::Temp qw(tempdir);\n use Getopt::Long qw(:config pass_through);\n use Git;\n+use Git::I18N;\n \n sub usage\n {\n@@ -122,7 +123,7 @@ sub setup_dir_diff\n \tmy $i = 0;\n \twhile ($i < $#rawdiff) {\n \t\tif ($rawdiff[$i] =~ /^::/) {\n-\t\t\twarn << 'EOF';\n+\t\t\twarn __ <<'EOF';\n Combined diff formats ('-c' and '--cc') are not supported in\n directory diff mode ('-d' and '--dir-diff').\n EOF\n@@ -338,7 +339,7 @@ sub main\n \t\tif (length($opts{difftool_cmd}) > 0) {\n \t\t\t$ENV{GIT_DIFF_TOOL} = $opts{difftool_cmd};\n \t\t} else {\n-\t\t\tprint \"No <tool> given for --tool=<tool>\\n\";\n+\t\t\tprint __(\"No <tool> given for --tool=<tool>\\n\");\n \t\t\tusage(1);\n \t\t}\n \t}\n@@ -346,7 +347,7 @@ sub main\n \t\tif (length($opts{extcmd}) > 0) {\n \t\t\t$ENV{GIT_DIFFTOOL_EXTCMD} = $opts{extcmd};\n \t\t} else {\n-\t\t\tprint \"No <cmd> given for --extcmd=<cmd>\\n\";\n+\t\t\tprint __(\"No <cmd> given for --extcmd=<cmd>\\n\");\n \t\t\tusage(1);\n \t\t}\n \t}\n@@ -419,11 +420,11 @@ sub dir_diff\n \t\t}\n \n \t\tif (exists $wt_modified{$file} and exists $tmp_modified{$file}) {\n-\t\t\tmy $errmsg = \"warning: Both files modified: \";\n-\t\t\t$errmsg .= \"'$workdir/$file' and '$b/$file'.\\n\";\n-\t\t\t$errmsg .= \"warning: Working tree file has been left.\\n\";\n-\t\t\t$errmsg .= \"warning:\\n\";\n-\t\t\twarn $errmsg;\n+\t\t\twarn sprintf(__(\n+\t\t\t\t\"warning: Both files modified:\\n\" .\n+\t\t\t\t\"'%s/%s' and '%s/%s'.\\n\" .\n+\t\t\t\t\"warning: Working tree file has been left.\\n\" .\n+\t\t\t\t\"warning:\\n\"), $workdir, $file, $b, $file);\n \t\t\t$error = 1;\n \t\t} elsif (exists $tmp_modified{$file}) {\n \t\t\tmy $mode = stat(\"$b/$file\")->mode;\n@@ -435,8 +436,9 @@ sub dir_diff\n \t\t}\n \t}\n \tif ($error) {\n-\t\twarn \"warning: Temporary files exist in '$tmpdir'.\\n\";\n-\t\twarn \"warning: You may want to cleanup or recover these.\\n\";\n+\t\twarn sprintf(__(\n+\t\t\t\"warning: Temporary files exist in '%s'.\\n\" .\n+\t\t\t\"warning: You may want to cleanup or recover these.\\n\"), $tmpdir);\n \t\texit(1);\n \t} else {\n \t\texit_cleanup($tmpdir, $rc);\n-- \n2.7.4\n\n"},{"id":"303448","messageId":"44a32c9e-55dd-e4ce-a5da-b16660edd587@gmail.com","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"Re: [PATCH v3 00/14] Mark strings in Perl scripts for translation","fromName":"Jakub Narębski","fromEmail":"jnareb@gmail.com","sentAt":"2016-10-05T21:50:34Z","receivedAt":"2016-10-05T21:50:58Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"W dniu 05.10.2016 o 19:20, Vasco Almeida pisze:\n> Mark messages in some perl scripts for translation.\n> \n> Thanks for the reviews of Junio Hamano and Jakub Narębski.  Although I think\n> Jakub Narębski's suggestions are overall good, I am not willing to go that path\n> because I cannot see huge benefits from them given what we already have and\n> also I lack Perl skills.\n\nAll right.  While I think that Locale::TextDomain-like interpolation\nin translated strings (__x, __xn / __nx, etc.), which is labelled as\n'perl-brace-format' by gettext, is more Perl-ish and better for unbiased\ntranslators, the printf based interpolation, labelled as ‘perl-format’\n(and identical to 'c-format', I think), may be preferred in this case.\n\nThe 'perl-brace-format' doesn't need TRANSLATOR comments to explain\nwhat placeholders are, and placeholders are easier to reorder.  On\nthe other hand translator needs to know to not translate contents\nof placeholders.\n\n  \"This is the {color} {thing}.\\n\"\n\nWith 'perl-format' / 'c-format' the translator might need to know\nhow to change order of placeholders, but he or she should know\nhow to do it translating strings from C code.\n\n  \"This is the %s %s.\\n\"\n\nAlso, if Perl code shares translation strings with C code, as in\nmost cases here, then printf format is needed to do translation\nonly once.\n\ntldr; I am reversing my opinion, and agree with your solution.\n\n> \n> Interdiff bellow.\n\nOne thing I have noticed in the interdiff is using *translated*\nstrings in hash content (translation takes time, and might not\nbe necessary), that is:\n\n   $hashref = {\n\tKEY => __('value'),\n   }\n\n   ... $hashref->{KEY} ...\n\ninstead of marking value for translation, and doing translation\nonly on print, when it is necessary\n\n   $hashref = {\n\tKEY => N__('value'),\n   }\n\n   ... __($hashref->{KEY}) ...\n\n> \n> Vasco Almeida (14):\n[...]\n\nI'll try to review those later.\n\nThank you for your work,\n-- \nJakub Narębski\n\n"},{"id":"303451","messageId":"xmqqshsamnve.fsf@gitster.mtv.corp.google.com","threadId":"44227","inReplyTo":"20161005172110.30801-4-vascomalmeida@sapo.pt","subject":"Re: [PATCH v3 03/14] i18n: add--interactive: mark strings with interpolation for translation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-05T22:28:53Z","receivedAt":"2016-10-05T22:29:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Vasco Almeida <vascomalmeida@sapo.pt> writes:\n\n>  \t\t\t\tif (!defined $bottom) {\n> -\t\t\t\t\terror_msg \"Huh ($choice)?\\n\";\n> +\t\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\\n\"), $choice);\n>  \t\t\t\t\tnext TOPLOOP;\n>  \t\t\t\t}\n>  \t\t\t}\n>  \t\t\tif ($opts->{SINGLETON} && $bottom != $top) {\n> -\t\t\t\terror_msg \"Huh ($choice)?\\n\";\n> +\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\"), $choice);\n>  \t\t\t\tnext TOPLOOP;\n\nDoesn't this want \"\\n\" just like the other one in this hunk?\n\n"},{"id":"303453","messageId":"xmqqoa2ymnb1.fsf@gitster.mtv.corp.google.com","threadId":"44227","inReplyTo":"20161005172110.30801-6-vascomalmeida@sapo.pt","subject":"Re: [PATCH v3 05/14] i18n: add--interactive: mark plural strings","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-05T22:41:06Z","receivedAt":"2016-10-05T22:41:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Vasco Almeida <vascomalmeida@sapo.pt> writes:\n\n> @@ -70,6 +72,8 @@ Git::I18N - Perl interface to Git's Gettext localizations\n>  \n>  \tprintf __(\"The following error occurred: %s\\n\"), $error;\n>  \n> +\tprintf __n(\"commited %d file\", \"commited %d files\", $files), $files;\n> +\n\nA micronit: the existing example above prints a whole line,\ni.e. terminated with a LF.  The new one probably should match.\n"},{"id":"303704","messageId":"20161010125449.7929-1-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 00/14] Mark strings in Perl scripts for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:35Z","receivedAt":"2016-10-10T12:55:42Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark messages in some perl scripts for translation.\n\nFix minor stuff and follow Jakub Narębski's suggestion to use N__() instead of\n__() in the hash tables.\n\nInterdiff included below.\n\nVasco Almeida (14):\n  i18n: add--interactive: mark strings for translation\n  i18n: add--interactive: mark simple here-documents for translation\n  i18n: add--interactive: mark strings with interpolation for\n    translation\n  i18n: clean.c: match string with git-add--interactive.perl\n  i18n: add--interactive: mark plural strings\n  i18n: add--interactive: mark patch prompt for translation\n  i18n: add--interactive: i18n of help_patch_cmd\n  i18n: add--interactive: mark edit_hunk_manually message for\n    translation\n  i18n: add--interactive: remove %patch_modes entries\n  i18n: add--interactive: mark status words for translation\n  i18n: send-email: mark strings for translation\n  i18n: send-email: mark warnings and errors for translation\n  i18n: send-email: mark string with interpolation for translation\n  i18n: difftool: mark warnings for translation\n\n Makefile                  |   3 +-\n builtin/clean.c           |  10 +-\n git-add--interactive.perl | 322 ++++++++++++++++++++++++++++++----------------\n git-difftool.perl         |  22 ++--\n git-send-email.perl       | 176 +++++++++++++------------\n perl/Git/I18N.pm          |  17 ++-\n t/t0202/test.pl           |  14 +-\n 7 files changed, 353 insertions(+), 211 deletions(-)\n\n\ndiff --git a/Makefile b/Makefile\nindex 4ef0344..9dc95cb 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -2112,7 +2112,7 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \\\n XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \\\n \t--keyword=gettextln --keyword=eval_gettextln\n XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \\\n-\t--keyword=__ --keyword=\"__n:1,2\"\n+\t--keyword=__ --keyword=N__ --keyword=\"__n:1,2\"\n LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)\n LOCALIZED_SH = $(SCRIPT_SH)\n LOCALIZED_SH += git-parse-remote.sh\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 0b4a27c..4754104 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -601,7 +601,7 @@ sub list_and_choose {\n \t\t\t\t}\n \t\t\t}\n \t\t\tif ($opts->{SINGLETON} && $bottom != $top) {\n-\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\"), $choice);\n+\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\\n\"), $choice);\n \t\t\t\tnext TOPLOOP;\n \t\t\t}\n \t\t\tfor ($i = $bottom-1; $i <= $top-1; $i++) {\n@@ -704,7 +704,7 @@ sub revert_cmd {\n \t\t\t\t    $_->{INDEX_ADDDEL} eq 'create') {\n \t\t\t\t\tsystem(qw(git update-index --force-remove --),\n \t\t\t\t\t       $_->{VALUE});\n-\t\t\t\t\tprint \"note: $_->{VALUE} is untracked now.\\n\";\n+\t\t\t\t\tprintf(__(\"note: %s is untracked now.\\n\"), $_->{VALUE});\n \t\t\t\t}\n \t\t\t}\n \t\t}\n@@ -1038,25 +1038,25 @@ sub color_diff {\n }\n \n my %edit_hunk_manually_modes = (\n-\tstage => __(\n+\tstage => N__(\n \"# If the patch applies cleanly, the edited hunk will immediately be\n # marked for staging.\"),\n-\tstash => __(\n+\tstash => N__(\n \"# If the patch applies cleanly, the edited hunk will immediately be\n # marked for stashing.\"),\n-\treset_head => __(\n+\treset_head => N__(\n \"# If the patch applies cleanly, the edited hunk will immediately be\n # marked for unstaging.\"),\n-\treset_nothead => __(\n+\treset_nothead => N__(\n \"# If the patch applies cleanly, the edited hunk will immediately be\n # marked for applying.\"),\n-\tcheckout_index => __(\n+\tcheckout_index => N__(\n \"# If the patch applies cleanly, the edited hunk will immediately be\n # marked for discarding\"),\n-\tcheckout_head => __(\n+\tcheckout_head => N__(\n \"# If the patch applies cleanly, the edited hunk will immediately be\n # marked for discarding.\"),\n-\tcheckout_nothead => __(\n+\tcheckout_nothead => N__(\n \"# If the patch applies cleanly, the edited hunk will immediately be\n # marked for applying.\"),\n );\n@@ -1078,7 +1078,7 @@ sub edit_hunk_manually {\n # To remove '%s' lines, delete them.\n # Lines starting with # will be removed.\n #\\n\"), $remove_minus, $remove_plus),\n-$edit_hunk_manually_modes{$patch_mode}, __(\n+__($edit_hunk_manually_modes{$patch_mode}), __(\n # TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.\n \" If it does not apply cleanly, you will be given\n # an opportunity to edit again. If all lines of the hunk are removed,\n@@ -1192,43 +1192,43 @@ sub edit_hunk_loop {\n }\n \n my %help_patch_modes = (\n-\tstage => __(\n+\tstage => N__(\n \"y - stage this hunk\n n - do not stage this hunk\n q - quit; do not stage this hunk or any of the remaining ones\n a - stage this hunk and all later hunks in the file\n d - do not stage this hunk or any of the later hunks in the file\"),\n-\tstash => __(\n+\tstash => N__(\n \"y - stash this hunk\n n - do not stash this hunk\n q - quit; do not stash this hunk or any of the remaining ones\n a - stash this hunk and all later hunks in the file\n d - do not stash this hunk or any of the later hunks in the file\"),\n-\treset_head => __(\n+\treset_head => N__(\n \"y - unstage this hunk\n n - do not unstage this hunk\n q - quit; do not unstage this hunk or any of the remaining ones\n a - unstage this hunk and all later hunks in the file\n d - do not unstage this hunk or any of the later hunks in the file\"),\n-\treset_nothead => __(\n+\treset_nothead => N__(\n \"y - apply this hunk to index\n n - do not apply this hunk to index\n q - quit; do not apply this hunk or any of the remaining ones\n a - apply this hunk and all later hunks in the file\n d - do not apply this hunk or any of the later hunks in the file\"),\n-\tcheckout_index => __(\n+\tcheckout_index => N__(\n \"y - discard this hunk from worktree\n n - do not discard this hunk from worktree\n q - quit; do not discard this hunk or any of the remaining ones\n a - discard this hunk and all later hunks in the file\n d - do not discard this hunk or any of the later hunks in the file\"),\n-\tcheckout_head => __(\n+\tcheckout_head => N__(\n \"y - discard this hunk from index and worktree\n n - do not discard this hunk from index and worktree\n q - quit; do not discard this hunk or any of the remaining ones\n a - discard this hunk and all later hunks in the file\n d - do not discard this hunk or any of the later hunks in the file\"),\n-\tcheckout_nothead => __(\n+\tcheckout_nothead => N__(\n \"y - apply this hunk to index and worktree\n n - do not apply this hunk to index and worktree\n q - quit; do not apply this hunk or any of the remaining ones\n@@ -1237,7 +1237,7 @@ d - do not apply this hunk or any of the later hunks in the file\"),\n );\n \n sub help_patch_cmd {\n-\tprint colored $help_color, $help_patch_modes{$patch_mode}, \"\\n\", __ <<EOF ;\n+\tprint colored $help_color, __($help_patch_modes{$patch_mode}), \"\\n\", __ <<EOF ;\n g - select a hunk to go to\n / - search for a hunk matching the given regex\n j - leave this hunk undecided, see next undecided hunk\n@@ -1303,7 +1303,7 @@ sub patch_update_cmd {\n \t\t@them = @mods;\n \t}\n \telse {\n-\t\t@them = list_and_choose({ PROMPT => 'Patch update',\n+\t\t@them = list_and_choose({ PROMPT => __('Patch update'),\n \t\t\t\t\t  HEADER => $status_head, },\n \t\t\t\t\t@mods);\n \t}\n@@ -1355,39 +1355,39 @@ sub display_hunks {\n \n my %patch_update_prompt_modes = (\n \tstage => {\n-\t\tmode => __(\"Stage mode change [y,n,q,a,d,/%s,?]? \"),\n-\t\tdeletion => __(\"Stage deletion [y,n,q,a,d,/%s,?]? \"),\n-\t\thunk => __(\"Stage this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t\tmode => N__(\"Stage mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Stage deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Stage this hunk [y,n,q,a,d,/%s,?]? \"),\n \t},\n \tstash => {\n-\t\tmode => __(\"Stash mode change [y,n,q,a,d,/%s,?]? \"),\n-\t\tdeletion => __(\"Stash deletion [y,n,q,a,d,/%s,?]? \"),\n-\t\thunk => __(\"Stash this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t\tmode => N__(\"Stash mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Stash deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Stash this hunk [y,n,q,a,d,/%s,?]? \"),\n \t},\n \treset_head => {\n-\t\tmode => __(\"Unstage mode change [y,n,q,a,d,/%s,?]? \"),\n-\t\tdeletion => __(\"Unstage deletion [y,n,q,a,d,/%s,?]? \"),\n-\t\thunk => __(\"Unstage this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t\tmode => N__(\"Unstage mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Unstage deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Unstage this hunk [y,n,q,a,d,/%s,?]? \"),\n \t},\n \treset_nothead => {\n-\t\tmode => __(\"Apply mode change to index [y,n,q,a,d,/%s,?]? \"),\n-\t\tdeletion => __(\"Apply deletion to index [y,n,q,a,d,/%s,?]? \"),\n-\t\thunk => __(\"Apply this hunk to index [y,n,q,a,d,/%s,?]? \"),\n+\t\tmode => N__(\"Apply mode change to index [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Apply deletion to index [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Apply this hunk to index [y,n,q,a,d,/%s,?]? \"),\n \t},\n \tcheckout_index => {\n-\t\tmode => __(\"Discard mode change from worktree [y,n,q,a,d,/%s,?]? \"),\n-\t\tdeletion => __(\"Discard deletion from worktree [y,n,q,a,d,/%s,?]? \"),\n-\t\thunk => __(\"Discard this hunk from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tmode => N__(\"Discard mode change from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Discard deletion from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Discard this hunk from worktree [y,n,q,a,d,/%s,?]? \"),\n \t},\n \tcheckout_head => {\n-\t\tmode => __(\"Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? \"),\n-\t\tdeletion => __(\"Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? \"),\n-\t\thunk => __(\"Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tmode => N__(\"Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? \"),\n \t},\n \tcheckout_nothead => {\n-\t\tmode => __(\"Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? \"),\n-\t\tdeletion => __(\"Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? \"),\n-\t\thunk => __(\"Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tmode => N__(\"Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? \"),\n \t},\n );\n \n@@ -1464,7 +1464,7 @@ sub patch_update_file {\n \t\t\tprint;\n \t\t}\n \t\tprint colored $prompt_color,\n-\t\t\tsprintf($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}, $other);\n+\t\t\tsprintf(__($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}), $other);\n \n \t\tmy $line = prompt_single_character;\n \t\tlast unless defined $line;\ndiff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm\nindex 3f7ac25..32c4568 100644\n--- a/perl/Git/I18N.pm\n+++ b/perl/Git/I18N.pm\n@@ -13,7 +13,7 @@ BEGIN {\n \t}\n }\n \n-our @EXPORT = qw(__ __n);\n+our @EXPORT = qw(__ __n N__);\n our @EXPORT_OK = @EXPORT;\n \n sub __bootstrap_locale_messages {\n@@ -54,6 +54,8 @@ BEGIN\n \t\t*__ = sub ($) { $_[0] };\n \t\t*__n = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };\n \t};\n+\n+\tsub N__($) { return shift; }\n }\n \n 1;\n@@ -74,6 +76,7 @@ Git::I18N - Perl interface to Git's Gettext localizations\n \n \tprintf __n(\"commited %d file\", \"commited %d files\", $files), $files;\n \n+\n =head1 DESCRIPTION\n \n Git's internal Perl interface to gettext via L<Locale::Messages>. If\n@@ -94,6 +97,11 @@ passthrough fallback function.\n =head2 __n($$$)\n L<Locale::Messages>'s ngettext function or passthrough fallback function.\n \n+=head2 N__($)\n+No-op that only returns its argument. Use this if you want xgettext to\n+extract the text to the pot template but do not want to trigger retrival of\n+the translation at run time.\n+\n =head1 AUTHOR\n \n E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>\ndiff --git a/t/t0202/test.pl b/t/t0202/test.pl\nindex 4101833..2cbf7b9 100755\n--- a/t/t0202/test.pl\n+++ b/t/t0202/test.pl\n@@ -4,7 +4,7 @@ use lib (split(/:/, $ENV{GITPERLLIB}));\n use strict;\n use warnings;\n use POSIX qw(:locale_h);\n-use Test::More tests => 11;\n+use Test::More tests => 13;\n use Git::I18N;\n \n my $has_gettext_library = $Git::I18N::__HAS_LIBRARY;\n@@ -32,6 +32,7 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \tmy %prototypes = (qw(\n \t\t__\t$\n \t\t__n\t$$$\n+\t\tN__\t$\n \t));\n \twhile (my ($sub, $proto) = each %prototypes) {\n \t\tis(prototype(\\&{\"Git::I18N::$sub\"}), $proto, \"sanity: $sub has a $proto prototype\");\n@@ -55,6 +56,8 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \t\t\"Get singular string through __n() in C locale\");\n \tis(__n($got_singular, $got_plural, 2), $expect_plural,\n \t\t\"Get plural string through __n() in C locale\");\n+\n+\tis(N__($got), $expect, \"Passing a string through N__() in the C locale works\");\n }\n \n # Test a basic message on different locales\n-- \n2.7.4\n\n"},{"id":"303705","messageId":"20161010125449.7929-2-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 01/14] i18n: add--interactive: mark strings for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:36Z","receivedAt":"2016-10-10T12:55:49Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark simple strings (without interpolation) for translation.\n\nBrackets around first parameter of ternary operator is necessary because\notherwise xgettext fails to extract strings marked for translation from\nthe rest of the file.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 76 ++++++++++++++++++++++++++---------------------\n 1 file changed, 42 insertions(+), 34 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex ee3d812..cf216ec 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -4,6 +4,7 @@ use 5.008;\n use strict;\n use warnings;\n use Git;\n+use Git::I18N;\n \n binmode(STDOUT, \":raw\");\n \n@@ -253,8 +254,9 @@ sub list_untracked {\n \trun_cmd_pipe(qw(git ls-files --others --exclude-standard --), @ARGV);\n }\n \n-my $status_fmt = '%12s %12s %s';\n-my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');\n+# TRANSLATORS: you can adjust this to align \"git add -i\" status menu\n+my $status_fmt = __('%12s %12s %s');\n+my $status_head = sprintf($status_fmt, __('staged'), __('unstaged'), __('path'));\n \n {\n \tmy $initial;\n@@ -680,7 +682,7 @@ sub update_cmd {\n \tmy @mods = list_modified('file-only');\n \treturn if (!@mods);\n \n-\tmy @update = list_and_choose({ PROMPT => 'Update',\n+\tmy @update = list_and_choose({ PROMPT => __('Update'),\n \t\t\t\t       HEADER => $status_head, },\n \t\t\t\t     @mods);\n \tif (@update) {\n@@ -692,7 +694,7 @@ sub update_cmd {\n }\n \n sub revert_cmd {\n-\tmy @update = list_and_choose({ PROMPT => 'Revert',\n+\tmy @update = list_and_choose({ PROMPT => __('Revert'),\n \t\t\t\t       HEADER => $status_head, },\n \t\t\t\t     list_modified());\n \tif (@update) {\n@@ -726,13 +728,13 @@ sub revert_cmd {\n }\n \n sub add_untracked_cmd {\n-\tmy @add = list_and_choose({ PROMPT => 'Add untracked' },\n+\tmy @add = list_and_choose({ PROMPT => __('Add untracked') },\n \t\t\t\t  list_untracked());\n \tif (@add) {\n \t\tsystem(qw(git update-index --add --), @add);\n \t\tsay_n_paths('added', @add);\n \t} else {\n-\t\tprint \"No untracked files.\\n\";\n+\t\tprint __(\"No untracked files.\\n\");\n \t}\n \tprint \"\\n\";\n }\n@@ -1166,8 +1168,14 @@ sub edit_hunk_loop {\n \t\t}\n \t\telse {\n \t\t\tprompt_yesno(\n-\t\t\t\t'Your edited hunk does not apply. Edit again '\n-\t\t\t\t. '(saying \"no\" discards!) [y/n]? '\n+\t\t\t\t# TRANSLATORS: do not translate [y/n]\n+\t\t\t\t# The program will only accept that input\n+\t\t\t\t# at this point.\n+\t\t\t\t# Consider translating (saying \"no\" discards!) as\n+\t\t\t\t# (saying \"n\" for \"no\" discards!) if the translation\n+\t\t\t\t# of the word \"no\" does not start with n.\n+\t\t\t\t__('Your edited hunk does not apply. Edit again '\n+\t\t\t\t   . '(saying \"no\" discards!) [y/n]? ')\n \t\t\t\t) or return undef;\n \t\t}\n \t}\n@@ -1213,11 +1221,11 @@ sub apply_patch_for_checkout_commit {\n \t\trun_git_apply 'apply '.$reverse, @_;\n \t\treturn 1;\n \t} elsif (!$applies_index) {\n-\t\tprint colored $error_color, \"The selected hunks do not apply to the index!\\n\";\n-\t\tif (prompt_yesno \"Apply them to the worktree anyway? \") {\n+\t\tprint colored $error_color, __(\"The selected hunks do not apply to the index!\\n\");\n+\t\tif (prompt_yesno __(\"Apply them to the worktree anyway? \")) {\n \t\t\treturn run_git_apply 'apply '.$reverse, @_;\n \t\t} else {\n-\t\t\tprint colored $error_color, \"Nothing was applied.\\n\";\n+\t\t\tprint colored $error_color, __(\"Nothing was applied.\\n\");\n \t\t\treturn 0;\n \t\t}\n \t} else {\n@@ -1237,9 +1245,9 @@ sub patch_update_cmd {\n \n \tif (!@mods) {\n \t\tif (@all_mods) {\n-\t\t\tprint STDERR \"Only binary files changed.\\n\";\n+\t\t\tprint STDERR __(\"Only binary files changed.\\n\");\n \t\t} else {\n-\t\t\tprint STDERR \"No changes.\\n\";\n+\t\t\tprint STDERR __(\"No changes.\\n\");\n \t\t}\n \t\treturn 0;\n \t}\n@@ -1247,7 +1255,7 @@ sub patch_update_cmd {\n \t\t@them = @mods;\n \t}\n \telse {\n-\t\t@them = list_and_choose({ PROMPT => 'Patch update',\n+\t\t@them = list_and_choose({ PROMPT => __('Patch update'),\n \t\t\t\t\t  HEADER => $status_head, },\n \t\t\t\t\t@mods);\n \t}\n@@ -1397,12 +1405,12 @@ sub patch_update_file {\n \t\t\t\tmy $response = $1;\n \t\t\t\tmy $no = $ix > 10 ? $ix - 10 : 0;\n \t\t\t\twhile ($response eq '') {\n-\t\t\t\t\tmy $extra = \"\";\n \t\t\t\t\t$no = display_hunks(\\@hunk, $no);\n \t\t\t\t\tif ($no < $num) {\n-\t\t\t\t\t\t$extra = \" (<ret> to see more)\";\n+\t\t\t\t\t\tprint __(\"go to which hunk (<ret> to see more)? \");\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tprint __(\"go to which hunk? \");\n \t\t\t\t\t}\n-\t\t\t\t\tprint \"go to which hunk$extra? \";\n \t\t\t\t\t$response = <STDIN>;\n \t\t\t\t\tif (!defined $response) {\n \t\t\t\t\t\t$response = '';\n@@ -1439,7 +1447,7 @@ sub patch_update_file {\n \t\t\telsif ($line =~ m|^/(.*)|) {\n \t\t\t\tmy $regex = $1;\n \t\t\t\tif ($1 eq \"\") {\n-\t\t\t\t\tprint colored $prompt_color, \"search for regex? \";\n+\t\t\t\t\tprint colored $prompt_color, __(\"search for regex? \");\n \t\t\t\t\t$regex = <STDIN>;\n \t\t\t\t\tif (defined $regex) {\n \t\t\t\t\t\tchomp $regex;\n@@ -1462,7 +1470,7 @@ sub patch_update_file {\n \t\t\t\t\t$iy++;\n \t\t\t\t\t$iy = 0 if ($iy >= $num);\n \t\t\t\t\tif ($ix == $iy) {\n-\t\t\t\t\t\terror_msg \"No hunk matches the given pattern\\n\";\n+\t\t\t\t\t\terror_msg __(\"No hunk matches the given pattern\\n\");\n \t\t\t\t\t\tlast;\n \t\t\t\t\t}\n \t\t\t\t}\n@@ -1474,7 +1482,7 @@ sub patch_update_file {\n \t\t\t\t\t$ix--;\n \t\t\t\t}\n \t\t\t\telse {\n-\t\t\t\t\terror_msg \"No previous hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No previous hunk\\n\");\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n@@ -1483,7 +1491,7 @@ sub patch_update_file {\n \t\t\t\t\t$ix++;\n \t\t\t\t}\n \t\t\t\telse {\n-\t\t\t\t\terror_msg \"No next hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No next hunk\\n\");\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n@@ -1496,13 +1504,13 @@ sub patch_update_file {\n \t\t\t\t\t}\n \t\t\t\t}\n \t\t\t\telse {\n-\t\t\t\t\terror_msg \"No previous hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No previous hunk\\n\");\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n \t\t\telsif ($line =~ /^j/) {\n \t\t\t\tif ($other !~ /j/) {\n-\t\t\t\t\terror_msg \"No next hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No next hunk\\n\");\n \t\t\t\t\tnext;\n \t\t\t\t}\n \t\t\t}\n@@ -1560,18 +1568,18 @@ sub diff_cmd {\n \tmy @mods = list_modified('index-only');\n \t@mods = grep { !($_->{BINARY}) } @mods;\n \treturn if (!@mods);\n-\tmy (@them) = list_and_choose({ PROMPT => 'Review diff',\n+\tmy (@them) = list_and_choose({ PROMPT => __('Review diff'),\n \t\t\t\t     IMMEDIATE => 1,\n \t\t\t\t     HEADER => $status_head, },\n \t\t\t\t   @mods);\n \treturn if (!@them);\n-\tmy $reference = is_initial_commit() ? get_empty_tree() : 'HEAD';\n+\tmy $reference = (is_initial_commit()) ? get_empty_tree() : 'HEAD';\n \tsystem(qw(git diff -p --cached), $reference, '--',\n \t\tmap { $_->{VALUE} } @them);\n }\n \n sub quit_cmd {\n-\tprint \"Bye.\\n\";\n+\tprint __(\"Bye.\\n\");\n \texit(0);\n }\n \n@@ -1594,32 +1602,32 @@ sub process_args {\n \t\t\tif ($1 eq 'reset') {\n \t\t\t\t$patch_mode = 'reset_head';\n \t\t\t\t$patch_mode_revision = 'HEAD';\n-\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\tif ($arg ne '--') {\n \t\t\t\t\t$patch_mode_revision = $arg;\n \t\t\t\t\t$patch_mode = ($arg eq 'HEAD' ?\n \t\t\t\t\t\t       'reset_head' : 'reset_nothead');\n-\t\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\t}\n \t\t\t} elsif ($1 eq 'checkout') {\n-\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\tif ($arg eq '--') {\n \t\t\t\t\t$patch_mode = 'checkout_index';\n \t\t\t\t} else {\n \t\t\t\t\t$patch_mode_revision = $arg;\n \t\t\t\t\t$patch_mode = ($arg eq 'HEAD' ?\n \t\t\t\t\t\t       'checkout_head' : 'checkout_nothead');\n-\t\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\t}\n \t\t\t} elsif ($1 eq 'stage' or $1 eq 'stash') {\n \t\t\t\t$patch_mode = $1;\n-\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t} else {\n \t\t\t\tdie \"unknown --patch mode: $1\";\n \t\t\t}\n \t\t} else {\n \t\t\t$patch_mode = 'stage';\n-\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t}\n \t\tdie \"invalid argument $arg, expecting --\"\n \t\t    unless $arg eq \"--\";\n@@ -1641,10 +1649,10 @@ sub main_loop {\n \t\t   [ 'help', \\&help_cmd, ],\n \t);\n \twhile (1) {\n-\t\tmy ($it) = list_and_choose({ PROMPT => 'What now',\n+\t\tmy ($it) = list_and_choose({ PROMPT => __('What now'),\n \t\t\t\t\t     SINGLETON => 1,\n \t\t\t\t\t     LIST_FLAT => 4,\n-\t\t\t\t\t     HEADER => '*** Commands ***',\n+\t\t\t\t\t     HEADER => __('*** Commands ***'),\n \t\t\t\t\t     ON_EOF => \\&quit_cmd,\n \t\t\t\t\t     IMMEDIATE => 1 }, @cmd);\n \t\tif ($it) {\n-- \n2.7.4\n\n"},{"id":"303706","messageId":"20161010125449.7929-3-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 02/14] i18n: add--interactive: mark simple here-documents for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:37Z","receivedAt":"2016-10-10T12:55:55Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark messages in here-document without interpolation for translation.\n\nThe here-document delimiter \\EOF, which is the same as 'EOF', indicate\nthat the text is to be treated literally without interpolation of its\ncontent.  Unfortunately xgettext is not able to extract here documents\nwith delimiter \\EOF but it is with delimiter enclosed in single quotes.\nThen change \\EOF to 'EOF', although in this case does not make\ndifference what variation of here-document to use since there is nothing\nto interpolate.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 8 +++++---\n 1 file changed, 5 insertions(+), 3 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex cf216ec..5800010 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -639,7 +639,7 @@ sub list_and_choose {\n }\n \n sub singleton_prompt_help_cmd {\n-\tprint colored $help_color, <<\\EOF ;\n+\tprint colored $help_color, __ <<'EOF' ;\n Prompt help:\n 1          - select a numbered item\n foo        - select item based on unique prefix\n@@ -648,7 +648,7 @@ EOF\n }\n \n sub prompt_help_cmd {\n-\tprint colored $help_color, <<\\EOF ;\n+\tprint colored $help_color, __ <<'EOF' ;\n Prompt help:\n 1          - select a single item\n 3-5        - select a range of items\n@@ -1584,7 +1584,9 @@ sub quit_cmd {\n }\n \n sub help_cmd {\n-\tprint colored $help_color, <<\\EOF ;\n+# TRANSLATORS: please do not translate the command names\n+# 'status', 'update', 'revert', etc.\n+\tprint colored $help_color, __ <<'EOF' ;\n status        - show paths with changes\n update        - add working tree state to the staged set of changes\n revert        - revert staged set of changes back to the HEAD version\n-- \n2.7.4\n\n"},{"id":"303707","messageId":"20161010125449.7929-4-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 03/14] i18n: add--interactive: mark strings with interpolation for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:38Z","receivedAt":"2016-10-10T12:55:58Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Since at this point Git::I18N.perl lacks support for Perl i18n\nplaceholder substitution, use of sprintf following die or error_msg is\nnecessary for placeholder substitution take place.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 25 +++++++++++++------------\n 1 file changed, 13 insertions(+), 12 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 5800010..d05ac60 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -615,12 +615,12 @@ sub list_and_choose {\n \t\t\telse {\n \t\t\t\t$bottom = $top = find_unique($choice, @stuff);\n \t\t\t\tif (!defined $bottom) {\n-\t\t\t\t\terror_msg \"Huh ($choice)?\\n\";\n+\t\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\\n\"), $choice);\n \t\t\t\t\tnext TOPLOOP;\n \t\t\t\t}\n \t\t\t}\n \t\t\tif ($opts->{SINGLETON} && $bottom != $top) {\n-\t\t\t\terror_msg \"Huh ($choice)?\\n\";\n+\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\\n\"), $choice);\n \t\t\t\tnext TOPLOOP;\n \t\t\t}\n \t\t\tfor ($i = $bottom-1; $i <= $top-1; $i++) {\n@@ -717,7 +717,7 @@ sub revert_cmd {\n \t\t\t\t    $_->{INDEX_ADDDEL} eq 'create') {\n \t\t\t\t\tsystem(qw(git update-index --force-remove --),\n \t\t\t\t\t       $_->{VALUE});\n-\t\t\t\t\tprint \"note: $_->{VALUE} is untracked now.\\n\";\n+\t\t\t\t\tprintf(__(\"note: %s is untracked now.\\n\"), $_->{VALUE});\n \t\t\t\t}\n \t\t\t}\n \t\t}\n@@ -1056,7 +1056,7 @@ sub edit_hunk_manually {\n \tmy $hunkfile = $repo->repo_path . \"/addp-hunk-edit.diff\";\n \tmy $fh;\n \topen $fh, '>', $hunkfile\n-\t\tor die \"failed to open hunk edit file for writing: \" . $!;\n+\t\tor die sprintf(__(\"failed to open hunk edit file for writing: %s\"), $!);\n \tprint $fh \"# Manual hunk edit mode -- see bottom for a quick guide\\n\";\n \tprint $fh @$oldtext;\n \tmy $participle = $patch_mode_flavour{PARTICIPLE};\n@@ -1083,7 +1083,7 @@ EOF\n \t}\n \n \topen $fh, '<', $hunkfile\n-\t\tor die \"failed to open hunk edit file for reading: \" . $!;\n+\t\tor die sprintf(__(\"failed to open hunk edit file for reading: %s\"), $!);\n \tmy @newtext = grep { !/^#/ } <$fh>;\n \tclose $fh;\n \tunlink $hunkfile;\n@@ -1236,7 +1236,7 @@ sub apply_patch_for_checkout_commit {\n \n sub patch_update_cmd {\n \tmy @all_mods = list_modified($patch_mode_flavour{FILTER});\n-\terror_msg \"ignoring unmerged: $_->{VALUE}\\n\"\n+\terror_msg sprintf(__(\"ignoring unmerged: %s\\n\"), $_->{VALUE})\n \t\tfor grep { $_->{UNMERGED} } @all_mods;\n \t@all_mods = grep { !$_->{UNMERGED} } @all_mods;\n \n@@ -1418,7 +1418,8 @@ sub patch_update_file {\n \t\t\t\t\tchomp $response;\n \t\t\t\t}\n \t\t\t\tif ($response !~ /^\\s*\\d+\\s*$/) {\n-\t\t\t\t\terror_msg \"Invalid number: '$response'\\n\";\n+\t\t\t\t\terror_msg sprintf(__(\"Invalid number: '%s'\\n\"),\n+\t\t\t\t\t\t\t     $response);\n \t\t\t\t} elsif (0 < $response && $response <= $num) {\n \t\t\t\t\t$ix = $response - 1;\n \t\t\t\t} else {\n@@ -1460,7 +1461,7 @@ sub patch_update_file {\n \t\t\t\tif ($@) {\n \t\t\t\t\tmy ($err,$exp) = ($@, $1);\n \t\t\t\t\t$err =~ s/ at .*git-add--interactive line \\d+, <STDIN> line \\d+.*$//;\n-\t\t\t\t\terror_msg \"Malformed search regexp $exp: $err\\n\";\n+\t\t\t\t\terror_msg sprintf(__(\"Malformed search regexp %s: %s\\n\"), $exp, $err);\n \t\t\t\t\tnext;\n \t\t\t\t}\n \t\t\t\tmy $iy = $ix;\n@@ -1625,18 +1626,18 @@ sub process_args {\n \t\t\t\t$patch_mode = $1;\n \t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t} else {\n-\t\t\t\tdie \"unknown --patch mode: $1\";\n+\t\t\t\tdie sprintf(__(\"unknown --patch mode: %s\"), $1);\n \t\t\t}\n \t\t} else {\n \t\t\t$patch_mode = 'stage';\n \t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t}\n-\t\tdie \"invalid argument $arg, expecting --\"\n-\t\t    unless $arg eq \"--\";\n+\t\tdie sprintf(__(\"invalid argument %s, expecting --\"),\n+\t\t\t       $arg) unless $arg eq \"--\";\n \t\t%patch_mode_flavour = %{$patch_modes{$patch_mode}};\n \t}\n \telsif ($arg ne \"--\") {\n-\t\tdie \"invalid argument $arg, expecting --\";\n+\t\tdie sprintf(__(\"invalid argument %s, expecting --\"), $arg);\n \t}\n }\n \n-- \n2.7.4\n\n"},{"id":"303708","messageId":"20161010125449.7929-5-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 04/14] i18n: clean.c: match string with git-add--interactive.perl","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:39Z","receivedAt":"2016-10-10T12:55:59Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Change strings for help to match the ones in git-add--interactive.perl.\nThe strings now represent one entry to translate each rather then two\nentries each different only by an ending newline character.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n builtin/clean.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/clean.c b/builtin/clean.c\nindex 0371010..d6bc3aa 100644\n--- a/builtin/clean.c\n+++ b/builtin/clean.c\n@@ -287,11 +287,11 @@ static void pretty_print_menus(struct string_list *menu_list)\n static void prompt_help_cmd(int singleton)\n {\n \tclean_print_color(CLEAN_COLOR_HELP);\n-\tprintf_ln(singleton ?\n+\tprintf(singleton ?\n \t\t  _(\"Prompt help:\\n\"\n \t\t    \"1          - select a numbered item\\n\"\n \t\t    \"foo        - select item based on unique prefix\\n\"\n-\t\t    \"           - (empty) select nothing\") :\n+\t\t    \"           - (empty) select nothing\\n\") :\n \t\t  _(\"Prompt help:\\n\"\n \t\t    \"1          - select a single item\\n\"\n \t\t    \"3-5        - select a range of items\\n\"\n@@ -299,7 +299,7 @@ static void prompt_help_cmd(int singleton)\n \t\t    \"foo        - select item based on unique prefix\\n\"\n \t\t    \"-...       - unselect specified items\\n\"\n \t\t    \"*          - choose all items\\n\"\n-\t\t    \"           - (empty) finish selecting\"));\n+\t\t    \"           - (empty) finish selecting\\n\"));\n \tclean_print_color(CLEAN_COLOR_RESET);\n }\n \n@@ -508,7 +508,7 @@ static int parse_choice(struct menu_stuff *menu_stuff,\n \t\tif (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||\n \t\t    (is_single && bottom != top)) {\n \t\t\tclean_print_color(CLEAN_COLOR_ERROR);\n-\t\t\tprintf_ln(_(\"Huh (%s)?\"), (*ptr)->buf);\n+\t\t\tprintf(_(\"Huh (%s)?\\n\"), (*ptr)->buf);\n \t\t\tclean_print_color(CLEAN_COLOR_RESET);\n \t\t\tcontinue;\n \t\t}\n@@ -774,7 +774,7 @@ static int ask_each_cmd(void)\n static int quit_cmd(void)\n {\n \tstring_list_clear(&del_list, 0);\n-\tprintf_ln(_(\"Bye.\"));\n+\tprintf(_(\"Bye.\\n\"));\n \treturn MENU_RETURN_NO_LOOP;\n }\n \n-- \n2.7.4\n\n"},{"id":"303709","messageId":"20161010125449.7929-6-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 05/14] i18n: add--interactive: mark plural strings","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:40Z","receivedAt":"2016-10-10T12:56:02Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark plural strings for translation.  Unfold each action case in one\nentire sentence.\n\nPass new keyword for xgettext to extract.\n\nUpdate test to include new subroutine __n() for plural strings handling.\n\nUpdate documentation to include a description of the new __n() subroutine.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n Makefile                  |  3 ++-\n git-add--interactive.perl | 27 ++++++++++++++++++---------\n perl/Git/I18N.pm          |  9 ++++++++-\n t/t0202/test.pl           | 11 ++++++++++-\n 4 files changed, 38 insertions(+), 12 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 1aad150..4ef0344 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -2111,7 +2111,8 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \\\n \t--keyword=_ --keyword=N_ --keyword=\"Q_:1,2\"\n XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \\\n \t--keyword=gettextln --keyword=eval_gettextln\n-XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl\n+XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \\\n+\t--keyword=__ --keyword=\"__n:1,2\"\n LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)\n LOCALIZED_SH = $(SCRIPT_SH)\n LOCALIZED_SH += git-parse-remote.sh\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex d05ac60..cd61783 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -669,12 +669,18 @@ sub status_cmd {\n sub say_n_paths {\n \tmy $did = shift @_;\n \tmy $cnt = scalar @_;\n-\tprint \"$did \";\n-\tif (1 < $cnt) {\n-\t\tprint \"$cnt paths\\n\";\n-\t}\n-\telse {\n-\t\tprint \"one path\\n\";\n+\tif ($did eq 'added') {\n+\t\tprintf(__n(\"added %d path\\n\", \"added %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n+\t} elsif ($did eq 'updated') {\n+\t\tprintf(__n(\"updated %d path\\n\", \"updated %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n+\t} elsif ($did eq 'reverted') {\n+\t\tprintf(__n(\"reverted %d path\\n\", \"reverted %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n+\t} else {\n+\t\tprintf(__n(\"touched %d path\\n\", \"touched %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n \t}\n }\n \n@@ -1423,7 +1429,8 @@ sub patch_update_file {\n \t\t\t\t} elsif (0 < $response && $response <= $num) {\n \t\t\t\t\t$ix = $response - 1;\n \t\t\t\t} else {\n-\t\t\t\t\terror_msg \"Sorry, only $num hunks available.\\n\";\n+\t\t\t\t\terror_msg sprintf(__n(\"Sorry, only %d hunk available.\\n\",\n+\t\t\t\t\t\t\t      \"Sorry, only %d hunks available.\\n\", $num), $num);\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n@@ -1518,8 +1525,10 @@ sub patch_update_file {\n \t\t\telsif ($other =~ /s/ && $line =~ /^s/) {\n \t\t\t\tmy @split = split_hunk($hunk[$ix]{TEXT}, $hunk[$ix]{DISPLAY});\n \t\t\t\tif (1 < @split) {\n-\t\t\t\t\tprint colored $header_color, \"Split into \",\n-\t\t\t\t\tscalar(@split), \" hunks.\\n\";\n+\t\t\t\t\tprint colored $header_color, sprintf(\n+\t\t\t\t\t\t__n(\"Split into %d hunk.\\n\",\n+\t\t\t\t\t\t    \"Split into %d hunks.\\n\",\n+\t\t\t\t\t\t    scalar(@split)), scalar(@split));\n \t\t\t\t}\n \t\t\t\tsplice (@hunk, $ix, 1, @split);\n \t\t\t\t$num = scalar @hunk;\ndiff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm\nindex f889fd6..3f7ac25 100644\n--- a/perl/Git/I18N.pm\n+++ b/perl/Git/I18N.pm\n@@ -13,7 +13,7 @@ BEGIN {\n \t}\n }\n \n-our @EXPORT = qw(__);\n+our @EXPORT = qw(__ __n);\n our @EXPORT_OK = @EXPORT;\n \n sub __bootstrap_locale_messages {\n@@ -44,6 +44,7 @@ BEGIN\n \teval {\n \t\t__bootstrap_locale_messages();\n \t\t*__ = \\&Locale::Messages::gettext;\n+\t\t*__n = \\&Locale::Messages::ngettext;\n \t\t1;\n \t} or do {\n \t\t# Tell test.pl that we couldn't load the gettext library.\n@@ -51,6 +52,7 @@ BEGIN\n \n \t\t# Just a fall-through no-op\n \t\t*__ = sub ($) { $_[0] };\n+\t\t*__n = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };\n \t};\n }\n \n@@ -70,6 +72,8 @@ Git::I18N - Perl interface to Git's Gettext localizations\n \n \tprintf __(\"The following error occurred: %s\\n\"), $error;\n \n+\tprintf __n(\"commited %d file\", \"commited %d files\", $files), $files;\n+\n =head1 DESCRIPTION\n \n Git's internal Perl interface to gettext via L<Locale::Messages>. If\n@@ -87,6 +91,9 @@ it.\n L<Locale::Messages>'s gettext function if all goes well, otherwise our\n passthrough fallback function.\n \n+=head2 __n($$$)\n+L<Locale::Messages>'s ngettext function or passthrough fallback function.\n+\n =head1 AUTHOR\n \n E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>\ndiff --git a/t/t0202/test.pl b/t/t0202/test.pl\nindex 2c10cb4..4101833 100755\n--- a/t/t0202/test.pl\n+++ b/t/t0202/test.pl\n@@ -4,7 +4,7 @@ use lib (split(/:/, $ENV{GITPERLLIB}));\n use strict;\n use warnings;\n use POSIX qw(:locale_h);\n-use Test::More tests => 8;\n+use Test::More tests => 11;\n use Git::I18N;\n \n my $has_gettext_library = $Git::I18N::__HAS_LIBRARY;\n@@ -31,6 +31,7 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \t# more gettext wrapper functions.\n \tmy %prototypes = (qw(\n \t\t__\t$\n+\t\t__n\t$$$\n \t));\n \twhile (my ($sub, $proto) = each %prototypes) {\n \t\tis(prototype(\\&{\"Git::I18N::$sub\"}), $proto, \"sanity: $sub has a $proto prototype\");\n@@ -46,6 +47,14 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \tmy ($got, $expect) = (('TEST: A Perl test string') x 2);\n \n \tis(__($got), $expect, \"Passing a string through __() in the C locale works\");\n+\n+\tmy ($got_singular, $got_plural, $expect_singular, $expect_plural) =\n+\t\t(('TEST: 1 file', 'TEST: n files') x 2);\n+\n+\tis(__n($got_singular, $got_plural, 1), $expect_singular,\n+\t\t\"Get singular string through __n() in C locale\");\n+\tis(__n($got_singular, $got_plural, 2), $expect_plural,\n+\t\t\"Get plural string through __n() in C locale\");\n }\n \n # Test a basic message on different locales\n-- \n2.7.4\n\n"},{"id":"303710","messageId":"20161010125449.7929-7-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 06/14] i18n: add--interactive: mark patch prompt for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:41Z","receivedAt":"2016-10-10T12:56:07Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark prompt message assembled in place for translation, unfolding each\nuse case for each entry in the %patch_modes hash table.\n\nPreviously, this script relied on whether $patch_mode was set to run the\ncommand patch_update_cmd() or show status and loop the main loop. Now,\nit uses $cmd to indicate we must run patch_update_cmd() and $patch_mode\nis used to tell which flavor of the %patch_modes are we on.  This is\nintroduced in order to be able to mark and unfold the message prompt\nknowing in which context we are.\n\nThe tracking of context was done previously by point %patch_mode_flavour\nhash table to the correct entry of %patch_modes, focusing only on value\nof %patch_modes. Now, we are also interested in the key ('staged',\n'stash', 'checkout_head', ...).\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n Makefile                  |  2 +-\n git-add--interactive.perl | 54 ++++++++++++++++++++++++++++++++++++++++-------\n perl/Git/I18N.pm          | 10 ++++++++-\n t/t0202/test.pl           |  5 ++++-\n 4 files changed, 60 insertions(+), 11 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 4ef0344..9dc95cb 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -2112,7 +2112,7 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \\\n XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \\\n \t--keyword=gettextln --keyword=eval_gettextln\n XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \\\n-\t--keyword=__ --keyword=\"__n:1,2\"\n+\t--keyword=__ --keyword=N__ --keyword=\"__n:1,2\"\n LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)\n LOCALIZED_SH = $(SCRIPT_SH)\n LOCALIZED_SH += git-parse-remote.sh\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex cd61783..b7d382b 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -93,6 +93,7 @@ sub colored {\n }\n \n # command line options\n+my $cmd;\n my $patch_mode;\n my $patch_mode_revision;\n \n@@ -173,7 +174,8 @@ my %patch_modes = (\n \t},\n );\n \n-my %patch_mode_flavour = %{$patch_modes{stage}};\n+$patch_mode = 'stage';\n+my %patch_mode_flavour = %{$patch_modes{$patch_mode}};\n \n sub run_cmd_pipe {\n \tif ($^O eq 'MSWin32') {\n@@ -1311,6 +1313,44 @@ sub display_hunks {\n \treturn $i;\n }\n \n+my %patch_update_prompt_modes = (\n+\tstage => {\n+\t\tmode => N__(\"Stage mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Stage deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Stage this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tstash => {\n+\t\tmode => N__(\"Stash mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Stash deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Stash this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\treset_head => {\n+\t\tmode => N__(\"Unstage mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Unstage deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Unstage this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\treset_nothead => {\n+\t\tmode => N__(\"Apply mode change to index [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Apply deletion to index [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Apply this hunk to index [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_index => {\n+\t\tmode => N__(\"Discard mode change from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Discard deletion from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Discard this hunk from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_head => {\n+\t\tmode => N__(\"Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_nothead => {\n+\t\tmode => N__(\"Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+);\n+\n sub patch_update_file {\n \tmy $quit = 0;\n \tmy ($ix, $num);\n@@ -1383,12 +1423,9 @@ sub patch_update_file {\n \t\tfor (@{$hunk[$ix]{DISPLAY}}) {\n \t\t\tprint;\n \t\t}\n-\t\tprint colored $prompt_color, $patch_mode_flavour{VERB},\n-\t\t  ($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' :\n-\t\t   $hunk[$ix]{TYPE} eq 'deletion' ? ' deletion' :\n-\t\t   ' this hunk'),\n-\t\t  $patch_mode_flavour{TARGET},\n-\t\t  \" [y,n,q,a,d,/$other,?]? \";\n+\t\tprint colored $prompt_color,\n+\t\t\tsprintf(__($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}), $other);\n+\n \t\tmy $line = prompt_single_character;\n \t\tlast unless defined $line;\n \t\tif ($line) {\n@@ -1644,6 +1681,7 @@ sub process_args {\n \t\tdie sprintf(__(\"invalid argument %s, expecting --\"),\n \t\t\t       $arg) unless $arg eq \"--\";\n \t\t%patch_mode_flavour = %{$patch_modes{$patch_mode}};\n+\t\t$cmd = 1;\n \t}\n \telsif ($arg ne \"--\") {\n \t\tdie sprintf(__(\"invalid argument %s, expecting --\"), $arg);\n@@ -1680,7 +1718,7 @@ sub main_loop {\n \n process_args();\n refresh();\n-if ($patch_mode) {\n+if ($cmd) {\n \tpatch_update_cmd();\n }\n else {\ndiff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm\nindex 3f7ac25..32c4568 100644\n--- a/perl/Git/I18N.pm\n+++ b/perl/Git/I18N.pm\n@@ -13,7 +13,7 @@ BEGIN {\n \t}\n }\n \n-our @EXPORT = qw(__ __n);\n+our @EXPORT = qw(__ __n N__);\n our @EXPORT_OK = @EXPORT;\n \n sub __bootstrap_locale_messages {\n@@ -54,6 +54,8 @@ BEGIN\n \t\t*__ = sub ($) { $_[0] };\n \t\t*__n = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };\n \t};\n+\n+\tsub N__($) { return shift; }\n }\n \n 1;\n@@ -74,6 +76,7 @@ Git::I18N - Perl interface to Git's Gettext localizations\n \n \tprintf __n(\"commited %d file\", \"commited %d files\", $files), $files;\n \n+\n =head1 DESCRIPTION\n \n Git's internal Perl interface to gettext via L<Locale::Messages>. If\n@@ -94,6 +97,11 @@ passthrough fallback function.\n =head2 __n($$$)\n L<Locale::Messages>'s ngettext function or passthrough fallback function.\n \n+=head2 N__($)\n+No-op that only returns its argument. Use this if you want xgettext to\n+extract the text to the pot template but do not want to trigger retrival of\n+the translation at run time.\n+\n =head1 AUTHOR\n \n E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>\ndiff --git a/t/t0202/test.pl b/t/t0202/test.pl\nindex 4101833..2cbf7b9 100755\n--- a/t/t0202/test.pl\n+++ b/t/t0202/test.pl\n@@ -4,7 +4,7 @@ use lib (split(/:/, $ENV{GITPERLLIB}));\n use strict;\n use warnings;\n use POSIX qw(:locale_h);\n-use Test::More tests => 11;\n+use Test::More tests => 13;\n use Git::I18N;\n \n my $has_gettext_library = $Git::I18N::__HAS_LIBRARY;\n@@ -32,6 +32,7 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \tmy %prototypes = (qw(\n \t\t__\t$\n \t\t__n\t$$$\n+\t\tN__\t$\n \t));\n \twhile (my ($sub, $proto) = each %prototypes) {\n \t\tis(prototype(\\&{\"Git::I18N::$sub\"}), $proto, \"sanity: $sub has a $proto prototype\");\n@@ -55,6 +56,8 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \t\t\"Get singular string through __n() in C locale\");\n \tis(__n($got_singular, $got_plural, 2), $expect_plural,\n \t\t\"Get plural string through __n() in C locale\");\n+\n+\tis(N__($got), $expect, \"Passing a string through N__() in the C locale works\");\n }\n \n # Test a basic message on different locales\n-- \n2.7.4\n\n"},{"id":"303711","messageId":"20161010125449.7929-8-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 07/14] i18n: add--interactive: i18n of help_patch_cmd","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:42Z","receivedAt":"2016-10-10T12:56:13Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark help message of help_patch_cmd for translation.  The message must\nbe unfolded to be free of variables so we can have high quality\ntranslations.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 54 ++++++++++++++++++++++++++++++++++++++++-------\n 1 file changed, 46 insertions(+), 8 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex b7d382b..045b847 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -1189,15 +1189,53 @@ sub edit_hunk_loop {\n \t}\n }\n \n+my %help_patch_modes = (\n+\tstage => N__(\n+\"y - stage this hunk\n+n - do not stage this hunk\n+q - quit; do not stage this hunk or any of the remaining ones\n+a - stage this hunk and all later hunks in the file\n+d - do not stage this hunk or any of the later hunks in the file\"),\n+\tstash => N__(\n+\"y - stash this hunk\n+n - do not stash this hunk\n+q - quit; do not stash this hunk or any of the remaining ones\n+a - stash this hunk and all later hunks in the file\n+d - do not stash this hunk or any of the later hunks in the file\"),\n+\treset_head => N__(\n+\"y - unstage this hunk\n+n - do not unstage this hunk\n+q - quit; do not unstage this hunk or any of the remaining ones\n+a - unstage this hunk and all later hunks in the file\n+d - do not unstage this hunk or any of the later hunks in the file\"),\n+\treset_nothead => N__(\n+\"y - apply this hunk to index\n+n - do not apply this hunk to index\n+q - quit; do not apply this hunk or any of the remaining ones\n+a - apply this hunk and all later hunks in the file\n+d - do not apply this hunk or any of the later hunks in the file\"),\n+\tcheckout_index => N__(\n+\"y - discard this hunk from worktree\n+n - do not discard this hunk from worktree\n+q - quit; do not discard this hunk or any of the remaining ones\n+a - discard this hunk and all later hunks in the file\n+d - do not discard this hunk or any of the later hunks in the file\"),\n+\tcheckout_head => N__(\n+\"y - discard this hunk from index and worktree\n+n - do not discard this hunk from index and worktree\n+q - quit; do not discard this hunk or any of the remaining ones\n+a - discard this hunk and all later hunks in the file\n+d - do not discard this hunk or any of the later hunks in the file\"),\n+\tcheckout_nothead => N__(\n+\"y - apply this hunk to index and worktree\n+n - do not apply this hunk to index and worktree\n+q - quit; do not apply this hunk or any of the remaining ones\n+a - apply this hunk and all later hunks in the file\n+d - do not apply this hunk or any of the later hunks in the file\"),\n+);\n+\n sub help_patch_cmd {\n-\tmy $verb = lc $patch_mode_flavour{VERB};\n-\tmy $target = $patch_mode_flavour{TARGET};\n-\tprint colored $help_color, <<EOF ;\n-y - $verb this hunk$target\n-n - do not $verb this hunk$target\n-q - quit; do not $verb this hunk or any of the remaining ones\n-a - $verb this hunk and all later hunks in the file\n-d - do not $verb this hunk or any of the later hunks in the file\n+\tprint colored $help_color, __($help_patch_modes{$patch_mode}), \"\\n\", __ <<EOF ;\n g - select a hunk to go to\n / - search for a hunk matching the given regex\n j - leave this hunk undecided, see next undecided hunk\n-- \n2.7.4\n\n"},{"id":"303712","messageId":"20161010125449.7929-9-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 08/14] i18n: add--interactive: mark edit_hunk_manually message for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:43Z","receivedAt":"2016-10-10T12:56:16Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark message of edit_hunk_manually displayed in the editing file when\nuser chooses 'e' option.  The message had to be unfolded to allow\ntranslation of the $participle verb.\n\nSome messages end up being exactly the same for some uses cases, but\nleft it for easier change in the future, e.g., wanting to change wording\nof one particular use case.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 45 ++++++++++++++++++++++++++++++++++-----------\n 1 file changed, 34 insertions(+), 11 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 045b847..861f7b0 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -1058,6 +1058,30 @@ sub color_diff {\n \t} @_;\n }\n \n+my %edit_hunk_manually_modes = (\n+\tstage => N__(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for staging.\"),\n+\tstash => N__(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for stashing.\"),\n+\treset_head => N__(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for unstaging.\"),\n+\treset_nothead => N__(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for applying.\"),\n+\tcheckout_index => N__(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for discarding\"),\n+\tcheckout_head => N__(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for discarding.\"),\n+\tcheckout_nothead => N__(\n+\"# If the patch applies cleanly, the edited hunk will immediately be\n+# marked for applying.\"),\n+);\n+\n sub edit_hunk_manually {\n \tmy ($oldtext) = @_;\n \n@@ -1065,22 +1089,21 @@ sub edit_hunk_manually {\n \tmy $fh;\n \topen $fh, '>', $hunkfile\n \t\tor die sprintf(__(\"failed to open hunk edit file for writing: %s\"), $!);\n-\tprint $fh \"# Manual hunk edit mode -- see bottom for a quick guide\\n\";\n+\tprint $fh __(\"# Manual hunk edit mode -- see bottom for a quick guide\\n\");\n \tprint $fh @$oldtext;\n-\tmy $participle = $patch_mode_flavour{PARTICIPLE};\n \tmy $is_reverse = $patch_mode_flavour{IS_REVERSE};\n \tmy ($remove_plus, $remove_minus) = $is_reverse ? ('-', '+') : ('+', '-');\n-\tprint $fh <<EOF;\n-# ---\n-# To remove '$remove_minus' lines, make them ' ' lines (context).\n-# To remove '$remove_plus' lines, delete them.\n+\tprint $fh sprintf(__(\n+\"# ---\n+# To remove '%s' lines, make them ' ' lines (context).\n+# To remove '%s' lines, delete them.\n # Lines starting with # will be removed.\n-#\n-# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for $participle. If it does not apply cleanly, you will be given\n+#\\n\"), $remove_minus, $remove_plus),\n+__($edit_hunk_manually_modes{$patch_mode}), __(\n+# TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.\n+\" If it does not apply cleanly, you will be given\n # an opportunity to edit again. If all lines of the hunk are removed,\n-# then the edit is aborted and the hunk is left unchanged.\n-EOF\n+# then the edit is aborted and the hunk is left unchanged.\\n\");\n \tclose $fh;\n \n \tchomp(my $editor = run_cmd_pipe(qw(git var GIT_EDITOR)));\n-- \n2.7.4\n\n"},{"id":"303713","messageId":"20161010125449.7929-10-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 09/14] i18n: add--interactive: remove %patch_modes entries","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:44Z","receivedAt":"2016-10-10T12:56:19Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Remove unnecessary entries from %patch_modes. After the i18n conversion,\nthese entries are not used anymore.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 21 ---------------------\n 1 file changed, 21 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 861f7b0..d7a8e0d 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -106,9 +106,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-files -p',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Stage',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'staging',\n \t\tFILTER => 'file-only',\n \t\tIS_REVERSE => 0,\n \t},\n@@ -116,9 +113,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p HEAD',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Stash',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'stashing',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 0,\n \t},\n@@ -126,9 +120,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p --cached',\n \t\tAPPLY => sub { apply_patch 'apply -R --cached', @_; },\n \t\tAPPLY_CHECK => 'apply -R --cached',\n-\t\tVERB => 'Unstage',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'unstaging',\n \t\tFILTER => 'index-only',\n \t\tIS_REVERSE => 1,\n \t},\n@@ -136,9 +127,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -R -p --cached',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Apply',\n-\t\tTARGET => ' to index',\n-\t\tPARTICIPLE => 'applying',\n \t\tFILTER => 'index-only',\n \t\tIS_REVERSE => 0,\n \t},\n@@ -146,9 +134,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-files -p',\n \t\tAPPLY => sub { apply_patch 'apply -R', @_; },\n \t\tAPPLY_CHECK => 'apply -R',\n-\t\tVERB => 'Discard',\n-\t\tTARGET => ' from worktree',\n-\t\tPARTICIPLE => 'discarding',\n \t\tFILTER => 'file-only',\n \t\tIS_REVERSE => 1,\n \t},\n@@ -156,9 +141,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p',\n \t\tAPPLY => sub { apply_patch_for_checkout_commit '-R', @_ },\n \t\tAPPLY_CHECK => 'apply -R',\n-\t\tVERB => 'Discard',\n-\t\tTARGET => ' from index and worktree',\n-\t\tPARTICIPLE => 'discarding',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 1,\n \t},\n@@ -166,9 +148,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -R -p',\n \t\tAPPLY => sub { apply_patch_for_checkout_commit '', @_ },\n \t\tAPPLY_CHECK => 'apply',\n-\t\tVERB => 'Apply',\n-\t\tTARGET => ' to index and worktree',\n-\t\tPARTICIPLE => 'applying',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 0,\n \t},\n-- \n2.7.4\n\n"},{"id":"303714","messageId":"20161010125449.7929-11-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 10/14] i18n: add--interactive: mark status words for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:45Z","receivedAt":"2016-10-10T12:56:22Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark words 'nothing', 'unchanged' and 'binary' used to display what has\nbeen staged or not, in \"git add -i\" status command.\n\nAlternatively one could mark N__('nothing') no-op in order to\nxgettext(1) extract the string and then trigger the translation at run\ntime only with __($print->{FILE}), but that has the side effect of triggering\nretrieval of translations for the changes indicator too (e.g. +2/-1)\nwhich may or may not be a problem.\n\nTo avoid that potential problem, mark only where there is certain to\ntrigger translation only of those words but in this case we must also\nretrieve the translation for the eq tests, since the value assigned was\nof the translation, not the English source.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex d7a8e0d..4754104 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -295,7 +295,7 @@ sub list_modified {\n \t\t\tmy ($change, $bin);\n \t\t\t$file = unquote_path($file);\n \t\t\tif ($add eq '-' && $del eq '-') {\n-\t\t\t\t$change = 'binary';\n+\t\t\t\t$change = __('binary');\n \t\t\t\t$bin = 1;\n \t\t\t}\n \t\t\telse {\n@@ -304,7 +304,7 @@ sub list_modified {\n \t\t\t$data{$file} = {\n \t\t\t\tINDEX => $change,\n \t\t\t\tBINARY => $bin,\n-\t\t\t\tFILE => 'nothing',\n+\t\t\t\tFILE => __('nothing'),\n \t\t\t}\n \t\t}\n \t\telsif (($adddel, $file) =\n@@ -320,7 +320,7 @@ sub list_modified {\n \t\t\t$file = unquote_path($file);\n \t\t\tmy ($change, $bin);\n \t\t\tif ($add eq '-' && $del eq '-') {\n-\t\t\t\t$change = 'binary';\n+\t\t\t\t$change = __('binary');\n \t\t\t\t$bin = 1;\n \t\t\t}\n \t\t\telse {\n@@ -340,7 +340,7 @@ sub list_modified {\n \t\t\t$file = unquote_path($2);\n \t\t\tif (!exists $data{$file}) {\n \t\t\t\t$data{$file} = +{\n-\t\t\t\t\tINDEX => 'unchanged',\n+\t\t\t\t\tINDEX => __('unchanged'),\n \t\t\t\t\tBINARY => 0,\n \t\t\t\t};\n \t\t\t}\n@@ -355,10 +355,10 @@ sub list_modified {\n \n \t\tif ($only) {\n \t\t\tif ($only eq 'index-only') {\n-\t\t\t\tnext if ($it->{INDEX} eq 'unchanged');\n+\t\t\t\tnext if ($it->{INDEX} eq __('unchanged'));\n \t\t\t}\n \t\t\tif ($only eq 'file-only') {\n-\t\t\t\tnext if ($it->{FILE} eq 'nothing');\n+\t\t\t\tnext if ($it->{FILE} eq __('nothing'));\n \t\t\t}\n \t\t}\n \t\tpush @return, +{\n-- \n2.7.4\n\n"},{"id":"303715","messageId":"20161010125449.7929-12-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 11/14] i18n: send-email: mark strings for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:46Z","receivedAt":"2016-10-10T12:56:31Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark strings often displayed to the user for translation.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-send-email.perl | 52 ++++++++++++++++++++++++++++++----------------------\n 1 file changed, 30 insertions(+), 22 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex da81be4..78eb59b 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -28,6 +28,7 @@ use File::Temp qw/ tempdir tempfile /;\n use File::Spec::Functions qw(catfile);\n use Error qw(:try);\n use Git;\n+use Git::I18N;\n \n Getopt::Long::Configure qw/ pass_through /;\n \n@@ -797,12 +798,12 @@ foreach my $f (@files) {\n }\n \n if (!defined $auto_8bit_encoding && scalar %broken_encoding) {\n-\tprint \"The following files are 8bit, but do not declare \" .\n-\t\t\"a Content-Transfer-Encoding.\\n\";\n+\tprint __(\"The following files are 8bit, but do not declare \" .\n+\t\t \"a Content-Transfer-Encoding.\\n\");\n \tforeach my $f (sort keys %broken_encoding) {\n \t\tprint \"    $f\\n\";\n \t}\n-\t$auto_8bit_encoding = ask(\"Which 8bit encoding should I declare [UTF-8]? \",\n+\t$auto_8bit_encoding = ask(__(\"Which 8bit encoding should I declare [UTF-8]? \"),\n \t\t\t\t  valid_re => qr/.{4}/, confirm_only => 1,\n \t\t\t\t  default => \"UTF-8\");\n }\n@@ -829,7 +830,7 @@ if (defined $sender) {\n # But it's a no-op to run sanitize_address on an already sanitized address.\n $sender = sanitize_address($sender);\n \n-my $to_whom = \"To whom should the emails be sent (if anyone)?\";\n+my $to_whom = __(\"To whom should the emails be sent (if anyone)?\");\n my $prompting = 0;\n if (!@initial_to && !defined $to_cmd) {\n \tmy $to = ask(\"$to_whom \",\n@@ -859,7 +860,7 @@ sub expand_one_alias {\n \n if ($thread && !defined $initial_reply_to && $prompting) {\n \t$initial_reply_to = ask(\n-\t\t\"Message-ID to be used as In-Reply-To for the first email (if any)? \",\n+\t\t__(\"Message-ID to be used as In-Reply-To for the first email (if any)? \"),\n \t\tdefault => \"\",\n \t\tvalid_re => qr/\\@.*\\./, confirm_only => 1);\n }\n@@ -918,7 +919,10 @@ sub validate_address {\n \tmy $address = shift;\n \twhile (!extract_valid_address($address)) {\n \t\tprint STDERR \"error: unable to extract a valid address from: $address\\n\";\n-\t\t$_ = ask(\"What to do with this address? ([q]uit|[d]rop|[e]dit): \",\n+\t\t# TRANSLATORS: Make sure to include [q] [d] [e] in your\n+\t\t# translation. The program will only accept English input\n+\t\t# at this point.\n+\t\t$_ = ask(__(\"What to do with this address? ([q]uit|[d]rop|[e]dit): \"),\n \t\t\tvalid_re => qr/^(?:quit|q|drop|d|edit|e)/i,\n \t\t\tdefault => 'q');\n \t\tif (/^d/i) {\n@@ -1293,17 +1297,21 @@ Message-Id: $message_id\n \t\tif ($needs_confirm eq \"inform\") {\n \t\t\t$confirm_unconfigured = 0; # squelch this message for the rest of this run\n \t\t\t$ask_default = \"y\"; # assume yes on EOF since user hasn't explicitly asked for confirmation\n-\t\t\tprint \"    The Cc list above has been expanded by additional\\n\";\n-\t\t\tprint \"    addresses found in the patch commit message. By default\\n\";\n-\t\t\tprint \"    send-email prompts before sending whenever this occurs.\\n\";\n-\t\t\tprint \"    This behavior is controlled by the sendemail.confirm\\n\";\n-\t\t\tprint \"    configuration setting.\\n\";\n-\t\t\tprint \"\\n\";\n-\t\t\tprint \"    For additional information, run 'git send-email --help'.\\n\";\n-\t\t\tprint \"    To retain the current behavior, but squelch this message,\\n\";\n-\t\t\tprint \"    run 'git config --global sendemail.confirm auto'.\\n\\n\";\n+\t\t\tprint __(\n+\"    The Cc list above has been expanded by additional\n+    addresses found in the patch commit message. By default\n+    send-email prompts before sending whenever this occurs.\n+    This behavior is controlled by the sendemail.confirm\n+    configuration setting.\n+\n+    For additional information, run 'git send-email --help'.\n+    To retain the current behavior, but squelch this message,\n+    run 'git config --global sendemail.confirm auto'.\"), \"\\n\\n\";\n \t\t}\n-\t\t$_ = ask(\"Send this email? ([y]es|[n]o|[q]uit|[a]ll): \",\n+\t\t# TRANSLATORS: Make sure to include [y] [n] [q] [a] in your\n+\t\t# translation. The program will only accept English input\n+\t\t# at this point.\n+\t\t$_ = ask(__(\"Send this email? ([y]es|[n]o|[q]uit|[a]ll): \"),\n \t\t         valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,\n \t\t         default => $ask_default);\n \t\tdie \"Send this email reply required\" unless defined $_;\n@@ -1405,7 +1413,7 @@ Message-Id: $message_id\n \tif ($quiet) {\n \t\tprintf (($dry_run ? \"Dry-\" : \"\").\"Sent %s\\n\", $subject);\n \t} else {\n-\t\tprint (($dry_run ? \"Dry-\" : \"\").\"OK. Log says:\\n\");\n+\t\tprint($dry_run ? __(\"Dry-OK. Log says:\\n\") : __(\"OK. Log says:\\n\"));\n \t\tif (!file_name_is_absolute($smtp_server)) {\n \t\t\tprint \"Server: $smtp_server\\n\";\n \t\t\tprint \"MAIL FROM:<$raw_from>\\n\";\n@@ -1480,13 +1488,13 @@ foreach my $t (@files) {\n \t\t\t\t$sauthor = sanitize_address($author);\n \t\t\t\tnext if $suppress_cc{'author'};\n \t\t\t\tnext if $suppress_cc{'self'} and $sauthor eq $sender;\n-\t\t\t\tprintf(\"(mbox) Adding cc: %s from line '%s'\\n\",\n+\t\t\t\tprintf(__(\"(mbox) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t\t$1, $_) unless $quiet;\n \t\t\t\tpush @cc, $1;\n \t\t\t}\n \t\t\telsif (/^To:\\s+(.*)$/i) {\n \t\t\t\tforeach my $addr (parse_address_line($1)) {\n-\t\t\t\t\tprintf(\"(mbox) Adding to: %s from line '%s'\\n\",\n+\t\t\t\t\tprintf(__(\"(mbox) Adding to: %s from line '%s'\\n\"),\n \t\t\t\t\t\t$addr, $_) unless $quiet;\n \t\t\t\t\tpush @to, $addr;\n \t\t\t\t}\n@@ -1500,7 +1508,7 @@ foreach my $t (@files) {\n \t\t\t\t\t} else {\n \t\t\t\t\t\tnext if ($suppress_cc{'cc'});\n \t\t\t\t\t}\n-\t\t\t\t\tprintf(\"(mbox) Adding cc: %s from line '%s'\\n\",\n+\t\t\t\t\tprintf(__(\"(mbox) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t\t\t$addr, $_) unless $quiet;\n \t\t\t\t\tpush @cc, $addr;\n \t\t\t\t}\n@@ -1534,7 +1542,7 @@ foreach my $t (@files) {\n \t\t\t# So let's support that, too.\n \t\t\t$input_format = 'lots';\n \t\t\tif (@cc == 0 && !$suppress_cc{'cc'}) {\n-\t\t\t\tprintf(\"(non-mbox) Adding cc: %s from line '%s'\\n\",\n+\t\t\t\tprintf(__(\"(non-mbox) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t\t$_, $_) unless $quiet;\n \t\t\t\tpush @cc, $_;\n \t\t\t} elsif (!defined $subject) {\n@@ -1557,7 +1565,7 @@ foreach my $t (@files) {\n \t\t\t\tnext if $suppress_cc{'bodycc'} and $what =~ /Cc/i;\n \t\t\t}\n \t\t\tpush @cc, $c;\n-\t\t\tprintf(\"(body) Adding cc: %s from line '%s'\\n\",\n+\t\t\tprintf(__(\"(body) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t$c, $_) unless $quiet;\n \t\t}\n \t}\n-- \n2.7.4\n\n"},{"id":"303716","messageId":"20161010125449.7929-13-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 12/14] i18n: send-email: mark warnings and errors for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:47Z","receivedAt":"2016-10-10T12:56:34Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark warnings, errors and other messages for translation.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-send-email.perl | 34 +++++++++++++++++-----------------\n 1 file changed, 17 insertions(+), 17 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 78eb59b..982c6c0 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -118,20 +118,20 @@ sub format_2822_time {\n \tmy $localmin = $localtm[1] + $localtm[2] * 60;\n \tmy $gmtmin = $gmttm[1] + $gmttm[2] * 60;\n \tif ($localtm[0] != $gmttm[0]) {\n-\t\tdie \"local zone differs from GMT by a non-minute interval\\n\";\n+\t\tdie __(\"local zone differs from GMT by a non-minute interval\\n\");\n \t}\n \tif ((($gmttm[6] + 1) % 7) == $localtm[6]) {\n \t\t$localmin += 1440;\n \t} elsif ((($gmttm[6] - 1) % 7) == $localtm[6]) {\n \t\t$localmin -= 1440;\n \t} elsif ($gmttm[6] != $localtm[6]) {\n-\t\tdie \"local time offset greater than or equal to 24 hours\\n\";\n+\t\tdie __(\"local time offset greater than or equal to 24 hours\\n\");\n \t}\n \tmy $offset = $localmin - $gmtmin;\n \tmy $offhour = $offset / 60;\n \tmy $offmin = abs($offset % 60);\n \tif (abs($offhour) >= 24) {\n-\t\tdie (\"local time offset greater than or equal to 24 hours\\n\");\n+\t\tdie __(\"local time offset greater than or equal to 24 hours\\n\");\n \t}\n \n \treturn sprintf(\"%s, %2d %s %d %02d:%02d:%02d %s%02d%02d\",\n@@ -199,13 +199,13 @@ sub do_edit {\n \t\tmap {\n \t\t\tsystem('sh', '-c', $editor.' \"$@\"', $editor, $_);\n \t\t\tif (($? & 127) || ($? >> 8)) {\n-\t\t\t\tdie(\"the editor exited uncleanly, aborting everything\");\n+\t\t\t\tdie(__(\"the editor exited uncleanly, aborting everything\"));\n \t\t\t}\n \t\t} @_;\n \t} else {\n \t\tsystem('sh', '-c', $editor.' \"$@\"', $editor, @_);\n \t\tif (($? & 127) || ($? >> 8)) {\n-\t\t\tdie(\"the editor exited uncleanly, aborting everything\");\n+\t\t\tdie(__(\"the editor exited uncleanly, aborting everything\"));\n \t\t}\n \t}\n }\n@@ -299,7 +299,7 @@ my $help;\n my $rc = GetOptions(\"h\" => \\$help,\n                     \"dump-aliases\" => \\$dump_aliases);\n usage() unless $rc;\n-die \"--dump-aliases incompatible with other options\\n\"\n+die __(\"--dump-aliases incompatible with other options\\n\")\n     if !$help and $dump_aliases and @ARGV;\n $rc = GetOptions(\n \t\t    \"sender|from=s\" => \\$sender,\n@@ -362,7 +362,7 @@ unless ($rc) {\n     usage();\n }\n \n-die \"Cannot run git format-patch from outside a repository\\n\"\n+die __(\"Cannot run git format-patch from outside a repository\\n\")\n \tif $format_patch and not $repo;\n \n # Now, let's fill any that aren't set in with defaults:\n@@ -617,7 +617,7 @@ while (defined(my $f = shift @ARGV)) {\n }\n \n if (@rev_list_opts) {\n-\tdie \"Cannot run git format-patch from outside a repository\\n\"\n+\tdie __(\"Cannot run git format-patch from outside a repository\\n\")\n \t\tunless $repo;\n \tpush @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);\n }\n@@ -638,7 +638,7 @@ if (@files) {\n \t\tprint $_,\"\\n\" for (@files);\n \t}\n } else {\n-\tprint STDERR \"\\nNo patch files specified!\\n\\n\";\n+\tprint STDERR __(\"\\nNo patch files specified!\\n\\n\");\n \tusage();\n }\n \n@@ -730,7 +730,7 @@ EOT\n \t\t\t$sender = $1;\n \t\t\tnext;\n \t\t} elsif (/^(?:To|Cc|Bcc):/i) {\n-\t\t\tprint \"To/Cc/Bcc fields are not interpreted yet, they have been ignored\\n\";\n+\t\t\tprint __(\"To/Cc/Bcc fields are not interpreted yet, they have been ignored\\n\");\n \t\t\tnext;\n \t\t}\n \t\tprint $c2 $_;\n@@ -739,7 +739,7 @@ EOT\n \tclose $c2;\n \n \tif ($summary_empty) {\n-\t\tprint \"Summary email is empty, skipping it\\n\";\n+\t\tprint __(\"Summary email is empty, skipping it\\n\");\n \t\t$compose = -1;\n \t}\n } elsif ($annotate) {\n@@ -1314,7 +1314,7 @@ Message-Id: $message_id\n \t\t$_ = ask(__(\"Send this email? ([y]es|[n]o|[q]uit|[a]ll): \"),\n \t\t         valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,\n \t\t         default => $ask_default);\n-\t\tdie \"Send this email reply required\" unless defined $_;\n+\t\tdie __(\"Send this email reply required\") unless defined $_;\n \t\tif (/^n/i) {\n \t\t\treturn 0;\n \t\t} elsif (/^q/i) {\n@@ -1340,7 +1340,7 @@ Message-Id: $message_id\n \t} else {\n \n \t\tif (!defined $smtp_server) {\n-\t\t\tdie \"The required SMTP server is not properly defined.\"\n+\t\t\tdie __(\"The required SMTP server is not properly defined.\")\n \t\t}\n \n \t\tif ($smtp_encryption eq 'ssl') {\n@@ -1425,10 +1425,10 @@ Message-Id: $message_id\n \t\t}\n \t\tprint $header, \"\\n\";\n \t\tif ($smtp) {\n-\t\t\tprint \"Result: \", $smtp->code, ' ',\n+\t\t\tprint __(\"Result: \"), $smtp->code, ' ',\n \t\t\t\t($smtp->message =~ /\\n([^\\n]+\\n)$/s), \"\\n\";\n \t\t} else {\n-\t\t\tprint \"Result: OK\\n\";\n+\t\t\tprint __(\"Result: OK\\n\");\n \t\t}\n \t}\n \n@@ -1701,7 +1701,7 @@ sub apply_transfer_encoding {\n \t$message = MIME::Base64::decode($message)\n \t\tif ($from eq 'base64');\n \n-\tdie \"cannot send message as 7bit\"\n+\tdie __(\"cannot send message as 7bit\")\n \t\tif ($to eq '7bit' and $message =~ /[^[:ascii:]]/);\n \treturn $message\n \t\tif ($to eq '7bit' or $to eq '8bit');\n@@ -1709,7 +1709,7 @@ sub apply_transfer_encoding {\n \t\tif ($to eq 'quoted-printable');\n \treturn MIME::Base64::encode($message, \"\\n\")\n \t\tif ($to eq 'base64');\n-\tdie \"invalid transfer encoding\";\n+\tdie __(\"invalid transfer encoding\");\n }\n \n sub unique_email_list {\n-- \n2.7.4\n\n"},{"id":"303717","messageId":"20161010125449.7929-14-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 13/14] i18n: send-email: mark string with interpolation for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:48Z","receivedAt":"2016-10-10T12:56:37Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark warnings, errors and other messages that are interpolated for\ntranslation.\n\nWe call sprintf() before calling die() and in few other circumstances in\norder to replace the values on the placeholders.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-send-email.perl | 90 ++++++++++++++++++++++++++++-------------------------\n 1 file changed, 48 insertions(+), 42 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 982c6c0..5c01425 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -279,10 +279,13 @@ sub signal_handler {\n \t# tmp files from --compose\n \tif (defined $compose_filename) {\n \t\tif (-e $compose_filename) {\n-\t\t\tprint \"'$compose_filename' contains an intermediate version of the email you were composing.\\n\";\n+\t\t\tprintf __(\"'%s' contains an intermediate version \".\n+\t\t\t\t  \"of the email you were composing.\\n\"),\n+\t\t\t\t  $compose_filename;\n \t\t}\n \t\tif (-e ($compose_filename . \".final\")) {\n-\t\t\tprint \"'$compose_filename.final' contains the composed email.\\n\"\n+\t\t\tprintf __(\"'%s.final' contains the composed email.\\n\"),\n+\t\t\t\t  $compose_filename;\n \t\t}\n \t}\n \n@@ -431,7 +434,7 @@ $smtp_encryption = '' unless (defined $smtp_encryption);\n my(%suppress_cc);\n if (@suppress_cc) {\n \tforeach my $entry (@suppress_cc) {\n-\t\tdie \"Unknown --suppress-cc field: '$entry'\\n\"\n+\t\tdie sprintf(__(\"Unknown --suppress-cc field: '%s'\\n\"), $entry)\n \t\t\tunless $entry =~ /^(?:all|cccmd|cc|author|self|sob|body|bodycc)$/;\n \t\t$suppress_cc{$entry} = 1;\n \t}\n@@ -460,7 +463,7 @@ my $confirm_unconfigured = !defined $confirm;\n if ($confirm_unconfigured) {\n \t$confirm = scalar %suppress_cc ? 'compose' : 'auto';\n };\n-die \"Unknown --confirm setting: '$confirm'\\n\"\n+die sprintf(__(\"Unknown --confirm setting: '%s'\\n\"), $confirm)\n \tunless $confirm =~ /^(?:auto|cc|compose|always|never)/;\n \n # Debugging, print out the suppressions.\n@@ -492,16 +495,16 @@ my %aliases;\n sub parse_sendmail_alias {\n \tlocal $_ = shift;\n \tif (/\"/) {\n-\t\tprint STDERR \"warning: sendmail alias with quotes is not supported: $_\\n\";\n+\t\tprintf STDERR __(\"warning: sendmail alias with quotes is not supported: %s\\n\"), $_;\n \t} elsif (/:include:/) {\n-\t\tprint STDERR \"warning: `:include:` not supported: $_\\n\";\n+\t\tprintf STDERR __(\"warning: `:include:` not supported: %s\\n\"), $_;\n \t} elsif (/[\\/|]/) {\n-\t\tprint STDERR \"warning: `/file` or `|pipe` redirection not supported: $_\\n\";\n+\t\tprintf STDERR __(\"warning: `/file` or `|pipe` redirection not supported: %s\\n\"), $_;\n \t} elsif (/^(\\S+?)\\s*:\\s*(.+)$/) {\n \t\tmy ($alias, $addr) = ($1, $2);\n \t\t$aliases{$alias} = [ split_addrs($addr) ];\n \t} else {\n-\t\tprint STDERR \"warning: sendmail line is not recognized: $_\\n\";\n+\t\tprintf STDERR __(\"warning: sendmail line is not recognized: %s\\n\"), $_;\n \t}\n }\n \n@@ -582,13 +585,12 @@ sub is_format_patch_arg {\n \t\tif (defined($format_patch)) {\n \t\t\treturn $format_patch;\n \t\t}\n-\t\tdie(<<EOF);\n-File '$f' exists but it could also be the range of commits\n+\t\tdie sprintf(__(\n+\"File '%s' exists but it could also be the range of commits\n to produce patches for.  Please disambiguate by...\n \n-    * Saying \"./$f\" if you mean a file; or\n-    * Giving --format-patch option if you mean a range.\n-EOF\n+    * Saying \\\"./%s\\\" if you mean a file; or\n+    * Giving --format-patch option if you mean a range.\"), $f, $f);\n \t} catch Git::Error::Command with {\n \t\t# Not a valid revision.  Treat it as a filename.\n \t\treturn 0;\n@@ -604,7 +606,7 @@ while (defined(my $f = shift @ARGV)) {\n \t\t@ARGV = ();\n \t} elsif (-d $f and !is_format_patch_arg($f)) {\n \t\topendir my $dh, $f\n-\t\t\tor die \"Failed to opendir $f: $!\";\n+\t\t\tor die sprintf(__(\"Failed to opendir %s: %s\"), $f, $!);\n \n \t\tpush @files, grep { -f $_ } map { catfile($f, $_) }\n \t\t\t\tsort readdir $dh;\n@@ -628,7 +630,8 @@ if ($validate) {\n \tforeach my $f (@files) {\n \t\tunless (-p $f) {\n \t\t\tmy $error = validate_patch($f);\n-\t\t\t$error and die \"fatal: $f: $error\\nwarning: no patches were sent\\n\";\n+\t\t\t$error and die sprintf(__(\"fatal: %s: %s\\nwarning: no patches were sent\\n\"),\n+\t\t\t\t\t\t  $f, $error);\n \t\t}\n \t}\n }\n@@ -651,7 +654,7 @@ sub get_patch_subject {\n \t\treturn \"GIT: $1\\n\";\n \t}\n \tclose $fh;\n-\tdie \"No subject line in $fn ?\";\n+\tdie sprintf(__(\"No subject line in %s ?\"), $fn);\n }\n \n if ($compose) {\n@@ -661,7 +664,7 @@ if ($compose) {\n \t\ttempfile(\".gitsendemail.msg.XXXXXX\", DIR => $repo->repo_path()) :\n \t\ttempfile(\".gitsendemail.msg.XXXXXX\", DIR => \".\"))[1];\n \topen my $c, \">\", $compose_filename\n-\t\tor die \"Failed to open for writing $compose_filename: $!\";\n+\t\tor die sprintf(__(\"Failed to open for writing %s: %s\"), $compose_filename, $!);\n \n \n \tmy $tpl_sender = $sender || $repoauthor || $repocommitter || '';\n@@ -692,10 +695,10 @@ EOT\n \t}\n \n \topen my $c2, \">\", $compose_filename . \".final\"\n-\t\tor die \"Failed to open $compose_filename.final : \" . $!;\n+\t\tor die sprintf(__(\"Failed to open %s.final : %s\"), $compose_filename, $!);\n \n \topen $c, \"<\", $compose_filename\n-\t\tor die \"Failed to open $compose_filename : \" . $!;\n+\t\tor die sprintf(__(\"Failed to open %s : %s\"), $compose_filename, $!);\n \n \tmy $need_8bit_cte = file_has_nonascii($compose_filename);\n \tmy $in_body = 0;\n@@ -769,7 +772,9 @@ sub ask {\n \t\t\treturn $resp;\n \t\t}\n \t\tif ($confirm_only) {\n-\t\t\tmy $yesno = $term->readline(\"Are you sure you want to use <$resp> [y/N]? \");\n+\t\t\tmy $yesno = $term->readline(\n+\t\t\t\t# TRANSLATORS: please keep [y/N] as is.\n+\t\t\t\tsprintf(__(\"Are you sure you want to use <%s> [y/N]? \"), $resp));\n \t\t\tif (defined $yesno && $yesno =~ /y/i) {\n \t\t\t\treturn $resp;\n \t\t\t}\n@@ -811,9 +816,9 @@ if (!defined $auto_8bit_encoding && scalar %broken_encoding) {\n if (!$force) {\n \tfor my $f (@files) {\n \t\tif (get_patch_subject($f) =~ /\\Q*** SUBJECT HERE ***\\E/) {\n-\t\t\tdie \"Refusing to send because the patch\\n\\t$f\\n\"\n+\t\t\tdie sprintf(__(\"Refusing to send because the patch\\n\\t%s\\n\"\n \t\t\t\t. \"has the template subject '*** SUBJECT HERE ***'. \"\n-\t\t\t\t. \"Pass --force if you really want to send.\\n\";\n+\t\t\t\t. \"Pass --force if you really want to send.\\n\"), $f);\n \t\t}\n \t}\n }\n@@ -848,7 +853,7 @@ my %EXPANDED_ALIASES;\n sub expand_one_alias {\n \tmy $alias = shift;\n \tif ($EXPANDED_ALIASES{$alias}) {\n-\t\tdie \"fatal: alias '$alias' expands to itself\\n\";\n+\t\tdie sprintf(__(\"fatal: alias '%s' expands to itself\\n\"), $alias);\n \t}\n \tlocal $EXPANDED_ALIASES{$alias} = 1;\n \treturn $aliases{$alias} ? expand_aliases(@{$aliases{$alias}}) : $alias;\n@@ -910,7 +915,7 @@ sub extract_valid_address {\n sub extract_valid_address_or_die {\n \tmy $address = shift;\n \t$address = extract_valid_address($address);\n-\tdie \"error: unable to extract a valid address from: $address\\n\"\n+\tdie sprintf(__(\"error: unable to extract a valid address from: %s\\n\"), $address)\n \t\tif !$address;\n \treturn $address;\n }\n@@ -918,7 +923,7 @@ sub extract_valid_address_or_die {\n sub validate_address {\n \tmy $address = shift;\n \twhile (!extract_valid_address($address)) {\n-\t\tprint STDERR \"error: unable to extract a valid address from: $address\\n\";\n+\t\tprintf STDERR __(\"error: unable to extract a valid address from: %s\\n\"), $address;\n \t\t# TRANSLATORS: Make sure to include [q] [d] [e] in your\n \t\t# translation. The program will only accept English input\n \t\t# at this point.\n@@ -1223,7 +1228,7 @@ sub ssl_verify_params {\n \t\treturn (SSL_verify_mode => SSL_VERIFY_PEER(),\n \t\t\tSSL_ca_file => $smtp_ssl_cert_path);\n \t} else {\n-\t\tdie \"CA path \\\"$smtp_ssl_cert_path\\\" does not exist\";\n+\t\tdie sprintf(__(\"CA path \\\"%s\\\" does not exist\"), $smtp_ssl_cert_path);\n \t}\n }\n \n@@ -1384,14 +1389,14 @@ Message-Id: $message_id\n \t\t\t\t\t# supported commands\n \t\t\t\t\t$smtp->hello($smtp_domain);\n \t\t\t\t} else {\n-\t\t\t\t\tdie \"Server does not support STARTTLS! \".$smtp->message;\n+\t\t\t\t\tdie sprintf(__(\"Server does not support STARTTLS! %s\"), $smtp->message);\n \t\t\t\t}\n \t\t\t}\n \t\t}\n \n \t\tif (!$smtp) {\n-\t\t\tdie \"Unable to initialize SMTP properly. Check config and use --smtp-debug. \",\n-\t\t\t    \"VALUES: server=$smtp_server \",\n+\t\t\tdie __(\"Unable to initialize SMTP properly. Check config and use --smtp-debug.\"),\n+\t\t\t    \" VALUES: server=$smtp_server \",\n \t\t\t    \"encryption=$smtp_encryption \",\n \t\t\t    \"hello=$smtp_domain\",\n \t\t\t    defined $smtp_server_port ? \" port=$smtp_server_port\" : \"\";\n@@ -1408,10 +1413,10 @@ Message-Id: $message_id\n \t\t\t$smtp->datasend(\"$line\") or die $smtp->message;\n \t\t}\n \t\t$smtp->dataend() or die $smtp->message;\n-\t\t$smtp->code =~ /250|200/ or die \"Failed to send $subject\\n\".$smtp->message;\n+\t\t$smtp->code =~ /250|200/ or die sprintf(__(\"Failed to send %s\\n\"), $subject).$smtp->message;\n \t}\n \tif ($quiet) {\n-\t\tprintf (($dry_run ? \"Dry-\" : \"\").\"Sent %s\\n\", $subject);\n+\t\tprintf($dry_run ? __(\"Dry-Sent %s\\n\") : __(\"Sent %s\\n\"), $subject);\n \t} else {\n \t\tprint($dry_run ? __(\"Dry-OK. Log says:\\n\") : __(\"OK. Log says:\\n\"));\n \t\tif (!file_name_is_absolute($smtp_server)) {\n@@ -1441,7 +1446,7 @@ $subject = $initial_subject;\n $message_num = 0;\n \n foreach my $t (@files) {\n-\topen my $fh, \"<\", $t or die \"can't open file $t\";\n+\topen my $fh, \"<\", $t or die sprintf(__(\"can't open file %s\"), $t);\n \n \tmy $author = undef;\n \tmy $sauthor = undef;\n@@ -1663,18 +1668,18 @@ sub recipients_cmd {\n \n \tmy @addresses = ();\n \topen my $fh, \"-|\", \"$cmd \\Q$file\\E\"\n-\t    or die \"($prefix) Could not execute '$cmd'\";\n+\t    or die sprintf(__(\"(%s) Could not execute '%s'\"), $prefix, $cmd);\n \twhile (my $address = <$fh>) {\n \t\t$address =~ s/^\\s*//g;\n \t\t$address =~ s/\\s*$//g;\n \t\t$address = sanitize_address($address);\n \t\tnext if ($address eq $sender and $suppress_cc{'self'});\n \t\tpush @addresses, $address;\n-\t\tprintf(\"($prefix) Adding %s: %s from: '%s'\\n\",\n-\t\t       $what, $address, $cmd) unless $quiet;\n+\t\tprintf(__(\"(%s) Adding %s: %s from: '%s'\\n\"),\n+\t\t       $prefix, $what, $address, $cmd) unless $quiet;\n \t\t}\n \tclose $fh\n-\t    or die \"($prefix) failed to close pipe to '$cmd'\";\n+\t    or die sprintf(__(\"(%s) failed to close pipe to '%s'\"), $prefix, $cmd);\n \treturn @addresses;\n }\n \n@@ -1728,10 +1733,10 @@ sub unique_email_list {\n sub validate_patch {\n \tmy $fn = shift;\n \topen(my $fh, '<', $fn)\n-\t\tor die \"unable to open $fn: $!\\n\";\n+\t\tor die sprintf(__(\"unable to open %s: %s\\n\"), $fn, $!);\n \twhile (my $line = <$fh>) {\n \t\tif (length($line) > 998) {\n-\t\t\treturn \"$.: patch contains a line longer than 998 characters\";\n+\t\t\treturn sprintf(__(\"%s: patch contains a line longer than 998 characters\"), $.);\n \t\t}\n \t}\n \treturn;\n@@ -1747,10 +1752,11 @@ sub handle_backup {\n \t    (substr($file, 0, $lastlen) eq $last) &&\n \t    ($suffix = substr($file, $lastlen)) !~ /^[a-z0-9]/i) {\n \t\tif (defined $known_suffix && $suffix eq $known_suffix) {\n-\t\t\tprint \"Skipping $file with backup suffix '$known_suffix'.\\n\";\n+\t\t\tprintf(__(\"Skipping %s with backup suffix '%s'.\\n\"), $file, $known_suffix);\n \t\t\t$skip = 1;\n \t\t} else {\n-\t\t\tmy $answer = ask(\"Do you really want to send $file? (y|N): \",\n+\t\t\t# TRANSLATORS: please keep \"[y|N]\" as is.\n+\t\t\tmy $answer = ask(sprintf(__(\"Do you really want to send %s? [y|N]: \"), $file),\n \t\t\t\t\t valid_re => qr/^(?:y|n)/i,\n \t\t\t\t\t default => 'n');\n \t\t\t$skip = ($answer ne 'y');\n@@ -1778,7 +1784,7 @@ sub handle_backup_files {\n sub file_has_nonascii {\n \tmy $fn = shift;\n \topen(my $fh, '<', $fn)\n-\t\tor die \"unable to open $fn: $!\\n\";\n+\t\tor die sprintf(__(\"unable to open %s: %s\\n\"), $fn, $!);\n \twhile (my $line = <$fh>) {\n \t\treturn 1 if $line =~ /[^[:ascii:]]/;\n \t}\n@@ -1788,7 +1794,7 @@ sub file_has_nonascii {\n sub body_or_subject_has_nonascii {\n \tmy $fn = shift;\n \topen(my $fh, '<', $fn)\n-\t\tor die \"unable to open $fn: $!\\n\";\n+\t\tor die sprintf(__(\"unable to open %s: %s\\n\"), $fn, $!);\n \twhile (my $line = <$fh>) {\n \t\tlast if $line =~ /^$/;\n \t\treturn 1 if $line =~ /^Subject.*[^[:ascii:]]/;\n-- \n2.7.4\n\n"},{"id":"303718","messageId":"20161010125449.7929-15-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"[PATCH v4 14/14] i18n: difftool: mark warnings for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-10T12:54:49Z","receivedAt":"2016-10-10T12:56:38Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-difftool.perl | 22 ++++++++++++----------\n 1 file changed, 12 insertions(+), 10 deletions(-)\n\ndiff --git a/git-difftool.perl b/git-difftool.perl\nindex a5790d0..8d3632e 100755\n--- a/git-difftool.perl\n+++ b/git-difftool.perl\n@@ -22,6 +22,7 @@ use File::Path qw(mkpath rmtree);\n use File::Temp qw(tempdir);\n use Getopt::Long qw(:config pass_through);\n use Git;\n+use Git::I18N;\n \n sub usage\n {\n@@ -122,7 +123,7 @@ sub setup_dir_diff\n \tmy $i = 0;\n \twhile ($i < $#rawdiff) {\n \t\tif ($rawdiff[$i] =~ /^::/) {\n-\t\t\twarn << 'EOF';\n+\t\t\twarn __ <<'EOF';\n Combined diff formats ('-c' and '--cc') are not supported in\n directory diff mode ('-d' and '--dir-diff').\n EOF\n@@ -338,7 +339,7 @@ sub main\n \t\tif (length($opts{difftool_cmd}) > 0) {\n \t\t\t$ENV{GIT_DIFF_TOOL} = $opts{difftool_cmd};\n \t\t} else {\n-\t\t\tprint \"No <tool> given for --tool=<tool>\\n\";\n+\t\t\tprint __(\"No <tool> given for --tool=<tool>\\n\");\n \t\t\tusage(1);\n \t\t}\n \t}\n@@ -346,7 +347,7 @@ sub main\n \t\tif (length($opts{extcmd}) > 0) {\n \t\t\t$ENV{GIT_DIFFTOOL_EXTCMD} = $opts{extcmd};\n \t\t} else {\n-\t\t\tprint \"No <cmd> given for --extcmd=<cmd>\\n\";\n+\t\t\tprint __(\"No <cmd> given for --extcmd=<cmd>\\n\");\n \t\t\tusage(1);\n \t\t}\n \t}\n@@ -419,11 +420,11 @@ sub dir_diff\n \t\t}\n \n \t\tif (exists $wt_modified{$file} and exists $tmp_modified{$file}) {\n-\t\t\tmy $errmsg = \"warning: Both files modified: \";\n-\t\t\t$errmsg .= \"'$workdir/$file' and '$b/$file'.\\n\";\n-\t\t\t$errmsg .= \"warning: Working tree file has been left.\\n\";\n-\t\t\t$errmsg .= \"warning:\\n\";\n-\t\t\twarn $errmsg;\n+\t\t\twarn sprintf(__(\n+\t\t\t\t\"warning: Both files modified:\\n\" .\n+\t\t\t\t\"'%s/%s' and '%s/%s'.\\n\" .\n+\t\t\t\t\"warning: Working tree file has been left.\\n\" .\n+\t\t\t\t\"warning:\\n\"), $workdir, $file, $b, $file);\n \t\t\t$error = 1;\n \t\t} elsif (exists $tmp_modified{$file}) {\n \t\t\tmy $mode = stat(\"$b/$file\")->mode;\n@@ -435,8 +436,9 @@ sub dir_diff\n \t\t}\n \t}\n \tif ($error) {\n-\t\twarn \"warning: Temporary files exist in '$tmpdir'.\\n\";\n-\t\twarn \"warning: You may want to cleanup or recover these.\\n\";\n+\t\twarn sprintf(__(\n+\t\t\t\"warning: Temporary files exist in '%s'.\\n\" .\n+\t\t\t\"warning: You may want to cleanup or recover these.\\n\"), $tmpdir);\n \t\texit(1);\n \t} else {\n \t\texit_cleanup($tmpdir, $rc);\n-- \n2.7.4\n\n"},{"id":"304406","messageId":"xmqqy41kkxzd.fsf@gitster.mtv.corp.google.com","threadId":"44227","inReplyTo":"20161010125449.7929-2-vascomalmeida@sapo.pt","subject":"Re: [PATCH v4 01/14] i18n: add--interactive: mark strings for translation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-19T18:14:14Z","receivedAt":"2016-10-19T18:14:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Vasco Almeida <vascomalmeida@sapo.pt> writes:\n\n>  \t} else {\n> -\t\tprint \"No untracked files.\\n\";\n> +\t\tprint __(\"No untracked files.\\n\");\n>  \t}\n\nNot a big deal, but this makes me wonder if we want to do this\ninstead\n\n\t\tprint __(\"No untracked files.\") . \"\\n\";\n\nso that translators do not have to remember to keep the final LF.\n\nIt seems there are some more hits of strings that end with \"\\n\"\ninside __(...) in this patch, so it probably is OK.\n"},{"id":"304407","messageId":"xmqqtwc8kwqz.fsf@gitster.mtv.corp.google.com","threadId":"44227","inReplyTo":"20161010125449.7929-6-vascomalmeida@sapo.pt","subject":"Re: [PATCH v4 05/14] i18n: add--interactive: mark plural strings","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-19T18:40:52Z","receivedAt":"2016-10-19T18:41:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Vasco Almeida <vascomalmeida@sapo.pt> writes:\n\n> @@ -669,12 +669,18 @@ sub status_cmd {\n>  sub say_n_paths {\n>  \tmy $did = shift @_;\n>  \tmy $cnt = scalar @_;\n> -\tprint \"$did \";\n> -\tif (1 < $cnt) {\n> -\t\tprint \"$cnt paths\\n\";\n> -\t}\n> -\telse {\n> -\t\tprint \"one path\\n\";\n> +\tif ($did eq 'added') {\n> +\t\tprintf(__n(\"added %d path\\n\", \"added %d paths\\n\",\n> +\t\t\t   $cnt), $cnt);\n> +\t} elsif ($did eq 'updated') {\n> +\t\tprintf(__n(\"updated %d path\\n\", \"updated %d paths\\n\",\n> +\t\t\t   $cnt), $cnt);\n> +\t} elsif ($did eq 'reverted') {\n> +\t\tprintf(__n(\"reverted %d path\\n\", \"reverted %d paths\\n\",\n> +\t\t\t   $cnt), $cnt);\n> +\t} else {\n> +\t\tprintf(__n(\"touched %d path\\n\", \"touched %d paths\\n\",\n> +\t\t\t   $cnt), $cnt);\n>  \t}\n>  }\n\nNice to see you covered all verbs currently in use and then\nfuture-proofed by adding a fallback \"touched\" here.\n\nThanks.\n\n"},{"id":"304472","messageId":"1476980461.14459.10.camel@sapo.pt","threadId":"44227","inReplyTo":"xmqqy41kkxzd.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v4 01/14] i18n: add--interactive: mark strings for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-20T16:21:01Z","receivedAt":"2016-10-20T16:21:14Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"A Qua, 19-10-2016 às 11:14 -0700, Junio C Hamano escreveu:\n> Vasco Almeida <vascomalmeida@sapo.pt> writes:\n> \n> > \n> >  \t} else {\n> > -\t\tprint \"No untracked files.\\n\";\n> > +\t\tprint __(\"No untracked files.\\n\");\n> >  \t}\n> \n> Not a big deal, but this makes me wonder if we want to do this\n> instead\n> \n> \t\tprint __(\"No untracked files.\") . \"\\n\";\n> \n> so that translators do not have to remember to keep the final LF.\n\nThis can be a good idea. On the other hand, I think translators are\ncautious to not forget the final LF since there is a lot of them from C\nsource. Also I think msgfmt checks if English source and translation\nboth end with newline or not. So if a translator forgets to put a \\n\nthen msgfmt would return an error. If it is not the translator to find\nthe error herself, someone else will, like the Translation coordinator.\n\nI will leave this patch as is.\n\nhttps://www.gnu.org/software/gettext/FAQ.html#newline\n"},{"id":"304474","messageId":"xmqqeg3bhts7.fsf@gitster.mtv.corp.google.com","threadId":"44227","inReplyTo":"1476980461.14459.10.camel@sapo.pt","subject":"Re: [PATCH v4 01/14] i18n: add--interactive: mark strings for translation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-20T16:25:28Z","receivedAt":"2016-10-20T16:25:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Vasco Almeida <vascomalmeida@sapo.pt> writes:\n\n>> Not a big deal, but this makes me wonder if we want to do this\n>> instead ...\n\nFor future reference (for others as well), when I say \"makes me\nwonder\" or \"I wonder\", I am never demanding to change what the\noriginal author wrote.  I just am trying to see that pros-and-cons\nhave been considered already.\n\n> ... Also I think msgfmt checks if English source and translation\n> both end with newline or not.\n\nThat is a good enough safety belt to me.\n\n> I will leave this patch as is.\n\nYup.  Thanks.\n"},{"id":"304475","messageId":"1476980984.14459.14.camel@sapo.pt","threadId":"44227","inReplyTo":"xmqqtwc8kwqz.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v4 05/14] i18n: add--interactive: mark plural strings","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-20T16:29:44Z","receivedAt":"2016-10-20T16:29:54Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"A Qua, 19-10-2016 às 11:40 -0700, Junio C Hamano escreveu:\n> Vasco Almeida <vascomalmeida@sapo.pt> writes:\n> \n> > \n> > @@ -669,12 +669,18 @@ sub status_cmd {\n> >  sub say_n_paths {\n> >  \tmy $did = shift @_;\n> >  \tmy $cnt = scalar @_;\n> > -\tprint \"$did \";\n> > -\tif (1 < $cnt) {\n> > -\t\tprint \"$cnt paths\\n\";\n> > -\t}\n> > -\telse {\n> > -\t\tprint \"one path\\n\";\n> > +\tif ($did eq 'added') {\n> > +\t\tprintf(__n(\"added %d path\\n\", \"added %d paths\\n\",\n> > +\t\t\t   $cnt), $cnt);\n> > +\t} elsif ($did eq 'updated') {\n> > +\t\tprintf(__n(\"updated %d path\\n\", \"updated %d\n> > paths\\n\",\n> > +\t\t\t   $cnt), $cnt);\n> > +\t} elsif ($did eq 'reverted') {\n> > +\t\tprintf(__n(\"reverted %d path\\n\", \"reverted %d\n> > paths\\n\",\n> > +\t\t\t   $cnt), $cnt);\n> > +\t} else {\n> > +\t\tprintf(__n(\"touched %d path\\n\", \"touched %d\n> > paths\\n\",\n> > +\t\t\t   $cnt), $cnt);\n> >  \t}\n> >  }\n> \n> Nice to see you covered all verbs currently in use and then\n> future-proofed by adding a fallback \"touched\" here.\n> \n> Thanks.\n> \n\nThanks. Here I added %d to the singular sentences \"added %d path\\n\" to\navoid a Perl warning about a redundant argument in printf.\n"},{"id":"304478","messageId":"1476981335.14459.19.camel@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-6-vascomalmeida@sapo.pt","subject":"Re: [PATCH v4 05/14] i18n: add--interactive: mark plural strings","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-10-20T16:35:35Z","receivedAt":"2016-10-20T16:36:08Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"A Seg, 10-10-2016 às 12:54 +0000, Vasco Almeida escreveu:\n> @@ -70,6 +72,8 @@ Git::I18N - Perl interface to Git's Gettext localizations\n>  \n>         printf __(\"The following error occurred: %s\\n\"), $error;\n>  \n> +       printf __n(\"commited %d file\", \"commited %d files\", $files), $files;\n> +\n\nI forgot to add \\n to this example as suggested in\n<xmqqoa2ymnb1.fsf@gitster.mtv.corp.google.com>\n\nWhat should I do? Should I wait for more reviews and then send a new\nre-roll fixing this?\n"},{"id":"304482","messageId":"xmqq37jrhrob.fsf@gitster.mtv.corp.google.com","threadId":"44227","inReplyTo":"1476981335.14459.19.camel@sapo.pt","subject":"Re: [PATCH v4 05/14] i18n: add--interactive: mark plural strings","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-20T17:11:00Z","receivedAt":"2016-10-20T17:11:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Vasco Almeida <vascomalmeida@sapo.pt> writes:\n\n> A Seg, 10-10-2016 às 12:54 +0000, Vasco Almeida escreveu:\n>> @@ -70,6 +72,8 @@ Git::I18N - Perl interface to Git's Gettext localizations\n>>  \n>>         printf __(\"The following error occurred: %s\\n\"), $error;\n>>  \n>> +       printf __n(\"commited %d file\", \"commited %d files\", $files), $files;\n>> +\n>\n> I forgot to add \\n to this example as suggested in\n> <xmqqoa2ymnb1.fsf@gitster.mtv.corp.google.com>\n>\n> What should I do? Should I wait for more reviews and then send a new\n> re-roll fixing this?\n\nYou fix it up locally not to forget, in case you need a reroll, and\nwait for more reviews.  In the meantime, I'll also fix it up locally\nnot to forget ;-)  That way, if it turns out that this round is good\nenough to be the final version, people will see my fixup, and if what\nI have needs to be replaced with your new version, your fixup will\nbe in there.\n\nThanks.\n"},{"id":"304972","messageId":"xmqqmvhp7m9m.fsf@gitster.mtv.corp.google.com","threadId":"44227","inReplyTo":"20161010125449.7929-1-vascomalmeida@sapo.pt","subject":"Re: [PATCH v4 00/14] Mark strings in Perl scripts for translation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-10-27T17:08:21Z","receivedAt":"2016-10-27T17:08:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"> Vasco Almeida (14):\n>   i18n: add--interactive: mark strings for translation\n>   i18n: add--interactive: mark simple here-documents for translation\n>   i18n: add--interactive: mark strings with interpolation for\n>     translation\n>   i18n: clean.c: match string with git-add--interactive.perl\n>   i18n: add--interactive: mark plural strings\n>   i18n: add--interactive: mark patch prompt for translation\n>   i18n: add--interactive: i18n of help_patch_cmd\n>   i18n: add--interactive: mark edit_hunk_manually message for\n>     translation\n>   i18n: add--interactive: remove %patch_modes entries\n>   i18n: add--interactive: mark status words for translation\n>   i18n: send-email: mark strings for translation\n>   i18n: send-email: mark warnings and errors for translation\n>   i18n: send-email: mark string with interpolation for translation\n>   i18n: difftool: mark warnings for translation\n\nIt seems that nobody has anything to say on this series, either\npositive or negative?\n\nThe topic has been in \"Waiting for review\" pile but I'll mark it as\n\"Will merge to 'next'\" unless I hear otherwise within a few days\n(positives may make it faster, negatives may require a reroll).\n\nThanks.\n\n\n"},{"id":"305486","messageId":"1478534673.29048.12.camel@sapo.pt","threadId":"44227","inReplyTo":"20161010125449.7929-9-vascomalmeida@sapo.pt","subject":"Re: [PATCH v4 08/14] i18n: add--interactive: mark edit_hunk_manually message for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-07T16:04:33Z","receivedAt":"2016-11-07T16:04:44Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"A Seg, 10-10-2016 às 12:54 +0000, Vasco Almeida escreveu:\n> diff --git a/git-add--interactive.perl b/git-add--interactive.perl\n> index 045b847..861f7b0 100755\n> --- a/git-add--interactive.perl\n> +++ b/git-add--interactive.perl\n> @@ -1058,6 +1058,30 @@ sub color_diff {\n>         } @_;\n>  }\n>  \n> +my %edit_hunk_manually_modes = (\n> +       stage => N__(\n> +\"# If the patch applies cleanly, the edited hunk will immediately be\n> +# marked for staging.\"),\n> +       stash => N__(\n> +\"# If the patch applies cleanly, the edited hunk will immediately be\n> +# marked for stashing.\"),\n> +       reset_head => N__(\n> +\"# If the patch applies cleanly, the edited hunk will immediately be\n> +# marked for unstaging.\"),\n> +       reset_nothead => N__(\n> +\"# If the patch applies cleanly, the edited hunk will immediately be\n> +# marked for applying.\"),\n> +       checkout_index => N__(\n> +\"# If the patch applies cleanly, the edited hunk will immediately be\n> +# marked for discarding\"),\n> +       checkout_head => N__(\n> +\"# If the patch applies cleanly, the edited hunk will immediately be\n> +# marked for discarding.\"),\n> +       checkout_nothead => N__(\n> +\"# If the patch applies cleanly, the edited hunk will immediately be\n> +# marked for applying.\"),\n> +);\n> +\n\nI think marking strings comment with '#' for translation is not the\nbest thing because there is a change that a translator will miss to\ncomment a line. I will change this to mark only the text and then, at\nrun time, prefix comment chars to that text.\n\n>  sub edit_hunk_manually {\n>         my ($oldtext) = @_;\n>  \n> @@ -1065,22 +1089,21 @@ sub edit_hunk_manually {\n>         my $fh;\n>         open $fh, '>', $hunkfile\n>                 or die sprintf(__(\"failed to open hunk edit file for\n> writing: %s\"), $!);\n> -       print $fh \"# Manual hunk edit mode -- see bottom for a quick\n> guide\\n\";\n> +       print $fh __(\"# Manual hunk edit mode -- see bottom for a\n> quick guide\\n\");\n\nHere too.\n\n>         print $fh @$oldtext;\n> -       my $participle = $patch_mode_flavour{PARTICIPLE};\n>         my $is_reverse = $patch_mode_flavour{IS_REVERSE};\n>         my ($remove_plus, $remove_minus) = $is_reverse ? ('-', '+') :\n> ('+', '-');\n> -       print $fh <<EOF;\n> -# ---\n> -# To remove '$remove_minus' lines, make them ' ' lines (context).\n> -# To remove '$remove_plus' lines, delete them.\n> +       print $fh sprintf(__(\n> +\"# ---\n> +# To remove '%s' lines, make them ' ' lines (context).\n> +# To remove '%s' lines, delete them.\n>  # Lines starting with # will be removed.\n> -#\n> -# If the patch applies cleanly, the edited hunk will immediately be\n> -# marked for $participle. If it does not apply cleanly, you will be\n> given\n> +#\\n\"), $remove_minus, $remove_plus),\n> +__($edit_hunk_manually_modes{$patch_mode}), __(\n> +# TRANSLATORS: 'it' refers to the patch mentioned in the previous\n> messages.\n> +\" If it does not apply cleanly, you will be given\n>  # an opportunity to edit again. If all lines of the hunk are\n> removed,\n> -# then the edit is aborted and the hunk is left unchanged.\n> -EOF\n> +# then the edit is aborted and the hunk is left unchanged.\\n\");\n\nAnd here too.\nCurrently this joins the two sentences/parts in the same line like so\n\n# If the patch applies cleanly, the edited hunk will immediately be\n# marked for staging. If it does not apply cleanly, you will be given\n# an opportunity to edit again. If all lines of the hunk are removed,\n# then the edit is aborted and the hunk is left unchanged.\n\nBut since the translator translates each sentence separately, it is\nhard to align them properly to not make lines too long. Hence I am\nconsidering to break each sentence to start on its own line.\n"},{"id":"305541","messageId":"20161108120823.11204-1-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161005172110.30801-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 00/16] Mark strings in Perl scripts for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:07Z","receivedAt":"2016-11-08T12:11:53Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark messages in some perl scripts for translation.\n\nIn these series v5:\n- Add and use a subroutine to comment lines. This way we can mark strings\n  for translation without including the comment char within them.\n- Mark for translation a message for the user when she is composing an\n  e-mail in git-send-email.perl.\n\nInterdiff included below.\n\n\nVasco Almeida (16):\n  Git.pm: add subroutines for commenting lines\n  i18n: add--interactive: mark strings for translation\n  i18n: add--interactive: mark simple here-documents for translation\n  i18n: add--interactive: mark strings with interpolation for\n    translation\n  i18n: clean.c: match string with git-add--interactive.perl\n  i18n: add--interactive: mark plural strings\n  i18n: add--interactive: mark patch prompt for translation\n  i18n: add--interactive: i18n of help_patch_cmd\n  i18n: add--interactive: mark edit_hunk_manually message for\n    translation\n  i18n: add--interactive: remove %patch_modes entries\n  i18n: add--interactive: mark status words for translation\n  i18n: send-email: mark strings for translation\n  i18n: send-email: mark warnings and errors for translation\n  i18n: send-email: mark string with interpolation for translation\n  i18n: send-email: mark composing message for translation\n  i18n: difftool: mark warnings for translation\n\n Makefile                  |   3 +-\n builtin/clean.c           |  10 +-\n git-add--interactive.perl | 329 ++++++++++++++++++++++++++++++----------------\n git-difftool.perl         |  22 ++--\n git-send-email.perl       | 192 ++++++++++++++-------------\n perl/Git.pm               |  23 ++++\n perl/Git/I18N.pm          |  19 ++-\n t/t0202/test.pl           |  14 +-\n 8 files changed, 391 insertions(+), 221 deletions(-)\n\n-- >8 --\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 4754104..56e6889 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -1039,26 +1039,26 @@ sub color_diff {\n \n my %edit_hunk_manually_modes = (\n \tstage => N__(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for staging.\"),\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for staging.\"),\n \tstash => N__(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for stashing.\"),\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for stashing.\"),\n \treset_head => N__(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for unstaging.\"),\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for unstaging.\"),\n \treset_nothead => N__(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for applying.\"),\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for applying.\"),\n \tcheckout_index => N__(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for discarding\"),\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for discarding\"),\n \tcheckout_head => N__(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for discarding.\"),\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for discarding.\"),\n \tcheckout_nothead => N__(\n-\"# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for applying.\"),\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for applying.\"),\n );\n \n sub edit_hunk_manually {\n@@ -1068,21 +1068,22 @@ sub edit_hunk_manually {\n \tmy $fh;\n \topen $fh, '>', $hunkfile\n \t\tor die sprintf(__(\"failed to open hunk edit file for writing: %s\"), $!);\n-\tprint $fh __(\"# Manual hunk edit mode -- see bottom for a quick guide\\n\");\n+\tprint $fh Git::comment_lines __(\"Manual hunk edit mode -- see bottom for a quick guide\\n\");\n \tprint $fh @$oldtext;\n \tmy $is_reverse = $patch_mode_flavour{IS_REVERSE};\n \tmy ($remove_plus, $remove_minus) = $is_reverse ? ('-', '+') : ('+', '-');\n-\tprint $fh sprintf(__(\n-\"# ---\n-# To remove '%s' lines, make them ' ' lines (context).\n-# To remove '%s' lines, delete them.\n-# Lines starting with # will be removed.\n-#\\n\"), $remove_minus, $remove_plus),\n-__($edit_hunk_manually_modes{$patch_mode}), __(\n+\tmy $comment_line_char = Git::config(\"core.commentchar\") || '#';\n+\tprint $fh Git::comment_lines sprintf(__(\n+\"---\n+To remove '%s' lines, make them ' ' lines (context).\n+To remove '%s' lines, delete them.\n+Lines starting with %s will be removed.\n+\\n\"), $remove_minus, $remove_plus, $comment_line_char) .\n+__($edit_hunk_manually_modes{$patch_mode}) .\"\\n\". __(\n # TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.\n-\" If it does not apply cleanly, you will be given\n-# an opportunity to edit again. If all lines of the hunk are removed,\n-# then the edit is aborted and the hunk is left unchanged.\\n\");\n+\"If it does not apply cleanly, you will be given an opportunity to\n+edit again.  If all lines of the hunk are removed, then the edit is\n+aborted and the hunk is left unchanged.\\n\");\n \tclose $fh;\n \n \tchomp(my $editor = run_cmd_pipe(qw(git var GIT_EDITOR)));\n@@ -1094,7 +1095,7 @@ __($edit_hunk_manually_modes{$patch_mode}), __(\n \n \topen $fh, '<', $hunkfile\n \t\tor die sprintf(__(\"failed to open hunk edit file for reading: %s\"), $!);\n-\tmy @newtext = grep { !/^#/ } <$fh>;\n+\tmy @newtext = grep { !/^$comment_line_char/ } <$fh>;\n \tclose $fh;\n \tunlink $hunkfile;\n \ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 5c01425..bbeb9fb 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -671,18 +671,20 @@ if ($compose) {\n \tmy $tpl_subject = $initial_subject || '';\n \tmy $tpl_reply_to = $initial_reply_to || '';\n \n-\tprint $c <<EOT;\n+\tprint $c <<EOT1, Git::prefix_lines(\"GIT: \", __ <<EOT2), <<EOT3;\n From $tpl_sender # This line is ignored.\n-GIT: Lines beginning in \"GIT:\" will be removed.\n-GIT: Consider including an overall diffstat or table of contents\n-GIT: for the patch you are writing.\n-GIT:\n-GIT: Clear the body content if you don't wish to send a summary.\n+EOT1\n+Lines beginning in \"GIT:\" will be removed.\n+Consider including an overall diffstat or table of contents\n+for the patch you are writing.\n+\n+Clear the body content if you don't wish to send a summary.\n+EOT2\n From: $tpl_sender\n Subject: $tpl_subject\n In-Reply-To: $tpl_reply_to\n \n-EOT\n+EOT3\n \tfor my $f (@files) {\n \t\tprint $c get_patch_subject($f);\n \t}\ndiff --git a/perl/Git.pm b/perl/Git.pm\nindex b273282..17be59f 100644\n--- a/perl/Git.pm\n+++ b/perl/Git.pm\n@@ -1438,6 +1438,29 @@ sub END {\n \n } # %TEMP_* Lexical Context\n \n+=item prefix_lines ( PREFIX, STRING )\n+\n+Prefixes lines in C<STRING> with C<PREFIX>.\n+\n+=cut\n+\n+sub prefix_lines {\n+\tmy ($prefix, $string) = @_;\n+\t$string =~ s/^/$prefix/mg;\n+\treturn $string;\n+}\n+\n+=item comment_lines ( STRING )\n+\n+Comments lines following core.commentchar configuration.\n+\n+=cut\n+\n+sub comment_lines {\n+\tmy $comment_line_char = config(\"core.commentchar\") || '#';\n+\treturn prefix_lines(\"$comment_line_char \", @_);\n+}\n+\n =back\n \n =head1 ERROR HANDLING\ndiff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm\nindex 32c4568..c41425c 100644\n--- a/perl/Git/I18N.pm\n+++ b/perl/Git/I18N.pm\n@@ -74,7 +74,7 @@ Git::I18N - Perl interface to Git's Gettext localizations\n \n \tprintf __(\"The following error occurred: %s\\n\"), $error;\n \n-\tprintf __n(\"commited %d file\", \"commited %d files\", $files), $files;\n+\tprintf __n(\"commited %d file\\n\", \"commited %d files\\n\", $files), $files;\n \n \n =head1 DESCRIPTION\n@@ -95,12 +95,14 @@ L<Locale::Messages>'s gettext function if all goes well, otherwise our\n passthrough fallback function.\n \n =head2 __n($$$)\n+\n L<Locale::Messages>'s ngettext function or passthrough fallback function.\n \n =head2 N__($)\n-No-op that only returns its argument. Use this if you want xgettext to\n-extract the text to the pot template but do not want to trigger retrival of\n-the translation at run time.\n+\n+No-operation that only returns its argument. Use this if you want xgettext to\n+extract the text to the pot template but do not want to trigger retrival of the\n+translation at run time.\n \n =head1 AUTHOR\n \n-- >8 --\n\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305542","messageId":"20161108120823.11204-3-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 02/16] i18n: add--interactive: mark strings for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:09Z","receivedAt":"2016-11-08T12:11:59Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark simple strings (without interpolation) for translation.\n\nBrackets around first parameter of ternary operator is necessary because\notherwise xgettext fails to extract strings marked for translation from\nthe rest of the file.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 76 ++++++++++++++++++++++++++---------------------\n 1 file changed, 42 insertions(+), 34 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex ee3d81269..cf216ecb6 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -4,6 +4,7 @@ use 5.008;\n use strict;\n use warnings;\n use Git;\n+use Git::I18N;\n \n binmode(STDOUT, \":raw\");\n \n@@ -253,8 +254,9 @@ sub list_untracked {\n \trun_cmd_pipe(qw(git ls-files --others --exclude-standard --), @ARGV);\n }\n \n-my $status_fmt = '%12s %12s %s';\n-my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');\n+# TRANSLATORS: you can adjust this to align \"git add -i\" status menu\n+my $status_fmt = __('%12s %12s %s');\n+my $status_head = sprintf($status_fmt, __('staged'), __('unstaged'), __('path'));\n \n {\n \tmy $initial;\n@@ -680,7 +682,7 @@ sub update_cmd {\n \tmy @mods = list_modified('file-only');\n \treturn if (!@mods);\n \n-\tmy @update = list_and_choose({ PROMPT => 'Update',\n+\tmy @update = list_and_choose({ PROMPT => __('Update'),\n \t\t\t\t       HEADER => $status_head, },\n \t\t\t\t     @mods);\n \tif (@update) {\n@@ -692,7 +694,7 @@ sub update_cmd {\n }\n \n sub revert_cmd {\n-\tmy @update = list_and_choose({ PROMPT => 'Revert',\n+\tmy @update = list_and_choose({ PROMPT => __('Revert'),\n \t\t\t\t       HEADER => $status_head, },\n \t\t\t\t     list_modified());\n \tif (@update) {\n@@ -726,13 +728,13 @@ sub revert_cmd {\n }\n \n sub add_untracked_cmd {\n-\tmy @add = list_and_choose({ PROMPT => 'Add untracked' },\n+\tmy @add = list_and_choose({ PROMPT => __('Add untracked') },\n \t\t\t\t  list_untracked());\n \tif (@add) {\n \t\tsystem(qw(git update-index --add --), @add);\n \t\tsay_n_paths('added', @add);\n \t} else {\n-\t\tprint \"No untracked files.\\n\";\n+\t\tprint __(\"No untracked files.\\n\");\n \t}\n \tprint \"\\n\";\n }\n@@ -1166,8 +1168,14 @@ sub edit_hunk_loop {\n \t\t}\n \t\telse {\n \t\t\tprompt_yesno(\n-\t\t\t\t'Your edited hunk does not apply. Edit again '\n-\t\t\t\t. '(saying \"no\" discards!) [y/n]? '\n+\t\t\t\t# TRANSLATORS: do not translate [y/n]\n+\t\t\t\t# The program will only accept that input\n+\t\t\t\t# at this point.\n+\t\t\t\t# Consider translating (saying \"no\" discards!) as\n+\t\t\t\t# (saying \"n\" for \"no\" discards!) if the translation\n+\t\t\t\t# of the word \"no\" does not start with n.\n+\t\t\t\t__('Your edited hunk does not apply. Edit again '\n+\t\t\t\t   . '(saying \"no\" discards!) [y/n]? ')\n \t\t\t\t) or return undef;\n \t\t}\n \t}\n@@ -1213,11 +1221,11 @@ sub apply_patch_for_checkout_commit {\n \t\trun_git_apply 'apply '.$reverse, @_;\n \t\treturn 1;\n \t} elsif (!$applies_index) {\n-\t\tprint colored $error_color, \"The selected hunks do not apply to the index!\\n\";\n-\t\tif (prompt_yesno \"Apply them to the worktree anyway? \") {\n+\t\tprint colored $error_color, __(\"The selected hunks do not apply to the index!\\n\");\n+\t\tif (prompt_yesno __(\"Apply them to the worktree anyway? \")) {\n \t\t\treturn run_git_apply 'apply '.$reverse, @_;\n \t\t} else {\n-\t\t\tprint colored $error_color, \"Nothing was applied.\\n\";\n+\t\t\tprint colored $error_color, __(\"Nothing was applied.\\n\");\n \t\t\treturn 0;\n \t\t}\n \t} else {\n@@ -1237,9 +1245,9 @@ sub patch_update_cmd {\n \n \tif (!@mods) {\n \t\tif (@all_mods) {\n-\t\t\tprint STDERR \"Only binary files changed.\\n\";\n+\t\t\tprint STDERR __(\"Only binary files changed.\\n\");\n \t\t} else {\n-\t\t\tprint STDERR \"No changes.\\n\";\n+\t\t\tprint STDERR __(\"No changes.\\n\");\n \t\t}\n \t\treturn 0;\n \t}\n@@ -1247,7 +1255,7 @@ sub patch_update_cmd {\n \t\t@them = @mods;\n \t}\n \telse {\n-\t\t@them = list_and_choose({ PROMPT => 'Patch update',\n+\t\t@them = list_and_choose({ PROMPT => __('Patch update'),\n \t\t\t\t\t  HEADER => $status_head, },\n \t\t\t\t\t@mods);\n \t}\n@@ -1397,12 +1405,12 @@ sub patch_update_file {\n \t\t\t\tmy $response = $1;\n \t\t\t\tmy $no = $ix > 10 ? $ix - 10 : 0;\n \t\t\t\twhile ($response eq '') {\n-\t\t\t\t\tmy $extra = \"\";\n \t\t\t\t\t$no = display_hunks(\\@hunk, $no);\n \t\t\t\t\tif ($no < $num) {\n-\t\t\t\t\t\t$extra = \" (<ret> to see more)\";\n+\t\t\t\t\t\tprint __(\"go to which hunk (<ret> to see more)? \");\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tprint __(\"go to which hunk? \");\n \t\t\t\t\t}\n-\t\t\t\t\tprint \"go to which hunk$extra? \";\n \t\t\t\t\t$response = <STDIN>;\n \t\t\t\t\tif (!defined $response) {\n \t\t\t\t\t\t$response = '';\n@@ -1439,7 +1447,7 @@ sub patch_update_file {\n \t\t\telsif ($line =~ m|^/(.*)|) {\n \t\t\t\tmy $regex = $1;\n \t\t\t\tif ($1 eq \"\") {\n-\t\t\t\t\tprint colored $prompt_color, \"search for regex? \";\n+\t\t\t\t\tprint colored $prompt_color, __(\"search for regex? \");\n \t\t\t\t\t$regex = <STDIN>;\n \t\t\t\t\tif (defined $regex) {\n \t\t\t\t\t\tchomp $regex;\n@@ -1462,7 +1470,7 @@ sub patch_update_file {\n \t\t\t\t\t$iy++;\n \t\t\t\t\t$iy = 0 if ($iy >= $num);\n \t\t\t\t\tif ($ix == $iy) {\n-\t\t\t\t\t\terror_msg \"No hunk matches the given pattern\\n\";\n+\t\t\t\t\t\terror_msg __(\"No hunk matches the given pattern\\n\");\n \t\t\t\t\t\tlast;\n \t\t\t\t\t}\n \t\t\t\t}\n@@ -1474,7 +1482,7 @@ sub patch_update_file {\n \t\t\t\t\t$ix--;\n \t\t\t\t}\n \t\t\t\telse {\n-\t\t\t\t\terror_msg \"No previous hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No previous hunk\\n\");\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n@@ -1483,7 +1491,7 @@ sub patch_update_file {\n \t\t\t\t\t$ix++;\n \t\t\t\t}\n \t\t\t\telse {\n-\t\t\t\t\terror_msg \"No next hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No next hunk\\n\");\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n@@ -1496,13 +1504,13 @@ sub patch_update_file {\n \t\t\t\t\t}\n \t\t\t\t}\n \t\t\t\telse {\n-\t\t\t\t\terror_msg \"No previous hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No previous hunk\\n\");\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n \t\t\telsif ($line =~ /^j/) {\n \t\t\t\tif ($other !~ /j/) {\n-\t\t\t\t\terror_msg \"No next hunk\\n\";\n+\t\t\t\t\terror_msg __(\"No next hunk\\n\");\n \t\t\t\t\tnext;\n \t\t\t\t}\n \t\t\t}\n@@ -1560,18 +1568,18 @@ sub diff_cmd {\n \tmy @mods = list_modified('index-only');\n \t@mods = grep { !($_->{BINARY}) } @mods;\n \treturn if (!@mods);\n-\tmy (@them) = list_and_choose({ PROMPT => 'Review diff',\n+\tmy (@them) = list_and_choose({ PROMPT => __('Review diff'),\n \t\t\t\t     IMMEDIATE => 1,\n \t\t\t\t     HEADER => $status_head, },\n \t\t\t\t   @mods);\n \treturn if (!@them);\n-\tmy $reference = is_initial_commit() ? get_empty_tree() : 'HEAD';\n+\tmy $reference = (is_initial_commit()) ? get_empty_tree() : 'HEAD';\n \tsystem(qw(git diff -p --cached), $reference, '--',\n \t\tmap { $_->{VALUE} } @them);\n }\n \n sub quit_cmd {\n-\tprint \"Bye.\\n\";\n+\tprint __(\"Bye.\\n\");\n \texit(0);\n }\n \n@@ -1594,32 +1602,32 @@ sub process_args {\n \t\t\tif ($1 eq 'reset') {\n \t\t\t\t$patch_mode = 'reset_head';\n \t\t\t\t$patch_mode_revision = 'HEAD';\n-\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\tif ($arg ne '--') {\n \t\t\t\t\t$patch_mode_revision = $arg;\n \t\t\t\t\t$patch_mode = ($arg eq 'HEAD' ?\n \t\t\t\t\t\t       'reset_head' : 'reset_nothead');\n-\t\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\t}\n \t\t\t} elsif ($1 eq 'checkout') {\n-\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\tif ($arg eq '--') {\n \t\t\t\t\t$patch_mode = 'checkout_index';\n \t\t\t\t} else {\n \t\t\t\t\t$patch_mode_revision = $arg;\n \t\t\t\t\t$patch_mode = ($arg eq 'HEAD' ?\n \t\t\t\t\t\t       'checkout_head' : 'checkout_nothead');\n-\t\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t\t}\n \t\t\t} elsif ($1 eq 'stage' or $1 eq 'stash') {\n \t\t\t\t$patch_mode = $1;\n-\t\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t} else {\n \t\t\t\tdie \"unknown --patch mode: $1\";\n \t\t\t}\n \t\t} else {\n \t\t\t$patch_mode = 'stage';\n-\t\t\t$arg = shift @ARGV or die \"missing --\";\n+\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t}\n \t\tdie \"invalid argument $arg, expecting --\"\n \t\t    unless $arg eq \"--\";\n@@ -1641,10 +1649,10 @@ sub main_loop {\n \t\t   [ 'help', \\&help_cmd, ],\n \t);\n \twhile (1) {\n-\t\tmy ($it) = list_and_choose({ PROMPT => 'What now',\n+\t\tmy ($it) = list_and_choose({ PROMPT => __('What now'),\n \t\t\t\t\t     SINGLETON => 1,\n \t\t\t\t\t     LIST_FLAT => 4,\n-\t\t\t\t\t     HEADER => '*** Commands ***',\n+\t\t\t\t\t     HEADER => __('*** Commands ***'),\n \t\t\t\t\t     ON_EOF => \\&quit_cmd,\n \t\t\t\t\t     IMMEDIATE => 1 }, @cmd);\n \t\tif ($it) {\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305543","messageId":"20161108120823.11204-10-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 09/16] i18n: add--interactive: mark edit_hunk_manually message for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:16Z","receivedAt":"2016-11-08T12:12:02Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark message of edit_hunk_manually displayed in the editing file when\nuser chooses 'e' option.  The message had to be unfolded to allow\ntranslation of the $participle verb.\n\nSome messages end up being exactly the same for some uses cases, but\nleft it for easier change in the future, e.g., wanting to change wording\nof one particular use case.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 52 ++++++++++++++++++++++++++++++++++-------------\n 1 file changed, 38 insertions(+), 14 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 045b847cf..45653e094 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -1058,6 +1058,30 @@ sub color_diff {\n \t} @_;\n }\n \n+my %edit_hunk_manually_modes = (\n+\tstage => N__(\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for staging.\"),\n+\tstash => N__(\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for stashing.\"),\n+\treset_head => N__(\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for unstaging.\"),\n+\treset_nothead => N__(\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for applying.\"),\n+\tcheckout_index => N__(\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for discarding\"),\n+\tcheckout_head => N__(\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for discarding.\"),\n+\tcheckout_nothead => N__(\n+\"If the patch applies cleanly, the edited hunk will immediately be\n+marked for applying.\"),\n+);\n+\n sub edit_hunk_manually {\n \tmy ($oldtext) = @_;\n \n@@ -1065,22 +1089,22 @@ sub edit_hunk_manually {\n \tmy $fh;\n \topen $fh, '>', $hunkfile\n \t\tor die sprintf(__(\"failed to open hunk edit file for writing: %s\"), $!);\n-\tprint $fh \"# Manual hunk edit mode -- see bottom for a quick guide\\n\";\n+\tprint $fh Git::comment_lines __(\"Manual hunk edit mode -- see bottom for a quick guide\\n\");\n \tprint $fh @$oldtext;\n-\tmy $participle = $patch_mode_flavour{PARTICIPLE};\n \tmy $is_reverse = $patch_mode_flavour{IS_REVERSE};\n \tmy ($remove_plus, $remove_minus) = $is_reverse ? ('-', '+') : ('+', '-');\n-\tprint $fh <<EOF;\n-# ---\n-# To remove '$remove_minus' lines, make them ' ' lines (context).\n-# To remove '$remove_plus' lines, delete them.\n-# Lines starting with # will be removed.\n-#\n-# If the patch applies cleanly, the edited hunk will immediately be\n-# marked for $participle. If it does not apply cleanly, you will be given\n-# an opportunity to edit again. If all lines of the hunk are removed,\n-# then the edit is aborted and the hunk is left unchanged.\n-EOF\n+\tmy $comment_line_char = Git::config(\"core.commentchar\") || '#';\n+\tprint $fh Git::comment_lines sprintf(__(\n+\"---\n+To remove '%s' lines, make them ' ' lines (context).\n+To remove '%s' lines, delete them.\n+Lines starting with %s will be removed.\n+\\n\"), $remove_minus, $remove_plus, $comment_line_char) .\n+__($edit_hunk_manually_modes{$patch_mode}) .\"\\n\". __(\n+# TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.\n+\"If it does not apply cleanly, you will be given an opportunity to\n+edit again.  If all lines of the hunk are removed, then the edit is\n+aborted and the hunk is left unchanged.\\n\");\n \tclose $fh;\n \n \tchomp(my $editor = run_cmd_pipe(qw(git var GIT_EDITOR)));\n@@ -1092,7 +1116,7 @@ EOF\n \n \topen $fh, '<', $hunkfile\n \t\tor die sprintf(__(\"failed to open hunk edit file for reading: %s\"), $!);\n-\tmy @newtext = grep { !/^#/ } <$fh>;\n+\tmy @newtext = grep { !/^$comment_line_char/ } <$fh>;\n \tclose $fh;\n \tunlink $hunkfile;\n \n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305544","messageId":"20161108120823.11204-11-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 10/16] i18n: add--interactive: remove %patch_modes entries","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:17Z","receivedAt":"2016-11-08T12:12:03Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Remove unnecessary entries from %patch_modes. After the i18n conversion,\nthese entries are not used anymore.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 21 ---------------------\n 1 file changed, 21 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 45653e094..93cc6f557 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -106,9 +106,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-files -p',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Stage',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'staging',\n \t\tFILTER => 'file-only',\n \t\tIS_REVERSE => 0,\n \t},\n@@ -116,9 +113,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p HEAD',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Stash',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'stashing',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 0,\n \t},\n@@ -126,9 +120,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p --cached',\n \t\tAPPLY => sub { apply_patch 'apply -R --cached', @_; },\n \t\tAPPLY_CHECK => 'apply -R --cached',\n-\t\tVERB => 'Unstage',\n-\t\tTARGET => '',\n-\t\tPARTICIPLE => 'unstaging',\n \t\tFILTER => 'index-only',\n \t\tIS_REVERSE => 1,\n \t},\n@@ -136,9 +127,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -R -p --cached',\n \t\tAPPLY => sub { apply_patch 'apply --cached', @_; },\n \t\tAPPLY_CHECK => 'apply --cached',\n-\t\tVERB => 'Apply',\n-\t\tTARGET => ' to index',\n-\t\tPARTICIPLE => 'applying',\n \t\tFILTER => 'index-only',\n \t\tIS_REVERSE => 0,\n \t},\n@@ -146,9 +134,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-files -p',\n \t\tAPPLY => sub { apply_patch 'apply -R', @_; },\n \t\tAPPLY_CHECK => 'apply -R',\n-\t\tVERB => 'Discard',\n-\t\tTARGET => ' from worktree',\n-\t\tPARTICIPLE => 'discarding',\n \t\tFILTER => 'file-only',\n \t\tIS_REVERSE => 1,\n \t},\n@@ -156,9 +141,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -p',\n \t\tAPPLY => sub { apply_patch_for_checkout_commit '-R', @_ },\n \t\tAPPLY_CHECK => 'apply -R',\n-\t\tVERB => 'Discard',\n-\t\tTARGET => ' from index and worktree',\n-\t\tPARTICIPLE => 'discarding',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 1,\n \t},\n@@ -166,9 +148,6 @@ my %patch_modes = (\n \t\tDIFF => 'diff-index -R -p',\n \t\tAPPLY => sub { apply_patch_for_checkout_commit '', @_ },\n \t\tAPPLY_CHECK => 'apply',\n-\t\tVERB => 'Apply',\n-\t\tTARGET => ' to index and worktree',\n-\t\tPARTICIPLE => 'applying',\n \t\tFILTER => undef,\n \t\tIS_REVERSE => 0,\n \t},\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305545","messageId":"20161108120823.11204-2-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 01/16] Git.pm: add subroutines for commenting lines","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:08Z","receivedAt":"2016-11-08T12:12:04Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Add subroutines prefix_lines and comment_lines.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n perl/Git.pm | 23 +++++++++++++++++++++++\n 1 file changed, 23 insertions(+)\n\ndiff --git a/perl/Git.pm b/perl/Git.pm\nindex b2732822a..17be59fb7 100644\n--- a/perl/Git.pm\n+++ b/perl/Git.pm\n@@ -1438,6 +1438,29 @@ sub END {\n \n } # %TEMP_* Lexical Context\n \n+=item prefix_lines ( PREFIX, STRING )\n+\n+Prefixes lines in C<STRING> with C<PREFIX>.\n+\n+=cut\n+\n+sub prefix_lines {\n+\tmy ($prefix, $string) = @_;\n+\t$string =~ s/^/$prefix/mg;\n+\treturn $string;\n+}\n+\n+=item comment_lines ( STRING )\n+\n+Comments lines following core.commentchar configuration.\n+\n+=cut\n+\n+sub comment_lines {\n+\tmy $comment_line_char = config(\"core.commentchar\") || '#';\n+\treturn prefix_lines(\"$comment_line_char \", @_);\n+}\n+\n =back\n \n =head1 ERROR HANDLING\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305546","messageId":"20161108120823.11204-9-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 08/16] i18n: add--interactive: i18n of help_patch_cmd","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:15Z","receivedAt":"2016-11-08T12:12:07Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark help message of help_patch_cmd for translation.  The message must\nbe unfolded to be free of variables so we can have high quality\ntranslations.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 54 ++++++++++++++++++++++++++++++++++++++++-------\n 1 file changed, 46 insertions(+), 8 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex b7d382b10..045b847cf 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -1189,15 +1189,53 @@ sub edit_hunk_loop {\n \t}\n }\n \n+my %help_patch_modes = (\n+\tstage => N__(\n+\"y - stage this hunk\n+n - do not stage this hunk\n+q - quit; do not stage this hunk or any of the remaining ones\n+a - stage this hunk and all later hunks in the file\n+d - do not stage this hunk or any of the later hunks in the file\"),\n+\tstash => N__(\n+\"y - stash this hunk\n+n - do not stash this hunk\n+q - quit; do not stash this hunk or any of the remaining ones\n+a - stash this hunk and all later hunks in the file\n+d - do not stash this hunk or any of the later hunks in the file\"),\n+\treset_head => N__(\n+\"y - unstage this hunk\n+n - do not unstage this hunk\n+q - quit; do not unstage this hunk or any of the remaining ones\n+a - unstage this hunk and all later hunks in the file\n+d - do not unstage this hunk or any of the later hunks in the file\"),\n+\treset_nothead => N__(\n+\"y - apply this hunk to index\n+n - do not apply this hunk to index\n+q - quit; do not apply this hunk or any of the remaining ones\n+a - apply this hunk and all later hunks in the file\n+d - do not apply this hunk or any of the later hunks in the file\"),\n+\tcheckout_index => N__(\n+\"y - discard this hunk from worktree\n+n - do not discard this hunk from worktree\n+q - quit; do not discard this hunk or any of the remaining ones\n+a - discard this hunk and all later hunks in the file\n+d - do not discard this hunk or any of the later hunks in the file\"),\n+\tcheckout_head => N__(\n+\"y - discard this hunk from index and worktree\n+n - do not discard this hunk from index and worktree\n+q - quit; do not discard this hunk or any of the remaining ones\n+a - discard this hunk and all later hunks in the file\n+d - do not discard this hunk or any of the later hunks in the file\"),\n+\tcheckout_nothead => N__(\n+\"y - apply this hunk to index and worktree\n+n - do not apply this hunk to index and worktree\n+q - quit; do not apply this hunk or any of the remaining ones\n+a - apply this hunk and all later hunks in the file\n+d - do not apply this hunk or any of the later hunks in the file\"),\n+);\n+\n sub help_patch_cmd {\n-\tmy $verb = lc $patch_mode_flavour{VERB};\n-\tmy $target = $patch_mode_flavour{TARGET};\n-\tprint colored $help_color, <<EOF ;\n-y - $verb this hunk$target\n-n - do not $verb this hunk$target\n-q - quit; do not $verb this hunk or any of the remaining ones\n-a - $verb this hunk and all later hunks in the file\n-d - do not $verb this hunk or any of the later hunks in the file\n+\tprint colored $help_color, __($help_patch_modes{$patch_mode}), \"\\n\", __ <<EOF ;\n g - select a hunk to go to\n / - search for a hunk matching the given regex\n j - leave this hunk undecided, see next undecided hunk\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305547","messageId":"20161108120823.11204-17-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 16/16] i18n: difftool: mark warnings for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:23Z","receivedAt":"2016-11-08T12:12:09Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-difftool.perl | 22 ++++++++++++----------\n 1 file changed, 12 insertions(+), 10 deletions(-)\n\ndiff --git a/git-difftool.perl b/git-difftool.perl\nindex a5790d03a..8d3632e55 100755\n--- a/git-difftool.perl\n+++ b/git-difftool.perl\n@@ -22,6 +22,7 @@ use File::Path qw(mkpath rmtree);\n use File::Temp qw(tempdir);\n use Getopt::Long qw(:config pass_through);\n use Git;\n+use Git::I18N;\n \n sub usage\n {\n@@ -122,7 +123,7 @@ sub setup_dir_diff\n \tmy $i = 0;\n \twhile ($i < $#rawdiff) {\n \t\tif ($rawdiff[$i] =~ /^::/) {\n-\t\t\twarn << 'EOF';\n+\t\t\twarn __ <<'EOF';\n Combined diff formats ('-c' and '--cc') are not supported in\n directory diff mode ('-d' and '--dir-diff').\n EOF\n@@ -338,7 +339,7 @@ sub main\n \t\tif (length($opts{difftool_cmd}) > 0) {\n \t\t\t$ENV{GIT_DIFF_TOOL} = $opts{difftool_cmd};\n \t\t} else {\n-\t\t\tprint \"No <tool> given for --tool=<tool>\\n\";\n+\t\t\tprint __(\"No <tool> given for --tool=<tool>\\n\");\n \t\t\tusage(1);\n \t\t}\n \t}\n@@ -346,7 +347,7 @@ sub main\n \t\tif (length($opts{extcmd}) > 0) {\n \t\t\t$ENV{GIT_DIFFTOOL_EXTCMD} = $opts{extcmd};\n \t\t} else {\n-\t\t\tprint \"No <cmd> given for --extcmd=<cmd>\\n\";\n+\t\t\tprint __(\"No <cmd> given for --extcmd=<cmd>\\n\");\n \t\t\tusage(1);\n \t\t}\n \t}\n@@ -419,11 +420,11 @@ sub dir_diff\n \t\t}\n \n \t\tif (exists $wt_modified{$file} and exists $tmp_modified{$file}) {\n-\t\t\tmy $errmsg = \"warning: Both files modified: \";\n-\t\t\t$errmsg .= \"'$workdir/$file' and '$b/$file'.\\n\";\n-\t\t\t$errmsg .= \"warning: Working tree file has been left.\\n\";\n-\t\t\t$errmsg .= \"warning:\\n\";\n-\t\t\twarn $errmsg;\n+\t\t\twarn sprintf(__(\n+\t\t\t\t\"warning: Both files modified:\\n\" .\n+\t\t\t\t\"'%s/%s' and '%s/%s'.\\n\" .\n+\t\t\t\t\"warning: Working tree file has been left.\\n\" .\n+\t\t\t\t\"warning:\\n\"), $workdir, $file, $b, $file);\n \t\t\t$error = 1;\n \t\t} elsif (exists $tmp_modified{$file}) {\n \t\t\tmy $mode = stat(\"$b/$file\")->mode;\n@@ -435,8 +436,9 @@ sub dir_diff\n \t\t}\n \t}\n \tif ($error) {\n-\t\twarn \"warning: Temporary files exist in '$tmpdir'.\\n\";\n-\t\twarn \"warning: You may want to cleanup or recover these.\\n\";\n+\t\twarn sprintf(__(\n+\t\t\t\"warning: Temporary files exist in '%s'.\\n\" .\n+\t\t\t\"warning: You may want to cleanup or recover these.\\n\"), $tmpdir);\n \t\texit(1);\n \t} else {\n \t\texit_cleanup($tmpdir, $rc);\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305548","messageId":"20161108120823.11204-16-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 15/16] i18n: send-email: mark composing message for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:22Z","receivedAt":"2016-11-08T12:12:11Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"When composing an e-mail, there is a message for the user whose lines\nare beginning in \"GIT:\" that can be marked for translation.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-send-email.perl | 16 +++++++++-------\n 1 file changed, 9 insertions(+), 7 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 5c014258b..bbeb9fbf0 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -671,18 +671,20 @@ if ($compose) {\n \tmy $tpl_subject = $initial_subject || '';\n \tmy $tpl_reply_to = $initial_reply_to || '';\n \n-\tprint $c <<EOT;\n+\tprint $c <<EOT1, Git::prefix_lines(\"GIT: \", __ <<EOT2), <<EOT3;\n From $tpl_sender # This line is ignored.\n-GIT: Lines beginning in \"GIT:\" will be removed.\n-GIT: Consider including an overall diffstat or table of contents\n-GIT: for the patch you are writing.\n-GIT:\n-GIT: Clear the body content if you don't wish to send a summary.\n+EOT1\n+Lines beginning in \"GIT:\" will be removed.\n+Consider including an overall diffstat or table of contents\n+for the patch you are writing.\n+\n+Clear the body content if you don't wish to send a summary.\n+EOT2\n From: $tpl_sender\n Subject: $tpl_subject\n In-Reply-To: $tpl_reply_to\n \n-EOT\n+EOT3\n \tfor my $f (@files) {\n \t\tprint $c get_patch_subject($f);\n \t}\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305549","messageId":"20161108120823.11204-15-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 14/16] i18n: send-email: mark string with interpolation for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:21Z","receivedAt":"2016-11-08T12:12:16Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark warnings, errors and other messages that are interpolated for\ntranslation.\n\nWe call sprintf() before calling die() and in few other circumstances in\norder to replace the values on the placeholders.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-send-email.perl | 90 ++++++++++++++++++++++++++++-------------------------\n 1 file changed, 48 insertions(+), 42 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 982c6c076..5c014258b 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -279,10 +279,13 @@ sub signal_handler {\n \t# tmp files from --compose\n \tif (defined $compose_filename) {\n \t\tif (-e $compose_filename) {\n-\t\t\tprint \"'$compose_filename' contains an intermediate version of the email you were composing.\\n\";\n+\t\t\tprintf __(\"'%s' contains an intermediate version \".\n+\t\t\t\t  \"of the email you were composing.\\n\"),\n+\t\t\t\t  $compose_filename;\n \t\t}\n \t\tif (-e ($compose_filename . \".final\")) {\n-\t\t\tprint \"'$compose_filename.final' contains the composed email.\\n\"\n+\t\t\tprintf __(\"'%s.final' contains the composed email.\\n\"),\n+\t\t\t\t  $compose_filename;\n \t\t}\n \t}\n \n@@ -431,7 +434,7 @@ $smtp_encryption = '' unless (defined $smtp_encryption);\n my(%suppress_cc);\n if (@suppress_cc) {\n \tforeach my $entry (@suppress_cc) {\n-\t\tdie \"Unknown --suppress-cc field: '$entry'\\n\"\n+\t\tdie sprintf(__(\"Unknown --suppress-cc field: '%s'\\n\"), $entry)\n \t\t\tunless $entry =~ /^(?:all|cccmd|cc|author|self|sob|body|bodycc)$/;\n \t\t$suppress_cc{$entry} = 1;\n \t}\n@@ -460,7 +463,7 @@ my $confirm_unconfigured = !defined $confirm;\n if ($confirm_unconfigured) {\n \t$confirm = scalar %suppress_cc ? 'compose' : 'auto';\n };\n-die \"Unknown --confirm setting: '$confirm'\\n\"\n+die sprintf(__(\"Unknown --confirm setting: '%s'\\n\"), $confirm)\n \tunless $confirm =~ /^(?:auto|cc|compose|always|never)/;\n \n # Debugging, print out the suppressions.\n@@ -492,16 +495,16 @@ my %aliases;\n sub parse_sendmail_alias {\n \tlocal $_ = shift;\n \tif (/\"/) {\n-\t\tprint STDERR \"warning: sendmail alias with quotes is not supported: $_\\n\";\n+\t\tprintf STDERR __(\"warning: sendmail alias with quotes is not supported: %s\\n\"), $_;\n \t} elsif (/:include:/) {\n-\t\tprint STDERR \"warning: `:include:` not supported: $_\\n\";\n+\t\tprintf STDERR __(\"warning: `:include:` not supported: %s\\n\"), $_;\n \t} elsif (/[\\/|]/) {\n-\t\tprint STDERR \"warning: `/file` or `|pipe` redirection not supported: $_\\n\";\n+\t\tprintf STDERR __(\"warning: `/file` or `|pipe` redirection not supported: %s\\n\"), $_;\n \t} elsif (/^(\\S+?)\\s*:\\s*(.+)$/) {\n \t\tmy ($alias, $addr) = ($1, $2);\n \t\t$aliases{$alias} = [ split_addrs($addr) ];\n \t} else {\n-\t\tprint STDERR \"warning: sendmail line is not recognized: $_\\n\";\n+\t\tprintf STDERR __(\"warning: sendmail line is not recognized: %s\\n\"), $_;\n \t}\n }\n \n@@ -582,13 +585,12 @@ sub is_format_patch_arg {\n \t\tif (defined($format_patch)) {\n \t\t\treturn $format_patch;\n \t\t}\n-\t\tdie(<<EOF);\n-File '$f' exists but it could also be the range of commits\n+\t\tdie sprintf(__(\n+\"File '%s' exists but it could also be the range of commits\n to produce patches for.  Please disambiguate by...\n \n-    * Saying \"./$f\" if you mean a file; or\n-    * Giving --format-patch option if you mean a range.\n-EOF\n+    * Saying \\\"./%s\\\" if you mean a file; or\n+    * Giving --format-patch option if you mean a range.\"), $f, $f);\n \t} catch Git::Error::Command with {\n \t\t# Not a valid revision.  Treat it as a filename.\n \t\treturn 0;\n@@ -604,7 +606,7 @@ while (defined(my $f = shift @ARGV)) {\n \t\t@ARGV = ();\n \t} elsif (-d $f and !is_format_patch_arg($f)) {\n \t\topendir my $dh, $f\n-\t\t\tor die \"Failed to opendir $f: $!\";\n+\t\t\tor die sprintf(__(\"Failed to opendir %s: %s\"), $f, $!);\n \n \t\tpush @files, grep { -f $_ } map { catfile($f, $_) }\n \t\t\t\tsort readdir $dh;\n@@ -628,7 +630,8 @@ if ($validate) {\n \tforeach my $f (@files) {\n \t\tunless (-p $f) {\n \t\t\tmy $error = validate_patch($f);\n-\t\t\t$error and die \"fatal: $f: $error\\nwarning: no patches were sent\\n\";\n+\t\t\t$error and die sprintf(__(\"fatal: %s: %s\\nwarning: no patches were sent\\n\"),\n+\t\t\t\t\t\t  $f, $error);\n \t\t}\n \t}\n }\n@@ -651,7 +654,7 @@ sub get_patch_subject {\n \t\treturn \"GIT: $1\\n\";\n \t}\n \tclose $fh;\n-\tdie \"No subject line in $fn ?\";\n+\tdie sprintf(__(\"No subject line in %s ?\"), $fn);\n }\n \n if ($compose) {\n@@ -661,7 +664,7 @@ if ($compose) {\n \t\ttempfile(\".gitsendemail.msg.XXXXXX\", DIR => $repo->repo_path()) :\n \t\ttempfile(\".gitsendemail.msg.XXXXXX\", DIR => \".\"))[1];\n \topen my $c, \">\", $compose_filename\n-\t\tor die \"Failed to open for writing $compose_filename: $!\";\n+\t\tor die sprintf(__(\"Failed to open for writing %s: %s\"), $compose_filename, $!);\n \n \n \tmy $tpl_sender = $sender || $repoauthor || $repocommitter || '';\n@@ -692,10 +695,10 @@ EOT\n \t}\n \n \topen my $c2, \">\", $compose_filename . \".final\"\n-\t\tor die \"Failed to open $compose_filename.final : \" . $!;\n+\t\tor die sprintf(__(\"Failed to open %s.final : %s\"), $compose_filename, $!);\n \n \topen $c, \"<\", $compose_filename\n-\t\tor die \"Failed to open $compose_filename : \" . $!;\n+\t\tor die sprintf(__(\"Failed to open %s : %s\"), $compose_filename, $!);\n \n \tmy $need_8bit_cte = file_has_nonascii($compose_filename);\n \tmy $in_body = 0;\n@@ -769,7 +772,9 @@ sub ask {\n \t\t\treturn $resp;\n \t\t}\n \t\tif ($confirm_only) {\n-\t\t\tmy $yesno = $term->readline(\"Are you sure you want to use <$resp> [y/N]? \");\n+\t\t\tmy $yesno = $term->readline(\n+\t\t\t\t# TRANSLATORS: please keep [y/N] as is.\n+\t\t\t\tsprintf(__(\"Are you sure you want to use <%s> [y/N]? \"), $resp));\n \t\t\tif (defined $yesno && $yesno =~ /y/i) {\n \t\t\t\treturn $resp;\n \t\t\t}\n@@ -811,9 +816,9 @@ if (!defined $auto_8bit_encoding && scalar %broken_encoding) {\n if (!$force) {\n \tfor my $f (@files) {\n \t\tif (get_patch_subject($f) =~ /\\Q*** SUBJECT HERE ***\\E/) {\n-\t\t\tdie \"Refusing to send because the patch\\n\\t$f\\n\"\n+\t\t\tdie sprintf(__(\"Refusing to send because the patch\\n\\t%s\\n\"\n \t\t\t\t. \"has the template subject '*** SUBJECT HERE ***'. \"\n-\t\t\t\t. \"Pass --force if you really want to send.\\n\";\n+\t\t\t\t. \"Pass --force if you really want to send.\\n\"), $f);\n \t\t}\n \t}\n }\n@@ -848,7 +853,7 @@ my %EXPANDED_ALIASES;\n sub expand_one_alias {\n \tmy $alias = shift;\n \tif ($EXPANDED_ALIASES{$alias}) {\n-\t\tdie \"fatal: alias '$alias' expands to itself\\n\";\n+\t\tdie sprintf(__(\"fatal: alias '%s' expands to itself\\n\"), $alias);\n \t}\n \tlocal $EXPANDED_ALIASES{$alias} = 1;\n \treturn $aliases{$alias} ? expand_aliases(@{$aliases{$alias}}) : $alias;\n@@ -910,7 +915,7 @@ sub extract_valid_address {\n sub extract_valid_address_or_die {\n \tmy $address = shift;\n \t$address = extract_valid_address($address);\n-\tdie \"error: unable to extract a valid address from: $address\\n\"\n+\tdie sprintf(__(\"error: unable to extract a valid address from: %s\\n\"), $address)\n \t\tif !$address;\n \treturn $address;\n }\n@@ -918,7 +923,7 @@ sub extract_valid_address_or_die {\n sub validate_address {\n \tmy $address = shift;\n \twhile (!extract_valid_address($address)) {\n-\t\tprint STDERR \"error: unable to extract a valid address from: $address\\n\";\n+\t\tprintf STDERR __(\"error: unable to extract a valid address from: %s\\n\"), $address;\n \t\t# TRANSLATORS: Make sure to include [q] [d] [e] in your\n \t\t# translation. The program will only accept English input\n \t\t# at this point.\n@@ -1223,7 +1228,7 @@ sub ssl_verify_params {\n \t\treturn (SSL_verify_mode => SSL_VERIFY_PEER(),\n \t\t\tSSL_ca_file => $smtp_ssl_cert_path);\n \t} else {\n-\t\tdie \"CA path \\\"$smtp_ssl_cert_path\\\" does not exist\";\n+\t\tdie sprintf(__(\"CA path \\\"%s\\\" does not exist\"), $smtp_ssl_cert_path);\n \t}\n }\n \n@@ -1384,14 +1389,14 @@ Message-Id: $message_id\n \t\t\t\t\t# supported commands\n \t\t\t\t\t$smtp->hello($smtp_domain);\n \t\t\t\t} else {\n-\t\t\t\t\tdie \"Server does not support STARTTLS! \".$smtp->message;\n+\t\t\t\t\tdie sprintf(__(\"Server does not support STARTTLS! %s\"), $smtp->message);\n \t\t\t\t}\n \t\t\t}\n \t\t}\n \n \t\tif (!$smtp) {\n-\t\t\tdie \"Unable to initialize SMTP properly. Check config and use --smtp-debug. \",\n-\t\t\t    \"VALUES: server=$smtp_server \",\n+\t\t\tdie __(\"Unable to initialize SMTP properly. Check config and use --smtp-debug.\"),\n+\t\t\t    \" VALUES: server=$smtp_server \",\n \t\t\t    \"encryption=$smtp_encryption \",\n \t\t\t    \"hello=$smtp_domain\",\n \t\t\t    defined $smtp_server_port ? \" port=$smtp_server_port\" : \"\";\n@@ -1408,10 +1413,10 @@ Message-Id: $message_id\n \t\t\t$smtp->datasend(\"$line\") or die $smtp->message;\n \t\t}\n \t\t$smtp->dataend() or die $smtp->message;\n-\t\t$smtp->code =~ /250|200/ or die \"Failed to send $subject\\n\".$smtp->message;\n+\t\t$smtp->code =~ /250|200/ or die sprintf(__(\"Failed to send %s\\n\"), $subject).$smtp->message;\n \t}\n \tif ($quiet) {\n-\t\tprintf (($dry_run ? \"Dry-\" : \"\").\"Sent %s\\n\", $subject);\n+\t\tprintf($dry_run ? __(\"Dry-Sent %s\\n\") : __(\"Sent %s\\n\"), $subject);\n \t} else {\n \t\tprint($dry_run ? __(\"Dry-OK. Log says:\\n\") : __(\"OK. Log says:\\n\"));\n \t\tif (!file_name_is_absolute($smtp_server)) {\n@@ -1441,7 +1446,7 @@ $subject = $initial_subject;\n $message_num = 0;\n \n foreach my $t (@files) {\n-\topen my $fh, \"<\", $t or die \"can't open file $t\";\n+\topen my $fh, \"<\", $t or die sprintf(__(\"can't open file %s\"), $t);\n \n \tmy $author = undef;\n \tmy $sauthor = undef;\n@@ -1663,18 +1668,18 @@ sub recipients_cmd {\n \n \tmy @addresses = ();\n \topen my $fh, \"-|\", \"$cmd \\Q$file\\E\"\n-\t    or die \"($prefix) Could not execute '$cmd'\";\n+\t    or die sprintf(__(\"(%s) Could not execute '%s'\"), $prefix, $cmd);\n \twhile (my $address = <$fh>) {\n \t\t$address =~ s/^\\s*//g;\n \t\t$address =~ s/\\s*$//g;\n \t\t$address = sanitize_address($address);\n \t\tnext if ($address eq $sender and $suppress_cc{'self'});\n \t\tpush @addresses, $address;\n-\t\tprintf(\"($prefix) Adding %s: %s from: '%s'\\n\",\n-\t\t       $what, $address, $cmd) unless $quiet;\n+\t\tprintf(__(\"(%s) Adding %s: %s from: '%s'\\n\"),\n+\t\t       $prefix, $what, $address, $cmd) unless $quiet;\n \t\t}\n \tclose $fh\n-\t    or die \"($prefix) failed to close pipe to '$cmd'\";\n+\t    or die sprintf(__(\"(%s) failed to close pipe to '%s'\"), $prefix, $cmd);\n \treturn @addresses;\n }\n \n@@ -1728,10 +1733,10 @@ sub unique_email_list {\n sub validate_patch {\n \tmy $fn = shift;\n \topen(my $fh, '<', $fn)\n-\t\tor die \"unable to open $fn: $!\\n\";\n+\t\tor die sprintf(__(\"unable to open %s: %s\\n\"), $fn, $!);\n \twhile (my $line = <$fh>) {\n \t\tif (length($line) > 998) {\n-\t\t\treturn \"$.: patch contains a line longer than 998 characters\";\n+\t\t\treturn sprintf(__(\"%s: patch contains a line longer than 998 characters\"), $.);\n \t\t}\n \t}\n \treturn;\n@@ -1747,10 +1752,11 @@ sub handle_backup {\n \t    (substr($file, 0, $lastlen) eq $last) &&\n \t    ($suffix = substr($file, $lastlen)) !~ /^[a-z0-9]/i) {\n \t\tif (defined $known_suffix && $suffix eq $known_suffix) {\n-\t\t\tprint \"Skipping $file with backup suffix '$known_suffix'.\\n\";\n+\t\t\tprintf(__(\"Skipping %s with backup suffix '%s'.\\n\"), $file, $known_suffix);\n \t\t\t$skip = 1;\n \t\t} else {\n-\t\t\tmy $answer = ask(\"Do you really want to send $file? (y|N): \",\n+\t\t\t# TRANSLATORS: please keep \"[y|N]\" as is.\n+\t\t\tmy $answer = ask(sprintf(__(\"Do you really want to send %s? [y|N]: \"), $file),\n \t\t\t\t\t valid_re => qr/^(?:y|n)/i,\n \t\t\t\t\t default => 'n');\n \t\t\t$skip = ($answer ne 'y');\n@@ -1778,7 +1784,7 @@ sub handle_backup_files {\n sub file_has_nonascii {\n \tmy $fn = shift;\n \topen(my $fh, '<', $fn)\n-\t\tor die \"unable to open $fn: $!\\n\";\n+\t\tor die sprintf(__(\"unable to open %s: %s\\n\"), $fn, $!);\n \twhile (my $line = <$fh>) {\n \t\treturn 1 if $line =~ /[^[:ascii:]]/;\n \t}\n@@ -1788,7 +1794,7 @@ sub file_has_nonascii {\n sub body_or_subject_has_nonascii {\n \tmy $fn = shift;\n \topen(my $fh, '<', $fn)\n-\t\tor die \"unable to open $fn: $!\\n\";\n+\t\tor die sprintf(__(\"unable to open %s: %s\\n\"), $fn, $!);\n \twhile (my $line = <$fh>) {\n \t\tlast if $line =~ /^$/;\n \t\treturn 1 if $line =~ /^Subject.*[^[:ascii:]]/;\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305550","messageId":"20161108120823.11204-14-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 13/16] i18n: send-email: mark warnings and errors for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:20Z","receivedAt":"2016-11-08T12:12:19Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark warnings, errors and other messages for translation.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-send-email.perl | 34 +++++++++++++++++-----------------\n 1 file changed, 17 insertions(+), 17 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 78eb59b21..982c6c076 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -118,20 +118,20 @@ sub format_2822_time {\n \tmy $localmin = $localtm[1] + $localtm[2] * 60;\n \tmy $gmtmin = $gmttm[1] + $gmttm[2] * 60;\n \tif ($localtm[0] != $gmttm[0]) {\n-\t\tdie \"local zone differs from GMT by a non-minute interval\\n\";\n+\t\tdie __(\"local zone differs from GMT by a non-minute interval\\n\");\n \t}\n \tif ((($gmttm[6] + 1) % 7) == $localtm[6]) {\n \t\t$localmin += 1440;\n \t} elsif ((($gmttm[6] - 1) % 7) == $localtm[6]) {\n \t\t$localmin -= 1440;\n \t} elsif ($gmttm[6] != $localtm[6]) {\n-\t\tdie \"local time offset greater than or equal to 24 hours\\n\";\n+\t\tdie __(\"local time offset greater than or equal to 24 hours\\n\");\n \t}\n \tmy $offset = $localmin - $gmtmin;\n \tmy $offhour = $offset / 60;\n \tmy $offmin = abs($offset % 60);\n \tif (abs($offhour) >= 24) {\n-\t\tdie (\"local time offset greater than or equal to 24 hours\\n\");\n+\t\tdie __(\"local time offset greater than or equal to 24 hours\\n\");\n \t}\n \n \treturn sprintf(\"%s, %2d %s %d %02d:%02d:%02d %s%02d%02d\",\n@@ -199,13 +199,13 @@ sub do_edit {\n \t\tmap {\n \t\t\tsystem('sh', '-c', $editor.' \"$@\"', $editor, $_);\n \t\t\tif (($? & 127) || ($? >> 8)) {\n-\t\t\t\tdie(\"the editor exited uncleanly, aborting everything\");\n+\t\t\t\tdie(__(\"the editor exited uncleanly, aborting everything\"));\n \t\t\t}\n \t\t} @_;\n \t} else {\n \t\tsystem('sh', '-c', $editor.' \"$@\"', $editor, @_);\n \t\tif (($? & 127) || ($? >> 8)) {\n-\t\t\tdie(\"the editor exited uncleanly, aborting everything\");\n+\t\t\tdie(__(\"the editor exited uncleanly, aborting everything\"));\n \t\t}\n \t}\n }\n@@ -299,7 +299,7 @@ my $help;\n my $rc = GetOptions(\"h\" => \\$help,\n                     \"dump-aliases\" => \\$dump_aliases);\n usage() unless $rc;\n-die \"--dump-aliases incompatible with other options\\n\"\n+die __(\"--dump-aliases incompatible with other options\\n\")\n     if !$help and $dump_aliases and @ARGV;\n $rc = GetOptions(\n \t\t    \"sender|from=s\" => \\$sender,\n@@ -362,7 +362,7 @@ unless ($rc) {\n     usage();\n }\n \n-die \"Cannot run git format-patch from outside a repository\\n\"\n+die __(\"Cannot run git format-patch from outside a repository\\n\")\n \tif $format_patch and not $repo;\n \n # Now, let's fill any that aren't set in with defaults:\n@@ -617,7 +617,7 @@ while (defined(my $f = shift @ARGV)) {\n }\n \n if (@rev_list_opts) {\n-\tdie \"Cannot run git format-patch from outside a repository\\n\"\n+\tdie __(\"Cannot run git format-patch from outside a repository\\n\")\n \t\tunless $repo;\n \tpush @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);\n }\n@@ -638,7 +638,7 @@ if (@files) {\n \t\tprint $_,\"\\n\" for (@files);\n \t}\n } else {\n-\tprint STDERR \"\\nNo patch files specified!\\n\\n\";\n+\tprint STDERR __(\"\\nNo patch files specified!\\n\\n\");\n \tusage();\n }\n \n@@ -730,7 +730,7 @@ EOT\n \t\t\t$sender = $1;\n \t\t\tnext;\n \t\t} elsif (/^(?:To|Cc|Bcc):/i) {\n-\t\t\tprint \"To/Cc/Bcc fields are not interpreted yet, they have been ignored\\n\";\n+\t\t\tprint __(\"To/Cc/Bcc fields are not interpreted yet, they have been ignored\\n\");\n \t\t\tnext;\n \t\t}\n \t\tprint $c2 $_;\n@@ -739,7 +739,7 @@ EOT\n \tclose $c2;\n \n \tif ($summary_empty) {\n-\t\tprint \"Summary email is empty, skipping it\\n\";\n+\t\tprint __(\"Summary email is empty, skipping it\\n\");\n \t\t$compose = -1;\n \t}\n } elsif ($annotate) {\n@@ -1314,7 +1314,7 @@ Message-Id: $message_id\n \t\t$_ = ask(__(\"Send this email? ([y]es|[n]o|[q]uit|[a]ll): \"),\n \t\t         valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,\n \t\t         default => $ask_default);\n-\t\tdie \"Send this email reply required\" unless defined $_;\n+\t\tdie __(\"Send this email reply required\") unless defined $_;\n \t\tif (/^n/i) {\n \t\t\treturn 0;\n \t\t} elsif (/^q/i) {\n@@ -1340,7 +1340,7 @@ Message-Id: $message_id\n \t} else {\n \n \t\tif (!defined $smtp_server) {\n-\t\t\tdie \"The required SMTP server is not properly defined.\"\n+\t\t\tdie __(\"The required SMTP server is not properly defined.\")\n \t\t}\n \n \t\tif ($smtp_encryption eq 'ssl') {\n@@ -1425,10 +1425,10 @@ Message-Id: $message_id\n \t\t}\n \t\tprint $header, \"\\n\";\n \t\tif ($smtp) {\n-\t\t\tprint \"Result: \", $smtp->code, ' ',\n+\t\t\tprint __(\"Result: \"), $smtp->code, ' ',\n \t\t\t\t($smtp->message =~ /\\n([^\\n]+\\n)$/s), \"\\n\";\n \t\t} else {\n-\t\t\tprint \"Result: OK\\n\";\n+\t\t\tprint __(\"Result: OK\\n\");\n \t\t}\n \t}\n \n@@ -1701,7 +1701,7 @@ sub apply_transfer_encoding {\n \t$message = MIME::Base64::decode($message)\n \t\tif ($from eq 'base64');\n \n-\tdie \"cannot send message as 7bit\"\n+\tdie __(\"cannot send message as 7bit\")\n \t\tif ($to eq '7bit' and $message =~ /[^[:ascii:]]/);\n \treturn $message\n \t\tif ($to eq '7bit' or $to eq '8bit');\n@@ -1709,7 +1709,7 @@ sub apply_transfer_encoding {\n \t\tif ($to eq 'quoted-printable');\n \treturn MIME::Base64::encode($message, \"\\n\")\n \t\tif ($to eq 'base64');\n-\tdie \"invalid transfer encoding\";\n+\tdie __(\"invalid transfer encoding\");\n }\n \n sub unique_email_list {\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305551","messageId":"20161108120823.11204-13-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 12/16] i18n: send-email: mark strings for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:19Z","receivedAt":"2016-11-08T12:12:23Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark strings often displayed to the user for translation.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-send-email.perl | 52 ++++++++++++++++++++++++++++++----------------------\n 1 file changed, 30 insertions(+), 22 deletions(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex da81be40c..78eb59b21 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -28,6 +28,7 @@ use File::Temp qw/ tempdir tempfile /;\n use File::Spec::Functions qw(catfile);\n use Error qw(:try);\n use Git;\n+use Git::I18N;\n \n Getopt::Long::Configure qw/ pass_through /;\n \n@@ -797,12 +798,12 @@ foreach my $f (@files) {\n }\n \n if (!defined $auto_8bit_encoding && scalar %broken_encoding) {\n-\tprint \"The following files are 8bit, but do not declare \" .\n-\t\t\"a Content-Transfer-Encoding.\\n\";\n+\tprint __(\"The following files are 8bit, but do not declare \" .\n+\t\t \"a Content-Transfer-Encoding.\\n\");\n \tforeach my $f (sort keys %broken_encoding) {\n \t\tprint \"    $f\\n\";\n \t}\n-\t$auto_8bit_encoding = ask(\"Which 8bit encoding should I declare [UTF-8]? \",\n+\t$auto_8bit_encoding = ask(__(\"Which 8bit encoding should I declare [UTF-8]? \"),\n \t\t\t\t  valid_re => qr/.{4}/, confirm_only => 1,\n \t\t\t\t  default => \"UTF-8\");\n }\n@@ -829,7 +830,7 @@ if (defined $sender) {\n # But it's a no-op to run sanitize_address on an already sanitized address.\n $sender = sanitize_address($sender);\n \n-my $to_whom = \"To whom should the emails be sent (if anyone)?\";\n+my $to_whom = __(\"To whom should the emails be sent (if anyone)?\");\n my $prompting = 0;\n if (!@initial_to && !defined $to_cmd) {\n \tmy $to = ask(\"$to_whom \",\n@@ -859,7 +860,7 @@ sub expand_one_alias {\n \n if ($thread && !defined $initial_reply_to && $prompting) {\n \t$initial_reply_to = ask(\n-\t\t\"Message-ID to be used as In-Reply-To for the first email (if any)? \",\n+\t\t__(\"Message-ID to be used as In-Reply-To for the first email (if any)? \"),\n \t\tdefault => \"\",\n \t\tvalid_re => qr/\\@.*\\./, confirm_only => 1);\n }\n@@ -918,7 +919,10 @@ sub validate_address {\n \tmy $address = shift;\n \twhile (!extract_valid_address($address)) {\n \t\tprint STDERR \"error: unable to extract a valid address from: $address\\n\";\n-\t\t$_ = ask(\"What to do with this address? ([q]uit|[d]rop|[e]dit): \",\n+\t\t# TRANSLATORS: Make sure to include [q] [d] [e] in your\n+\t\t# translation. The program will only accept English input\n+\t\t# at this point.\n+\t\t$_ = ask(__(\"What to do with this address? ([q]uit|[d]rop|[e]dit): \"),\n \t\t\tvalid_re => qr/^(?:quit|q|drop|d|edit|e)/i,\n \t\t\tdefault => 'q');\n \t\tif (/^d/i) {\n@@ -1293,17 +1297,21 @@ Message-Id: $message_id\n \t\tif ($needs_confirm eq \"inform\") {\n \t\t\t$confirm_unconfigured = 0; # squelch this message for the rest of this run\n \t\t\t$ask_default = \"y\"; # assume yes on EOF since user hasn't explicitly asked for confirmation\n-\t\t\tprint \"    The Cc list above has been expanded by additional\\n\";\n-\t\t\tprint \"    addresses found in the patch commit message. By default\\n\";\n-\t\t\tprint \"    send-email prompts before sending whenever this occurs.\\n\";\n-\t\t\tprint \"    This behavior is controlled by the sendemail.confirm\\n\";\n-\t\t\tprint \"    configuration setting.\\n\";\n-\t\t\tprint \"\\n\";\n-\t\t\tprint \"    For additional information, run 'git send-email --help'.\\n\";\n-\t\t\tprint \"    To retain the current behavior, but squelch this message,\\n\";\n-\t\t\tprint \"    run 'git config --global sendemail.confirm auto'.\\n\\n\";\n+\t\t\tprint __(\n+\"    The Cc list above has been expanded by additional\n+    addresses found in the patch commit message. By default\n+    send-email prompts before sending whenever this occurs.\n+    This behavior is controlled by the sendemail.confirm\n+    configuration setting.\n+\n+    For additional information, run 'git send-email --help'.\n+    To retain the current behavior, but squelch this message,\n+    run 'git config --global sendemail.confirm auto'.\"), \"\\n\\n\";\n \t\t}\n-\t\t$_ = ask(\"Send this email? ([y]es|[n]o|[q]uit|[a]ll): \",\n+\t\t# TRANSLATORS: Make sure to include [y] [n] [q] [a] in your\n+\t\t# translation. The program will only accept English input\n+\t\t# at this point.\n+\t\t$_ = ask(__(\"Send this email? ([y]es|[n]o|[q]uit|[a]ll): \"),\n \t\t         valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,\n \t\t         default => $ask_default);\n \t\tdie \"Send this email reply required\" unless defined $_;\n@@ -1405,7 +1413,7 @@ Message-Id: $message_id\n \tif ($quiet) {\n \t\tprintf (($dry_run ? \"Dry-\" : \"\").\"Sent %s\\n\", $subject);\n \t} else {\n-\t\tprint (($dry_run ? \"Dry-\" : \"\").\"OK. Log says:\\n\");\n+\t\tprint($dry_run ? __(\"Dry-OK. Log says:\\n\") : __(\"OK. Log says:\\n\"));\n \t\tif (!file_name_is_absolute($smtp_server)) {\n \t\t\tprint \"Server: $smtp_server\\n\";\n \t\t\tprint \"MAIL FROM:<$raw_from>\\n\";\n@@ -1480,13 +1488,13 @@ foreach my $t (@files) {\n \t\t\t\t$sauthor = sanitize_address($author);\n \t\t\t\tnext if $suppress_cc{'author'};\n \t\t\t\tnext if $suppress_cc{'self'} and $sauthor eq $sender;\n-\t\t\t\tprintf(\"(mbox) Adding cc: %s from line '%s'\\n\",\n+\t\t\t\tprintf(__(\"(mbox) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t\t$1, $_) unless $quiet;\n \t\t\t\tpush @cc, $1;\n \t\t\t}\n \t\t\telsif (/^To:\\s+(.*)$/i) {\n \t\t\t\tforeach my $addr (parse_address_line($1)) {\n-\t\t\t\t\tprintf(\"(mbox) Adding to: %s from line '%s'\\n\",\n+\t\t\t\t\tprintf(__(\"(mbox) Adding to: %s from line '%s'\\n\"),\n \t\t\t\t\t\t$addr, $_) unless $quiet;\n \t\t\t\t\tpush @to, $addr;\n \t\t\t\t}\n@@ -1500,7 +1508,7 @@ foreach my $t (@files) {\n \t\t\t\t\t} else {\n \t\t\t\t\t\tnext if ($suppress_cc{'cc'});\n \t\t\t\t\t}\n-\t\t\t\t\tprintf(\"(mbox) Adding cc: %s from line '%s'\\n\",\n+\t\t\t\t\tprintf(__(\"(mbox) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t\t\t$addr, $_) unless $quiet;\n \t\t\t\t\tpush @cc, $addr;\n \t\t\t\t}\n@@ -1534,7 +1542,7 @@ foreach my $t (@files) {\n \t\t\t# So let's support that, too.\n \t\t\t$input_format = 'lots';\n \t\t\tif (@cc == 0 && !$suppress_cc{'cc'}) {\n-\t\t\t\tprintf(\"(non-mbox) Adding cc: %s from line '%s'\\n\",\n+\t\t\t\tprintf(__(\"(non-mbox) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t\t$_, $_) unless $quiet;\n \t\t\t\tpush @cc, $_;\n \t\t\t} elsif (!defined $subject) {\n@@ -1557,7 +1565,7 @@ foreach my $t (@files) {\n \t\t\t\tnext if $suppress_cc{'bodycc'} and $what =~ /Cc/i;\n \t\t\t}\n \t\t\tpush @cc, $c;\n-\t\t\tprintf(\"(body) Adding cc: %s from line '%s'\\n\",\n+\t\t\tprintf(__(\"(body) Adding cc: %s from line '%s'\\n\"),\n \t\t\t\t$c, $_) unless $quiet;\n \t\t}\n \t}\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305552","messageId":"20161108120823.11204-8-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 07/16] i18n: add--interactive: mark patch prompt for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:14Z","receivedAt":"2016-11-08T12:12:26Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark prompt message assembled in place for translation, unfolding each\nuse case for each entry in the %patch_modes hash table.\n\nPreviously, this script relied on whether $patch_mode was set to run the\ncommand patch_update_cmd() or show status and loop the main loop. Now,\nit uses $cmd to indicate we must run patch_update_cmd() and $patch_mode\nis used to tell which flavor of the %patch_modes are we on.  This is\nintroduced in order to be able to mark and unfold the message prompt\nknowing in which context we are.\n\nThe tracking of context was done previously by point %patch_mode_flavour\nhash table to the correct entry of %patch_modes, focusing only on value\nof %patch_modes. Now, we are also interested in the key ('staged',\n'stash', 'checkout_head', ...).\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n Makefile                  |  2 +-\n git-add--interactive.perl | 54 ++++++++++++++++++++++++++++++++++++++++-------\n perl/Git/I18N.pm          | 11 +++++++++-\n t/t0202/test.pl           |  5 ++++-\n 4 files changed, 61 insertions(+), 11 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 328151dd6..ee89c0624 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -2114,7 +2114,7 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \\\n XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \\\n \t--keyword=gettextln --keyword=eval_gettextln\n XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \\\n-\t--keyword=__ --keyword=\"__n:1,2\"\n+\t--keyword=__ --keyword=N__ --keyword=\"__n:1,2\"\n LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)\n LOCALIZED_SH = $(SCRIPT_SH)\n LOCALIZED_SH += git-parse-remote.sh\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex cd617837b..b7d382b10 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -93,6 +93,7 @@ sub colored {\n }\n \n # command line options\n+my $cmd;\n my $patch_mode;\n my $patch_mode_revision;\n \n@@ -173,7 +174,8 @@ my %patch_modes = (\n \t},\n );\n \n-my %patch_mode_flavour = %{$patch_modes{stage}};\n+$patch_mode = 'stage';\n+my %patch_mode_flavour = %{$patch_modes{$patch_mode}};\n \n sub run_cmd_pipe {\n \tif ($^O eq 'MSWin32') {\n@@ -1311,6 +1313,44 @@ sub display_hunks {\n \treturn $i;\n }\n \n+my %patch_update_prompt_modes = (\n+\tstage => {\n+\t\tmode => N__(\"Stage mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Stage deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Stage this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tstash => {\n+\t\tmode => N__(\"Stash mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Stash deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Stash this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\treset_head => {\n+\t\tmode => N__(\"Unstage mode change [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Unstage deletion [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Unstage this hunk [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\treset_nothead => {\n+\t\tmode => N__(\"Apply mode change to index [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Apply deletion to index [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Apply this hunk to index [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_index => {\n+\t\tmode => N__(\"Discard mode change from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Discard deletion from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Discard this hunk from worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_head => {\n+\t\tmode => N__(\"Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+\tcheckout_nothead => {\n+\t\tmode => N__(\"Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\tdeletion => N__(\"Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t\thunk => N__(\"Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? \"),\n+\t},\n+);\n+\n sub patch_update_file {\n \tmy $quit = 0;\n \tmy ($ix, $num);\n@@ -1383,12 +1423,9 @@ sub patch_update_file {\n \t\tfor (@{$hunk[$ix]{DISPLAY}}) {\n \t\t\tprint;\n \t\t}\n-\t\tprint colored $prompt_color, $patch_mode_flavour{VERB},\n-\t\t  ($hunk[$ix]{TYPE} eq 'mode' ? ' mode change' :\n-\t\t   $hunk[$ix]{TYPE} eq 'deletion' ? ' deletion' :\n-\t\t   ' this hunk'),\n-\t\t  $patch_mode_flavour{TARGET},\n-\t\t  \" [y,n,q,a,d,/$other,?]? \";\n+\t\tprint colored $prompt_color,\n+\t\t\tsprintf(__($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}), $other);\n+\n \t\tmy $line = prompt_single_character;\n \t\tlast unless defined $line;\n \t\tif ($line) {\n@@ -1644,6 +1681,7 @@ sub process_args {\n \t\tdie sprintf(__(\"invalid argument %s, expecting --\"),\n \t\t\t       $arg) unless $arg eq \"--\";\n \t\t%patch_mode_flavour = %{$patch_modes{$patch_mode}};\n+\t\t$cmd = 1;\n \t}\n \telsif ($arg ne \"--\") {\n \t\tdie sprintf(__(\"invalid argument %s, expecting --\"), $arg);\n@@ -1680,7 +1718,7 @@ sub main_loop {\n \n process_args();\n refresh();\n-if ($patch_mode) {\n+if ($cmd) {\n \tpatch_update_cmd();\n }\n else {\ndiff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm\nindex 617d8c2a1..c41425c8d 100644\n--- a/perl/Git/I18N.pm\n+++ b/perl/Git/I18N.pm\n@@ -13,7 +13,7 @@ BEGIN {\n \t}\n }\n \n-our @EXPORT = qw(__ __n);\n+our @EXPORT = qw(__ __n N__);\n our @EXPORT_OK = @EXPORT;\n \n sub __bootstrap_locale_messages {\n@@ -54,6 +54,8 @@ BEGIN\n \t\t*__ = sub ($) { $_[0] };\n \t\t*__n = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };\n \t};\n+\n+\tsub N__($) { return shift; }\n }\n \n 1;\n@@ -74,6 +76,7 @@ Git::I18N - Perl interface to Git's Gettext localizations\n \n \tprintf __n(\"commited %d file\\n\", \"commited %d files\\n\", $files), $files;\n \n+\n =head1 DESCRIPTION\n \n Git's internal Perl interface to gettext via L<Locale::Messages>. If\n@@ -95,6 +98,12 @@ passthrough fallback function.\n \n L<Locale::Messages>'s ngettext function or passthrough fallback function.\n \n+=head2 N__($)\n+\n+No-operation that only returns its argument. Use this if you want xgettext to\n+extract the text to the pot template but do not want to trigger retrival of the\n+translation at run time.\n+\n =head1 AUTHOR\n \n E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>\ndiff --git a/t/t0202/test.pl b/t/t0202/test.pl\nindex 4101833a8..2cbf7b959 100755\n--- a/t/t0202/test.pl\n+++ b/t/t0202/test.pl\n@@ -4,7 +4,7 @@ use lib (split(/:/, $ENV{GITPERLLIB}));\n use strict;\n use warnings;\n use POSIX qw(:locale_h);\n-use Test::More tests => 11;\n+use Test::More tests => 13;\n use Git::I18N;\n \n my $has_gettext_library = $Git::I18N::__HAS_LIBRARY;\n@@ -32,6 +32,7 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \tmy %prototypes = (qw(\n \t\t__\t$\n \t\t__n\t$$$\n+\t\tN__\t$\n \t));\n \twhile (my ($sub, $proto) = each %prototypes) {\n \t\tis(prototype(\\&{\"Git::I18N::$sub\"}), $proto, \"sanity: $sub has a $proto prototype\");\n@@ -55,6 +56,8 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \t\t\"Get singular string through __n() in C locale\");\n \tis(__n($got_singular, $got_plural, 2), $expect_plural,\n \t\t\"Get plural string through __n() in C locale\");\n+\n+\tis(N__($got), $expect, \"Passing a string through N__() in the C locale works\");\n }\n \n # Test a basic message on different locales\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305553","messageId":"20161108120823.11204-12-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 11/16] i18n: add--interactive: mark status words for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:18Z","receivedAt":"2016-11-08T12:12:27Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark words 'nothing', 'unchanged' and 'binary' used to display what has\nbeen staged or not, in \"git add -i\" status command.\n\nAlternatively one could mark N__('nothing') no-op in order to\nxgettext(1) extract the string and then trigger the translation at run\ntime only with __($print->{FILE}), but that has the side effect of triggering\nretrieval of translations for the changes indicator too (e.g. +2/-1)\nwhich may or may not be a problem.\n\nTo avoid that potential problem, mark only where there is certain to\ntrigger translation only of those words but in this case we must also\nretrieve the translation for the eq tests, since the value assigned was\nof the translation, not the English source.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 12 ++++++------\n 1 file changed, 6 insertions(+), 6 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 93cc6f557..56e688907 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -295,7 +295,7 @@ sub list_modified {\n \t\t\tmy ($change, $bin);\n \t\t\t$file = unquote_path($file);\n \t\t\tif ($add eq '-' && $del eq '-') {\n-\t\t\t\t$change = 'binary';\n+\t\t\t\t$change = __('binary');\n \t\t\t\t$bin = 1;\n \t\t\t}\n \t\t\telse {\n@@ -304,7 +304,7 @@ sub list_modified {\n \t\t\t$data{$file} = {\n \t\t\t\tINDEX => $change,\n \t\t\t\tBINARY => $bin,\n-\t\t\t\tFILE => 'nothing',\n+\t\t\t\tFILE => __('nothing'),\n \t\t\t}\n \t\t}\n \t\telsif (($adddel, $file) =\n@@ -320,7 +320,7 @@ sub list_modified {\n \t\t\t$file = unquote_path($file);\n \t\t\tmy ($change, $bin);\n \t\t\tif ($add eq '-' && $del eq '-') {\n-\t\t\t\t$change = 'binary';\n+\t\t\t\t$change = __('binary');\n \t\t\t\t$bin = 1;\n \t\t\t}\n \t\t\telse {\n@@ -340,7 +340,7 @@ sub list_modified {\n \t\t\t$file = unquote_path($2);\n \t\t\tif (!exists $data{$file}) {\n \t\t\t\t$data{$file} = +{\n-\t\t\t\t\tINDEX => 'unchanged',\n+\t\t\t\t\tINDEX => __('unchanged'),\n \t\t\t\t\tBINARY => 0,\n \t\t\t\t};\n \t\t\t}\n@@ -355,10 +355,10 @@ sub list_modified {\n \n \t\tif ($only) {\n \t\t\tif ($only eq 'index-only') {\n-\t\t\t\tnext if ($it->{INDEX} eq 'unchanged');\n+\t\t\t\tnext if ($it->{INDEX} eq __('unchanged'));\n \t\t\t}\n \t\t\tif ($only eq 'file-only') {\n-\t\t\t\tnext if ($it->{FILE} eq 'nothing');\n+\t\t\t\tnext if ($it->{FILE} eq __('nothing'));\n \t\t\t}\n \t\t}\n \t\tpush @return, +{\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305554","messageId":"20161108120823.11204-7-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 06/16] i18n: add--interactive: mark plural strings","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:13Z","receivedAt":"2016-11-08T12:12:28Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark plural strings for translation.  Unfold each action case in one\nentire sentence.\n\nPass new keyword for xgettext to extract.\n\nUpdate test to include new subroutine __n() for plural strings handling.\n\nUpdate documentation to include a description of the new __n()\nsubroutine.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n Makefile                  |  3 ++-\n git-add--interactive.perl | 27 ++++++++++++++++++---------\n perl/Git/I18N.pm          | 10 +++++++++-\n t/t0202/test.pl           | 11 ++++++++++-\n 4 files changed, 39 insertions(+), 12 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 9d6c24503..328151dd6 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -2113,7 +2113,8 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \\\n \t--keyword=_ --keyword=N_ --keyword=\"Q_:1,2\"\n XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \\\n \t--keyword=gettextln --keyword=eval_gettextln\n-XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl\n+XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --language=Perl \\\n+\t--keyword=__ --keyword=\"__n:1,2\"\n LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)\n LOCALIZED_SH = $(SCRIPT_SH)\n LOCALIZED_SH += git-parse-remote.sh\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex d05ac608e..cd617837b 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -669,12 +669,18 @@ sub status_cmd {\n sub say_n_paths {\n \tmy $did = shift @_;\n \tmy $cnt = scalar @_;\n-\tprint \"$did \";\n-\tif (1 < $cnt) {\n-\t\tprint \"$cnt paths\\n\";\n-\t}\n-\telse {\n-\t\tprint \"one path\\n\";\n+\tif ($did eq 'added') {\n+\t\tprintf(__n(\"added %d path\\n\", \"added %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n+\t} elsif ($did eq 'updated') {\n+\t\tprintf(__n(\"updated %d path\\n\", \"updated %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n+\t} elsif ($did eq 'reverted') {\n+\t\tprintf(__n(\"reverted %d path\\n\", \"reverted %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n+\t} else {\n+\t\tprintf(__n(\"touched %d path\\n\", \"touched %d paths\\n\",\n+\t\t\t   $cnt), $cnt);\n \t}\n }\n \n@@ -1423,7 +1429,8 @@ sub patch_update_file {\n \t\t\t\t} elsif (0 < $response && $response <= $num) {\n \t\t\t\t\t$ix = $response - 1;\n \t\t\t\t} else {\n-\t\t\t\t\terror_msg \"Sorry, only $num hunks available.\\n\";\n+\t\t\t\t\terror_msg sprintf(__n(\"Sorry, only %d hunk available.\\n\",\n+\t\t\t\t\t\t\t      \"Sorry, only %d hunks available.\\n\", $num), $num);\n \t\t\t\t}\n \t\t\t\tnext;\n \t\t\t}\n@@ -1518,8 +1525,10 @@ sub patch_update_file {\n \t\t\telsif ($other =~ /s/ && $line =~ /^s/) {\n \t\t\t\tmy @split = split_hunk($hunk[$ix]{TEXT}, $hunk[$ix]{DISPLAY});\n \t\t\t\tif (1 < @split) {\n-\t\t\t\t\tprint colored $header_color, \"Split into \",\n-\t\t\t\t\tscalar(@split), \" hunks.\\n\";\n+\t\t\t\t\tprint colored $header_color, sprintf(\n+\t\t\t\t\t\t__n(\"Split into %d hunk.\\n\",\n+\t\t\t\t\t\t    \"Split into %d hunks.\\n\",\n+\t\t\t\t\t\t    scalar(@split)), scalar(@split));\n \t\t\t\t}\n \t\t\t\tsplice (@hunk, $ix, 1, @split);\n \t\t\t\t$num = scalar @hunk;\ndiff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm\nindex f889fd6da..617d8c2a1 100644\n--- a/perl/Git/I18N.pm\n+++ b/perl/Git/I18N.pm\n@@ -13,7 +13,7 @@ BEGIN {\n \t}\n }\n \n-our @EXPORT = qw(__);\n+our @EXPORT = qw(__ __n);\n our @EXPORT_OK = @EXPORT;\n \n sub __bootstrap_locale_messages {\n@@ -44,6 +44,7 @@ BEGIN\n \teval {\n \t\t__bootstrap_locale_messages();\n \t\t*__ = \\&Locale::Messages::gettext;\n+\t\t*__n = \\&Locale::Messages::ngettext;\n \t\t1;\n \t} or do {\n \t\t# Tell test.pl that we couldn't load the gettext library.\n@@ -51,6 +52,7 @@ BEGIN\n \n \t\t# Just a fall-through no-op\n \t\t*__ = sub ($) { $_[0] };\n+\t\t*__n = sub ($$$) { $_[2] == 1 ? $_[0] : $_[1] };\n \t};\n }\n \n@@ -70,6 +72,8 @@ Git::I18N - Perl interface to Git's Gettext localizations\n \n \tprintf __(\"The following error occurred: %s\\n\"), $error;\n \n+\tprintf __n(\"commited %d file\\n\", \"commited %d files\\n\", $files), $files;\n+\n =head1 DESCRIPTION\n \n Git's internal Perl interface to gettext via L<Locale::Messages>. If\n@@ -87,6 +91,10 @@ it.\n L<Locale::Messages>'s gettext function if all goes well, otherwise our\n passthrough fallback function.\n \n+=head2 __n($$$)\n+\n+L<Locale::Messages>'s ngettext function or passthrough fallback function.\n+\n =head1 AUTHOR\n \n E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avarab@gmail.com>\ndiff --git a/t/t0202/test.pl b/t/t0202/test.pl\nindex 2c10cb469..4101833a8 100755\n--- a/t/t0202/test.pl\n+++ b/t/t0202/test.pl\n@@ -4,7 +4,7 @@ use lib (split(/:/, $ENV{GITPERLLIB}));\n use strict;\n use warnings;\n use POSIX qw(:locale_h);\n-use Test::More tests => 8;\n+use Test::More tests => 11;\n use Git::I18N;\n \n my $has_gettext_library = $Git::I18N::__HAS_LIBRARY;\n@@ -31,6 +31,7 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \t# more gettext wrapper functions.\n \tmy %prototypes = (qw(\n \t\t__\t$\n+\t\t__n\t$$$\n \t));\n \twhile (my ($sub, $proto) = each %prototypes) {\n \t\tis(prototype(\\&{\"Git::I18N::$sub\"}), $proto, \"sanity: $sub has a $proto prototype\");\n@@ -46,6 +47,14 @@ is_deeply(\\@Git::I18N::EXPORT, \\@Git::I18N::EXPORT_OK, \"sanity: Git::I18N export\n \tmy ($got, $expect) = (('TEST: A Perl test string') x 2);\n \n \tis(__($got), $expect, \"Passing a string through __() in the C locale works\");\n+\n+\tmy ($got_singular, $got_plural, $expect_singular, $expect_plural) =\n+\t\t(('TEST: 1 file', 'TEST: n files') x 2);\n+\n+\tis(__n($got_singular, $got_plural, 1), $expect_singular,\n+\t\t\"Get singular string through __n() in C locale\");\n+\tis(__n($got_singular, $got_plural, 2), $expect_plural,\n+\t\t\"Get plural string through __n() in C locale\");\n }\n \n # Test a basic message on different locales\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305555","messageId":"20161108120823.11204-6-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 05/16] i18n: clean.c: match string with git-add--interactive.perl","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:12Z","receivedAt":"2016-11-08T12:12:33Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Change strings for help to match the ones in git-add--interactive.perl.\nThe strings now represent one entry to translate each rather then two\nentries each different only by an ending newline character.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n builtin/clean.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/clean.c b/builtin/clean.c\nindex 0371010af..d6bc3aaae 100644\n--- a/builtin/clean.c\n+++ b/builtin/clean.c\n@@ -287,11 +287,11 @@ static void pretty_print_menus(struct string_list *menu_list)\n static void prompt_help_cmd(int singleton)\n {\n \tclean_print_color(CLEAN_COLOR_HELP);\n-\tprintf_ln(singleton ?\n+\tprintf(singleton ?\n \t\t  _(\"Prompt help:\\n\"\n \t\t    \"1          - select a numbered item\\n\"\n \t\t    \"foo        - select item based on unique prefix\\n\"\n-\t\t    \"           - (empty) select nothing\") :\n+\t\t    \"           - (empty) select nothing\\n\") :\n \t\t  _(\"Prompt help:\\n\"\n \t\t    \"1          - select a single item\\n\"\n \t\t    \"3-5        - select a range of items\\n\"\n@@ -299,7 +299,7 @@ static void prompt_help_cmd(int singleton)\n \t\t    \"foo        - select item based on unique prefix\\n\"\n \t\t    \"-...       - unselect specified items\\n\"\n \t\t    \"*          - choose all items\\n\"\n-\t\t    \"           - (empty) finish selecting\"));\n+\t\t    \"           - (empty) finish selecting\\n\"));\n \tclean_print_color(CLEAN_COLOR_RESET);\n }\n \n@@ -508,7 +508,7 @@ static int parse_choice(struct menu_stuff *menu_stuff,\n \t\tif (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||\n \t\t    (is_single && bottom != top)) {\n \t\t\tclean_print_color(CLEAN_COLOR_ERROR);\n-\t\t\tprintf_ln(_(\"Huh (%s)?\"), (*ptr)->buf);\n+\t\t\tprintf(_(\"Huh (%s)?\\n\"), (*ptr)->buf);\n \t\t\tclean_print_color(CLEAN_COLOR_RESET);\n \t\t\tcontinue;\n \t\t}\n@@ -774,7 +774,7 @@ static int ask_each_cmd(void)\n static int quit_cmd(void)\n {\n \tstring_list_clear(&del_list, 0);\n-\tprintf_ln(_(\"Bye.\"));\n+\tprintf(_(\"Bye.\\n\"));\n \treturn MENU_RETURN_NO_LOOP;\n }\n \n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305556","messageId":"20161108120823.11204-5-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 04/16] i18n: add--interactive: mark strings with interpolation for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:11Z","receivedAt":"2016-11-08T12:12:36Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Since at this point Git::I18N.perl lacks support for Perl i18n\nplaceholder substitution, use of sprintf following die or error_msg is\nnecessary for placeholder substitution take place.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 25 +++++++++++++------------\n 1 file changed, 13 insertions(+), 12 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 5800010ed..d05ac608e 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -615,12 +615,12 @@ sub list_and_choose {\n \t\t\telse {\n \t\t\t\t$bottom = $top = find_unique($choice, @stuff);\n \t\t\t\tif (!defined $bottom) {\n-\t\t\t\t\terror_msg \"Huh ($choice)?\\n\";\n+\t\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\\n\"), $choice);\n \t\t\t\t\tnext TOPLOOP;\n \t\t\t\t}\n \t\t\t}\n \t\t\tif ($opts->{SINGLETON} && $bottom != $top) {\n-\t\t\t\terror_msg \"Huh ($choice)?\\n\";\n+\t\t\t\terror_msg sprintf(__(\"Huh (%s)?\\n\"), $choice);\n \t\t\t\tnext TOPLOOP;\n \t\t\t}\n \t\t\tfor ($i = $bottom-1; $i <= $top-1; $i++) {\n@@ -717,7 +717,7 @@ sub revert_cmd {\n \t\t\t\t    $_->{INDEX_ADDDEL} eq 'create') {\n \t\t\t\t\tsystem(qw(git update-index --force-remove --),\n \t\t\t\t\t       $_->{VALUE});\n-\t\t\t\t\tprint \"note: $_->{VALUE} is untracked now.\\n\";\n+\t\t\t\t\tprintf(__(\"note: %s is untracked now.\\n\"), $_->{VALUE});\n \t\t\t\t}\n \t\t\t}\n \t\t}\n@@ -1056,7 +1056,7 @@ sub edit_hunk_manually {\n \tmy $hunkfile = $repo->repo_path . \"/addp-hunk-edit.diff\";\n \tmy $fh;\n \topen $fh, '>', $hunkfile\n-\t\tor die \"failed to open hunk edit file for writing: \" . $!;\n+\t\tor die sprintf(__(\"failed to open hunk edit file for writing: %s\"), $!);\n \tprint $fh \"# Manual hunk edit mode -- see bottom for a quick guide\\n\";\n \tprint $fh @$oldtext;\n \tmy $participle = $patch_mode_flavour{PARTICIPLE};\n@@ -1083,7 +1083,7 @@ EOF\n \t}\n \n \topen $fh, '<', $hunkfile\n-\t\tor die \"failed to open hunk edit file for reading: \" . $!;\n+\t\tor die sprintf(__(\"failed to open hunk edit file for reading: %s\"), $!);\n \tmy @newtext = grep { !/^#/ } <$fh>;\n \tclose $fh;\n \tunlink $hunkfile;\n@@ -1236,7 +1236,7 @@ sub apply_patch_for_checkout_commit {\n \n sub patch_update_cmd {\n \tmy @all_mods = list_modified($patch_mode_flavour{FILTER});\n-\terror_msg \"ignoring unmerged: $_->{VALUE}\\n\"\n+\terror_msg sprintf(__(\"ignoring unmerged: %s\\n\"), $_->{VALUE})\n \t\tfor grep { $_->{UNMERGED} } @all_mods;\n \t@all_mods = grep { !$_->{UNMERGED} } @all_mods;\n \n@@ -1418,7 +1418,8 @@ sub patch_update_file {\n \t\t\t\t\tchomp $response;\n \t\t\t\t}\n \t\t\t\tif ($response !~ /^\\s*\\d+\\s*$/) {\n-\t\t\t\t\terror_msg \"Invalid number: '$response'\\n\";\n+\t\t\t\t\terror_msg sprintf(__(\"Invalid number: '%s'\\n\"),\n+\t\t\t\t\t\t\t     $response);\n \t\t\t\t} elsif (0 < $response && $response <= $num) {\n \t\t\t\t\t$ix = $response - 1;\n \t\t\t\t} else {\n@@ -1460,7 +1461,7 @@ sub patch_update_file {\n \t\t\t\tif ($@) {\n \t\t\t\t\tmy ($err,$exp) = ($@, $1);\n \t\t\t\t\t$err =~ s/ at .*git-add--interactive line \\d+, <STDIN> line \\d+.*$//;\n-\t\t\t\t\terror_msg \"Malformed search regexp $exp: $err\\n\";\n+\t\t\t\t\terror_msg sprintf(__(\"Malformed search regexp %s: %s\\n\"), $exp, $err);\n \t\t\t\t\tnext;\n \t\t\t\t}\n \t\t\t\tmy $iy = $ix;\n@@ -1625,18 +1626,18 @@ sub process_args {\n \t\t\t\t$patch_mode = $1;\n \t\t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t\t} else {\n-\t\t\t\tdie \"unknown --patch mode: $1\";\n+\t\t\t\tdie sprintf(__(\"unknown --patch mode: %s\"), $1);\n \t\t\t}\n \t\t} else {\n \t\t\t$patch_mode = 'stage';\n \t\t\t$arg = shift @ARGV or die __(\"missing --\");\n \t\t}\n-\t\tdie \"invalid argument $arg, expecting --\"\n-\t\t    unless $arg eq \"--\";\n+\t\tdie sprintf(__(\"invalid argument %s, expecting --\"),\n+\t\t\t       $arg) unless $arg eq \"--\";\n \t\t%patch_mode_flavour = %{$patch_modes{$patch_mode}};\n \t}\n \telsif ($arg ne \"--\") {\n-\t\tdie \"invalid argument $arg, expecting --\";\n+\t\tdie sprintf(__(\"invalid argument %s, expecting --\"), $arg);\n \t}\n }\n \n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305557","messageId":"20161108120823.11204-4-vascomalmeida@sapo.pt","threadId":"44227","inReplyTo":"20161108120823.11204-1-vascomalmeida@sapo.pt","subject":"[PATCH v5 03/16] i18n: add--interactive: mark simple here-documents for translation","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-08T12:08:10Z","receivedAt":"2016-11-08T12:12:37Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"Mark messages in here-documents without interpolation for translation.\n\nThe here-document delimiter \\EOF, which is the same as 'EOF', indicates\nthat the text is to be treated literally without interpolation of its\ncontent.  Unfortunately xgettext is not able to extract here-documents\ndelimited with \\EOF but it is with delimiter enclosed in single quotes.\nSo change \\EOF to 'EOF', although in this case does not make\ndifference what variation of here-document to use since there is nothing\nto interpolate.\n\nSigned-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n---\n git-add--interactive.perl | 8 +++++---\n 1 file changed, 5 insertions(+), 3 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex cf216ecb6..5800010ed 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -639,7 +639,7 @@ sub list_and_choose {\n }\n \n sub singleton_prompt_help_cmd {\n-\tprint colored $help_color, <<\\EOF ;\n+\tprint colored $help_color, __ <<'EOF' ;\n Prompt help:\n 1          - select a numbered item\n foo        - select item based on unique prefix\n@@ -648,7 +648,7 @@ EOF\n }\n \n sub prompt_help_cmd {\n-\tprint colored $help_color, <<\\EOF ;\n+\tprint colored $help_color, __ <<'EOF' ;\n Prompt help:\n 1          - select a single item\n 3-5        - select a range of items\n@@ -1584,7 +1584,9 @@ sub quit_cmd {\n }\n \n sub help_cmd {\n-\tprint colored $help_color, <<\\EOF ;\n+# TRANSLATORS: please do not translate the command names\n+# 'status', 'update', 'revert', etc.\n+\tprint colored $help_color, __ <<'EOF' ;\n status        - show paths with changes\n update        - add working tree state to the staged set of changes\n revert        - revert staged set of changes back to the HEAD version\n-- \n2.11.0.rc0.23.g8236252\n\n"},{"id":"305615","messageId":"xmqqshr19oxp.fsf@gitster.mtv.corp.google.com","threadId":"44227","inReplyTo":"20161108120823.11204-2-vascomalmeida@sapo.pt","subject":"Re: [PATCH v5 01/16] Git.pm: add subroutines for commenting lines","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-11-09T01:06:35Z","receivedAt":"2016-11-09T05:56:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Vasco Almeida <vascomalmeida@sapo.pt> writes:\n\n> Add subroutines prefix_lines and comment_lines.\n>\n> Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n> ---\n>  perl/Git.pm | 23 +++++++++++++++++++++++\n>  1 file changed, 23 insertions(+)\n>\n> diff --git a/perl/Git.pm b/perl/Git.pm\n> index b2732822a..17be59fb7 100644\n> --- a/perl/Git.pm\n> +++ b/perl/Git.pm\n> @@ -1438,6 +1438,29 @@ sub END {\n>  \n>  } # %TEMP_* Lexical Context\n>  \n> +=item prefix_lines ( PREFIX, STRING )\n> +\n> +Prefixes lines in C<STRING> with C<PREFIX>.\n> +\n> +=cut\n> +\n> +sub prefix_lines {\n> +\tmy ($prefix, $string) = @_;\n> +\t$string =~ s/^/$prefix/mg;\n> +\treturn $string;\n> +}\n> +\n> +=item comment_lines ( STRING )\n> +\n> +Comments lines following core.commentchar configuration.\n> +\n> +=cut\n> +\n> +sub comment_lines {\n> +\tmy $comment_line_char = config(\"core.commentchar\") || '#';\n> +\treturn prefix_lines(\"$comment_line_char \", @_);\n> +}\n> +\n\nThis makes it appear as if comment_lines can take arbitrary number\nof strings as its arguments (because the outer caller just passes @_\nthru), but in fact because prefix_lines ignores anything other than\n$_[0] and $_[1], only the first parameter given to comment_lineS sub\nis inspected for lines in it and the prefix-char prefixed at the\nbeginning of each of them.\n\nWhich is not a great interface, as it is quite misleading.\n\nPerhaps\n\n\tprefix_lines(\"#\", join(\"\\n\", @_));\n\nor something like that may make it less confusing.\n"},{"id":"305639","messageId":"1478710943.28771.4.camel@sapo.pt","threadId":"44227","inReplyTo":"xmqqshr19oxp.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v5 01/16] Git.pm: add subroutines for commenting lines","fromName":"Vasco Almeida","fromEmail":"vascomalmeida@sapo.pt","sentAt":"2016-11-09T17:02:23Z","receivedAt":"2016-11-09T17:02:43Z","isPatch":true,"sender":{"key":"vascomalmeida@sapo.pt","avatar":"https://avatars.githubusercontent.com/u/9001556?v=4"},"body":"A Ter, 08-11-2016 às 17:06 -0800, Junio C Hamano escreveu:\n> Vasco Almeida <vascomalmeida@sapo.pt> writes:\n> \n> > \n> > Add subroutines prefix_lines and comment_lines.\n> > \n> > Signed-off-by: Vasco Almeida <vascomalmeida@sapo.pt>\n> > ---\n> >  perl/Git.pm | 23 +++++++++++++++++++++++\n> >  1 file changed, 23 insertions(+)\n> > \n> > diff --git a/perl/Git.pm b/perl/Git.pm\n> > index b2732822a..17be59fb7 100644\n> > --- a/perl/Git.pm\n> > +++ b/perl/Git.pm\n> > @@ -1438,6 +1438,29 @@ sub END {\n> >  \n> >  } # %TEMP_* Lexical Context\n> >  \n> > +=item prefix_lines ( PREFIX, STRING )\n> > +\n> > +Prefixes lines in C<STRING> with C<PREFIX>.\n> > +\n> > +=cut\n> > +\n> > +sub prefix_lines {\n> > +\tmy ($prefix, $string) = @_;\n> > +\t$string =~ s/^/$prefix/mg;\n> > +\treturn $string;\n> > +}\n> > +\n> > +=item comment_lines ( STRING )\n> > +\n> > +Comments lines following core.commentchar configuration.\n> > +\n> > +=cut\n> > +\n> > +sub comment_lines {\n> > +\tmy $comment_line_char = config(\"core.commentchar\") || '#';\n> > +\treturn prefix_lines(\"$comment_line_char \", @_);\n> > +}\n> > +\n> \n> This makes it appear as if comment_lines can take arbitrary number\n> of strings as its arguments (because the outer caller just passes @_\n> thru), but in fact because prefix_lines ignores anything other than\n> $_[0] and $_[1], only the first parameter given to comment_lineS sub\n> is inspected for lines in it and the prefix-char prefixed at the\n> beginning of each of them.\n> \n> Which is not a great interface, as it is quite misleading.\n> \n> Perhaps\n> \n> \tprefix_lines(\"#\", join(\"\\n\", @_));\n> \n> or something like that may make it less confusing.\n\nI prefer to have like this instead\n\nsub prefix_lines {\n        my $prefix = shift;\n        my $string = join(\"\\n\", @_);\n        $string =~ s/^/$prefix/mg;\n        return $string;\n}\n\nSo both subroutines can take several strings as arguments.\n"},{"id":"305648","messageId":"b01d0d90-f87c-f708-5d2a-79f6268b4f44@gmail.com","threadId":"44227","inReplyTo":"1478710943.28771.4.camel@sapo.pt","subject":"Re: [PATCH v5 01/16] Git.pm: add subroutines for commenting lines","fromName":"Jakub Narębski","fromEmail":"jnareb@gmail.com","sentAt":"2016-11-09T22:25:23Z","receivedAt":"2016-11-09T22:25:44Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"W dniu 09.11.2016 o 18:02, Vasco Almeida pisze:\n> A Ter, 08-11-2016 às 17:06 -0800, Junio C Hamano escreveu:\n>> Vasco Almeida <vascomalmeida@sapo.pt> writes:\n\n>>> +sub comment_lines {\n>>> +\tmy $comment_line_char = config(\"core.commentchar\") || '#';\n>>> +\treturn prefix_lines(\"$comment_line_char \", @_);\n>>> +}\n>>> +\n>>\n>> This makes it appear as if comment_lines can take arbitrary number\n>> of strings as its arguments (because the outer caller just passes @_\n>> thru), but in fact because prefix_lines ignores anything other than\n>> $_[0] and $_[1], only the first parameter given to comment_lineS sub\n>> is inspected for lines in it and the prefix-char prefixed at the\n>> beginning of each of them.\n>>\n>> Which is not a great interface, as it is quite misleading.\n>>\n>> Perhaps\n>>\n>> \tprefix_lines(\"#\", join(\"\\n\", @_));\n>>\n>> or something like that may make it less confusing.\n> \n> I prefer to have like this instead\n> \n> sub prefix_lines {\n>         my $prefix = shift;\n>         my $string = join(\"\\n\", @_);\n>         $string =~ s/^/$prefix/mg;\n>         return $string;\n> }\n> \n> So both subroutines can take several strings as arguments.\n\nI like the interface, but the implementation looks a bit inefficient.\nWhy not simply:\n\n  sub prefix_lines {\n          my $prefix = shift;\n          return \"$prefix\" . join(\"\\n$prefix\", @_) . \"\\n\";\n  }\n\nThat is, if we can assume that those lines are not terminated by\nnewlines themselves.\n\nIf they can be (but cannot have embedded newlines), then\n\n  sub prefix_lines {\n          my $prefix = shift;\n          return \"$prefix\" . join(\"\\n$prefix\", map(chomp, @_)) . \"\\n\";\n  }\n\nIf those strings can contain embedded newlines (so that they can be\ncalled as in Junio example), then your solution is a must-be\n\n  sub prefix_lines {\n          my $prefix = shift;\n          my $string = join(\"\\n\", @_);\n          $string =~ s/^/$prefix/mg;\n          return $string;\n  }\n\nWell, nevermind then\n-- \nJakub Narębski\n\n"},{"id":"305657","messageId":"xmqqa8d88crj.fsf@gitster.mtv.corp.google.com","threadId":"44227","inReplyTo":"b01d0d90-f87c-f708-5d2a-79f6268b4f44@gmail.com","subject":"Re: [PATCH v5 01/16] Git.pm: add subroutines for commenting lines","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-11-09T23:16:48Z","receivedAt":"2016-11-09T23:16:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narębski <jnareb@gmail.com> writes:\n\n>> I prefer to have like this instead\n>> \n>> sub prefix_lines {\n>>         my $prefix = shift;\n>>         my $string = join(\"\\n\", @_);\n>>         $string =~ s/^/$prefix/mg;\n>>         return $string;\n>> }\n>> \n>> So both subroutines can take several strings as arguments.\n>\n> I like the interface, but the implementation looks a bit inefficient.\n> Why not simply:\n> ...\n> If those strings can contain embedded newlines (so that they can be\n> called as in Junio example), then your solution is a must-be\n>\n>   sub prefix_lines {\n>           my $prefix = shift;\n>           my $string = join(\"\\n\", @_);\n>           $string =~ s/^/$prefix/mg;\n>           return $string;\n>   }\n>\n> Well, nevermind then\n\nOK, so in short, is that a \"Reviewed-by:\" from you ;-)?\n\nI agree with the conclusion.  Thanks for a review.\n\n"}]}