{"thread":{"id":"49702","subject":"[PATCH 00/12] Mark more strings for translation","startedAt":"2018-10-28T06:52:09Z","lastAt":"2018-11-10T14:59:11Z","messageCount":71,"participants":["Nguyễn Thái Ngọc Duy","Junio C Hamano","SZEDER Gábor","Duy Nguyen","Ævar Arnfjörð Bjarmason","Jonathan Nieder","Jiang Xin","Ramsay Jones","Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":12},"messages":[{"id":"361825","messageId":"20181028065157.26727-1-pclouds@gmail.com","threadId":"49702","inReplyTo":null,"subject":"[PATCH 00/12] Mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:45Z","receivedAt":"2018-10-28T06:52:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Not much to write here. I make a note whenever I see unstranslated\nstrings during review and this is the result. There are some more code\nchanges than just adding _() though, e.g. 10/12.\n\nNguyễn Thái Ngọc Duy (12):\n  git.c: mark more strings for translation\n  alias.c: mark split_cmdline_strerror() strings for translation\n  archive.c: mark more strings for translation\n  attr.c: mark more string for translation\n  read-cache.c: mark more strings for translation\n  read-cache.c: add missing colon separators\n  reflog: mark strings for translation\n  remote.c: mark messages for translation\n  repack: mark more strings for translation\n  parse-options: replace opterror() with optname()\n  parse-options.c: mark more strings for translation\n  fsck: mark strings for translation\n\n alias.c                    |   4 +-\n archive.c                  |   8 +--\n attr.c                     |   2 +-\n builtin/fsck.c             | 113 ++++++++++++++++++++-----------------\n builtin/merge.c            |   4 +-\n builtin/reflog.c           |  34 ++++++-----\n builtin/repack.c           |  26 ++++-----\n builtin/revert.c           |   3 +-\n git.c                      |  32 +++++------\n parse-options-cb.c         |   7 ++-\n parse-options.c            |  64 +++++++++++----------\n parse-options.h            |   5 +-\n read-cache.c               |  73 ++++++++++++------------\n ref-filter.c               |   8 ++-\n remote.c                   |  49 ++++++++--------\n t/t0040-parse-options.sh   |   4 +-\n t/t1410-reflog.sh          |   6 +-\n t/t1450-fsck.sh            |  52 ++++++++---------\n t/t4211-line-log.sh        |   2 +-\n t/t6050-replace.sh         |   4 +-\n t/t7415-submodule-names.sh |   6 +-\n 21 files changed, 264 insertions(+), 242 deletions(-)\n\n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361826","messageId":"20181028065157.26727-2-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 01/12] git.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:46Z","receivedAt":"2018-10-28T06:52:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n git.c | 30 +++++++++++++++---------------\n 1 file changed, 15 insertions(+), 15 deletions(-)\n\ndiff --git a/git.c b/git.c\nindex adac132956..1ad565c5c8 100644\n--- a/git.c\n+++ b/git.c\n@@ -338,27 +338,27 @@ static int handle_alias(int *argcp, const char ***argv)\n \t\t\tif (ret >= 0)   /* normal exit */\n \t\t\t\texit(ret);\n \n-\t\t\tdie_errno(\"while expanding alias '%s': '%s'\",\n-\t\t\t    alias_command, alias_string + 1);\n+\t\t\tdie_errno(_(\"while expanding alias '%s': '%s'\"),\n+\t\t\t\t  alias_command, alias_string + 1);\n \t\t}\n \t\tcount = split_cmdline(alias_string, &new_argv);\n \t\tif (count < 0)\n-\t\t\tdie(\"Bad alias.%s string: %s\", alias_command,\n+\t\t\tdie(_(\"bad alias.%s string: %s\"), alias_command,\n \t\t\t    split_cmdline_strerror(count));\n \t\toption_count = handle_options(&new_argv, &count, &envchanged);\n \t\tif (envchanged)\n-\t\t\tdie(\"alias '%s' changes environment variables.\\n\"\n-\t\t\t\t \"You can use '!git' in the alias to do this\",\n-\t\t\t\t alias_command);\n+\t\t\tdie(_(\"alias '%s' changes environment variables.\\n\"\n+\t\t\t      \"You can use '!git' in the alias to do this\"),\n+\t\t\t    alias_command);\n \t\tmemmove(new_argv - option_count, new_argv,\n \t\t\t\tcount * sizeof(char *));\n \t\tnew_argv -= option_count;\n \n \t\tif (count < 1)\n-\t\t\tdie(\"empty alias for %s\", alias_command);\n+\t\t\tdie(_(\"empty alias for %s\"), alias_command);\n \n \t\tif (!strcmp(alias_command, new_argv[0]))\n-\t\t\tdie(\"recursive alias: %s\", alias_command);\n+\t\t\tdie(_(\"recursive alias: %s\"), alias_command);\n \n \t\ttrace_argv_printf(new_argv,\n \t\t\t\t  \"trace: alias expansion: %s =>\",\n@@ -409,7 +409,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n \n \tif (!help && get_super_prefix()) {\n \t\tif (!(p->option & SUPPORT_SUPER_PREFIX))\n-\t\t\tdie(\"%s doesn't support --super-prefix\", p->cmd);\n+\t\t\tBUG(\"%s doesn't support --super-prefix\", p->cmd);\n \t}\n \n \tif (!help && p->option & NEED_WORK_TREE)\n@@ -433,11 +433,11 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n \n \t/* Check for ENOSPC and EIO errors.. */\n \tif (fflush(stdout))\n-\t\tdie_errno(\"write failure on standard output\");\n+\t\tdie_errno(_(\"write failure on standard output\"));\n \tif (ferror(stdout))\n-\t\tdie(\"unknown write failure on standard output\");\n+\t\tdie(_(\"unknown write failure on standard output\"));\n \tif (fclose(stdout))\n-\t\tdie_errno(\"close failed on standard output\");\n+\t\tdie_errno(_(\"close failed on standard output\"));\n \treturn 0;\n }\n \n@@ -648,7 +648,7 @@ static void execv_dashed_external(const char **argv)\n \tint status;\n \n \tif (get_super_prefix())\n-\t\tdie(\"%s doesn't support --super-prefix\", argv[0]);\n+\t\tBUG(\"%s doesn't support --super-prefix\", argv[0]);\n \n \tif (use_pager == -1 && !is_builtin(argv[0]))\n \t\tuse_pager = check_pager_config(argv[0]);\n@@ -760,7 +760,7 @@ int cmd_main(int argc, const char **argv)\n \tif (skip_prefix(cmd, \"git-\", &cmd)) {\n \t\targv[0] = cmd;\n \t\thandle_builtin(argc, argv);\n-\t\tdie(\"cannot handle %s as a builtin\", cmd);\n+\t\tdie(_(\"cannot handle %s as a builtin\"), cmd);\n \t}\n \n \t/* Look for flags.. */\n@@ -773,7 +773,7 @@ int cmd_main(int argc, const char **argv)\n \t} else {\n \t\t/* The user didn't specify a command; give them help */\n \t\tcommit_pager_choice();\n-\t\tprintf(\"usage: %s\\n\\n\", git_usage_string);\n+\t\tprintf(_(\"usage: %s\\n\\n\"), git_usage_string);\n \t\tlist_common_cmds_help();\n \t\tprintf(\"\\n%s\\n\", _(git_more_info_string));\n \t\texit(1);\n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361827","messageId":"20181028065157.26727-3-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 02/12] alias.c: mark split_cmdline_strerror() strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:47Z","receivedAt":"2018-10-28T06:52:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This function can be part of translated messages. To make sure we\ndon't have a sentence with mixed languages, mark the strings for\ntranslation, but only use translated strings in places we know we will\noutput translated strings.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n alias.c         | 4 ++--\n builtin/merge.c | 2 +-\n git.c           | 2 +-\n 3 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/alias.c b/alias.c\nindex a7e4e57130..c471538020 100644\n--- a/alias.c\n+++ b/alias.c\n@@ -47,8 +47,8 @@ void list_aliases(struct string_list *list)\n #define SPLIT_CMDLINE_BAD_ENDING 1\n #define SPLIT_CMDLINE_UNCLOSED_QUOTE 2\n static const char *split_cmdline_errors[] = {\n-\t\"cmdline ends with \\\\\",\n-\t\"unclosed quote\"\n+\tN_(\"cmdline ends with \\\\\"),\n+\tN_(\"unclosed quote\")\n };\n \n int split_cmdline(char *cmdline, const char ***argv)\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 4aa6071598..92ba7e1c6d 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -577,7 +577,7 @@ static void parse_branch_merge_options(char *bmo)\n \targc = split_cmdline(bmo, &argv);\n \tif (argc < 0)\n \t\tdie(_(\"Bad branch.%s.mergeoptions string: %s\"), branch,\n-\t\t    split_cmdline_strerror(argc));\n+\t\t    _(split_cmdline_strerror(argc)));\n \tREALLOC_ARRAY(argv, argc + 2);\n \tMOVE_ARRAY(argv + 1, argv, argc + 1);\n \targc++;\ndiff --git a/git.c b/git.c\nindex 1ad565c5c8..09d6169f6c 100644\n--- a/git.c\n+++ b/git.c\n@@ -344,7 +344,7 @@ static int handle_alias(int *argcp, const char ***argv)\n \t\tcount = split_cmdline(alias_string, &new_argv);\n \t\tif (count < 0)\n \t\t\tdie(_(\"bad alias.%s string: %s\"), alias_command,\n-\t\t\t    split_cmdline_strerror(count));\n+\t\t\t    _(split_cmdline_strerror(count)));\n \t\toption_count = handle_options(&new_argv, &count, &envchanged);\n \t\tif (envchanged)\n \t\t\tdie(_(\"alias '%s' changes environment variables.\\n\"\n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361828","messageId":"20181028065157.26727-4-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 03/12] archive.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:48Z","receivedAt":"2018-10-28T06:52:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n archive.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 9d16b7fadf..757519a9d6 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -385,12 +385,12 @@ static void parse_treeish_arg(const char **argv,\n \t\tint refnamelen = colon - name;\n \n \t\tif (!dwim_ref(name, refnamelen, &oid, &ref))\n-\t\t\tdie(\"no such ref: %.*s\", refnamelen, name);\n+\t\t\tdie(_(\"no such ref: %.*s\"), refnamelen, name);\n \t\tfree(ref);\n \t}\n \n \tif (get_oid(name, &oid))\n-\t\tdie(\"Not a valid object name\");\n+\t\tdie(_(\"'%s' is not a valid object name\"), name);\n \n \tcommit = lookup_commit_reference_gently(ar_args->repo, &oid, 1);\n \tif (commit) {\n@@ -403,7 +403,7 @@ static void parse_treeish_arg(const char **argv,\n \n \ttree = parse_tree_indirect(&oid);\n \tif (tree == NULL)\n-\t\tdie(\"not a tree object\");\n+\t\tdie(_(\"%s is not a tree object\"), oid_to_hex(&oid));\n \n \tif (prefix) {\n \t\tstruct object_id tree_oid;\n@@ -413,7 +413,7 @@ static void parse_treeish_arg(const char **argv,\n \t\terr = get_tree_entry(&tree->object.oid, prefix, &tree_oid,\n \t\t\t\t     &mode);\n \t\tif (err || !S_ISDIR(mode))\n-\t\t\tdie(\"current working directory is untracked\");\n+\t\t\tdie(_(\"current working directory is untracked\"));\n \n \t\ttree = parse_tree_indirect(&tree_oid);\n \t}\n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361829","messageId":"20181028065157.26727-5-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 04/12] attr.c: mark more string for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:49Z","receivedAt":"2018-10-28T06:52:10Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n attr.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/attr.c b/attr.c\nindex 60d284796d..4ebc169abe 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -372,7 +372,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,\n \tif (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen &&\n \t    starts_with(name, ATTRIBUTE_MACRO_PREFIX)) {\n \t\tif (!macro_ok) {\n-\t\t\tfprintf(stderr, \"%s not allowed: %s:%d\\n\",\n+\t\t\tfprintf(stderr, _(\"%s not allowed: %s:%d\\n\"),\n \t\t\t\tname, src, lineno);\n \t\t\tgoto fail_return;\n \t\t}\n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361830","messageId":"20181028065157.26727-6-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 05/12] read-cache.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:50Z","receivedAt":"2018-10-28T06:52:12Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"There are a couple other improvements on these strings as well:\n\n - add missing colon (as separator)\n - quote paths\n - provide more information on error messages\n - keep first word in lowercase\n - some die() become BUG()\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n read-cache.c    | 63 +++++++++++++++++++++++++------------------------\n t/t1450-fsck.sh |  2 +-\n 2 files changed, 33 insertions(+), 32 deletions(-)\n\ndiff --git a/read-cache.c b/read-cache.c\nindex d57958233e..5083cd8333 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -316,7 +316,7 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)\n \t\t\tchanged |= DATA_CHANGED;\n \t\treturn changed;\n \tdefault:\n-\t\tdie(\"internal error: ce_mode is %o\", ce->ce_mode);\n+\t\tBUG(\"unsupported ce_mode %o\", ce->ce_mode);\n \t}\n \n \tchanged |= match_stat_data(&ce->ce_stat_data, st);\n@@ -672,7 +672,8 @@ static struct cache_entry *create_alias_ce(struct index_state *istate,\n \tstruct cache_entry *new_entry;\n \n \tif (alias->ce_flags & CE_ADDED)\n-\t\tdie(\"Will not add file alias '%s' ('%s' already exists in index)\", ce->name, alias->name);\n+\t\tdie(_(\"will not add file alias '%s' ('%s' already exists in index)\"),\n+\t\t    ce->name, alias->name);\n \n \t/* Ok, create the new entry using the name of the existing alias */\n \tlen = ce_namelen(alias);\n@@ -687,7 +688,7 @@ void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)\n {\n \tstruct object_id oid;\n \tif (write_object_file(\"\", 0, blob_type, &oid))\n-\t\tdie(\"cannot create an empty blob in the object database\");\n+\t\tdie(_(\"cannot create an empty blob in the object database\"));\n \toidcpy(&ce->oid, &oid);\n }\n \n@@ -708,7 +709,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \t\tnewflags |= HASH_RENORMALIZE;\n \n \tif (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))\n-\t\treturn error(\"%s: can only add regular files, symbolic links or git-directories\", path);\n+\t\treturn error(_(\"%s: can only add regular files, symbolic links or git-directories\"), path);\n \n \tnamelen = strlen(path);\n \tif (S_ISDIR(st_mode)) {\n@@ -763,7 +764,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \tif (!intent_only) {\n \t\tif (index_path(istate, &ce->oid, path, st, newflags)) {\n \t\t\tdiscard_cache_entry(ce);\n-\t\t\treturn error(\"unable to index file %s\", path);\n+\t\t\treturn error(_(\"unable to index file '%s'\"), path);\n \t\t}\n \t} else\n \t\tset_object_name_for_intent_to_add_entry(ce);\n@@ -782,7 +783,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \t\tdiscard_cache_entry(ce);\n \telse if (add_index_entry(istate, ce, add_option)) {\n \t\tdiscard_cache_entry(ce);\n-\t\treturn error(\"unable to add %s to index\", path);\n+\t\treturn error(_(\"unable to add '%s' to index\"), path);\n \t}\n \tif (verbose && !was_same)\n \t\tprintf(\"add '%s'\\n\", path);\n@@ -793,7 +794,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int flags)\n {\n \tstruct stat st;\n \tif (lstat(path, &st))\n-\t\tdie_errno(\"unable to stat '%s'\", path);\n+\t\tdie_errno(_(\"unable to stat '%s'\"), path);\n \treturn add_to_index(istate, path, &st, flags);\n }\n \n@@ -818,7 +819,7 @@ struct cache_entry *make_cache_entry(struct index_state *istate,\n \tint len;\n \n \tif (!verify_path(path, mode)) {\n-\t\terror(\"Invalid path '%s'\", path);\n+\t\terror(_(\"invalid path '%s'\"), path);\n \t\treturn NULL;\n \t}\n \n@@ -844,7 +845,7 @@ struct cache_entry *make_transient_cache_entry(unsigned int mode, const struct o\n \tint len;\n \n \tif (!verify_path(path, mode)) {\n-\t\terror(\"Invalid path '%s'\", path);\n+\t\terror(_(\"invalid path '%s'\"), path);\n \t\treturn NULL;\n \t}\n \n@@ -1297,12 +1298,12 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e\n \tif (!ok_to_add)\n \t\treturn -1;\n \tif (!verify_path(ce->name, ce->ce_mode))\n-\t\treturn error(\"Invalid path '%s'\", ce->name);\n+\t\treturn error(_(\"invalid path '%s'\"), ce->name);\n \n \tif (!skip_df_check &&\n \t    check_file_directory_conflict(istate, ce, pos, ok_to_replace)) {\n \t\tif (!ok_to_replace)\n-\t\t\treturn error(\"'%s' appears as both a file and as a directory\",\n+\t\t\treturn error(_(\"'%s' appears as both a file and as a directory\"),\n \t\t\t\t     ce->name);\n \t\tpos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce));\n \t\tpos = -pos-1;\n@@ -1676,10 +1677,10 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)\n \tint hdr_version;\n \n \tif (hdr->hdr_signature != htonl(CACHE_SIGNATURE))\n-\t\treturn error(\"bad signature\");\n+\t\treturn error(_(\"bad signature 0x%08x\"), hdr->hdr_signature);\n \thdr_version = ntohl(hdr->hdr_version);\n \tif (hdr_version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < hdr_version)\n-\t\treturn error(\"bad index version %d\", hdr_version);\n+\t\treturn error(_(\"bad index version %d\"), hdr_version);\n \n \tif (!verify_index_checksum)\n \t\treturn 0;\n@@ -1688,7 +1689,7 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)\n \tthe_hash_algo->update_fn(&c, hdr, size - the_hash_algo->rawsz);\n \tthe_hash_algo->final_fn(hash, &c);\n \tif (!hasheq(hash, (unsigned char *)hdr + size - the_hash_algo->rawsz))\n-\t\treturn error(\"bad index file sha1 signature\");\n+\t\treturn error(_(\"bad index file sha1 signature\"));\n \treturn 0;\n }\n \n@@ -1718,9 +1719,9 @@ static int read_index_extension(struct index_state *istate,\n \t\tbreak;\n \tdefault:\n \t\tif (*ext < 'A' || 'Z' < *ext)\n-\t\t\treturn error(\"index uses %.4s extension, which we do not understand\",\n+\t\t\treturn error(_(\"index uses %.4s extension, which we do not understand\"),\n \t\t\t\t     ext);\n-\t\tfprintf(stderr, \"ignoring %.4s extension\\n\", ext);\n+\t\tfprintf_ln(stderr, _(\"ignoring %.4s extension\"), ext);\n \t\tbreak;\n \t}\n \treturn 0;\n@@ -1767,7 +1768,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,\n \t\textended_flags = get_be16(&ondisk2->flags2) << 16;\n \t\t/* We do not yet understand any bit out of CE_EXTENDED_FLAGS */\n \t\tif (extended_flags & ~CE_EXTENDED_FLAGS)\n-\t\t\tdie(\"Unknown index entry format %08x\", extended_flags);\n+\t\t\tdie(_(\"unknown index entry format 0x%08x\"), extended_flags);\n \t\tflags |= extended_flags;\n \t\tname = ondisk2->name;\n \t}\n@@ -1840,13 +1841,13 @@ static void check_ce_order(struct index_state *istate)\n \t\tint name_compare = strcmp(ce->name, next_ce->name);\n \n \t\tif (0 < name_compare)\n-\t\t\tdie(\"unordered stage entries in index\");\n+\t\t\tdie(_(\"unordered stage entries in index\"));\n \t\tif (!name_compare) {\n \t\t\tif (!ce_stage(ce))\n-\t\t\t\tdie(\"multiple stage entries for merged file '%s'\",\n+\t\t\t\tdie(_(\"multiple stage entries for merged file '%s'\"),\n \t\t\t\t    ce->name);\n \t\t\tif (ce_stage(ce) > ce_stage(next_ce))\n-\t\t\t\tdie(\"unordered stage entries for '%s'\",\n+\t\t\t\tdie(_(\"unordered stage entries for '%s'\"),\n \t\t\t\t    ce->name);\n \t\t}\n \t}\n@@ -2149,19 +2150,19 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n \tif (fd < 0) {\n \t\tif (!must_exist && errno == ENOENT)\n \t\t\treturn 0;\n-\t\tdie_errno(\"%s: index file open failed\", path);\n+\t\tdie_errno(_(\"%s: index file open failed\"), path);\n \t}\n \n \tif (fstat(fd, &st))\n-\t\tdie_errno(\"cannot stat the open index\");\n+\t\tdie_errno(_(\"%s: cannot stat the open index\"), path);\n \n \tmmap_size = xsize_t(st.st_size);\n \tif (mmap_size < sizeof(struct cache_header) + the_hash_algo->rawsz)\n-\t\tdie(\"index file smaller than expected\");\n+\t\tdie(_(\"%s: index file smaller than expected\"), path);\n \n \tmmap = xmmap(NULL, mmap_size, PROT_READ, MAP_PRIVATE, fd, 0);\n \tif (mmap == MAP_FAILED)\n-\t\tdie_errno(\"unable to map index file\");\n+\t\tdie_errno(_(\"%s: unable to map index file\"), path);\n \tclose(fd);\n \n \thdr = (const struct cache_header *)mmap;\n@@ -2243,7 +2244,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n \n unmap:\n \tmunmap((void *)mmap, mmap_size);\n-\tdie(\"index file corrupt\");\n+\tdie(_(\"index file corrupt\"));\n }\n \n /*\n@@ -2255,7 +2256,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n static void freshen_shared_index(const char *shared_index, int warn)\n {\n \tif (!check_and_freshen_file(shared_index, 1) && warn)\n-\t\twarning(\"could not freshen shared index '%s'\", shared_index);\n+\t\twarning(_(\"could not freshen shared index '%s'\"), shared_index);\n }\n \n int read_index_from(struct index_state *istate, const char *path,\n@@ -2290,7 +2291,7 @@ int read_index_from(struct index_state *istate, const char *path,\n \tbase_path = xstrfmt(\"%s/sharedindex.%s\", gitdir, base_oid_hex);\n \tret = do_read_index(split_index->base, base_path, 1);\n \tif (!oideq(&split_index->base_oid, &split_index->base->oid))\n-\t\tdie(\"broken index, expect %s in %s, got %s\",\n+\t\tdie(_(\"broken index, expect %s in %s, got %s\"),\n \t\t    base_oid_hex, base_path,\n \t\t    oid_to_hex(&split_index->base->oid));\n \n@@ -2356,14 +2357,14 @@ void validate_cache_entries(const struct index_state *istate)\n \n \tfor (i = 0; i < istate->cache_nr; i++) {\n \t\tif (!istate) {\n-\t\t\tdie(\"internal error: cache entry is not allocated from expected memory pool\");\n+\t\t\tBUG(\"cache entry is not allocated from expected memory pool\");\n \t\t} else if (!istate->ce_mem_pool ||\n \t\t\t!mem_pool_contains(istate->ce_mem_pool, istate->cache[i])) {\n \t\t\tif (!istate->split_index ||\n \t\t\t\t!istate->split_index->base ||\n \t\t\t\t!istate->split_index->base->ce_mem_pool ||\n \t\t\t\t!mem_pool_contains(istate->split_index->base->ce_mem_pool, istate->cache[i])) {\n-\t\t\t\tdie(\"internal error: cache entry is not allocated from expected memory pool\");\n+\t\t\t\tBUG(\"cache entry is not allocated from expected memory pool\");\n \t\t\t}\n \t\t}\n \t}\n@@ -3076,7 +3077,7 @@ static int write_shared_index(struct index_state *istate,\n \t\treturn ret;\n \tret = adjust_shared_perm(get_tempfile_path(*temp));\n \tif (ret) {\n-\t\terror(\"cannot fix permission bits on %s\", get_tempfile_path(*temp));\n+\t\terror(_(\"cannot fix permission bits on '%s'\"), get_tempfile_path(*temp));\n \t\treturn ret;\n \t}\n \tret = rename_tempfile(temp,\n@@ -3222,7 +3223,7 @@ int read_index_unmerged(struct index_state *istate)\n \t\tnew_ce->ce_namelen = len;\n \t\tnew_ce->ce_mode = ce->ce_mode;\n \t\tif (add_index_entry(istate, new_ce, ADD_CACHE_SKIP_DFCHECK))\n-\t\t\treturn error(\"%s: cannot drop to stage #0\",\n+\t\t\treturn error(_(\"%s: cannot drop to stage #0\"),\n \t\t\t\t     new_ce->name);\n \t}\n \treturn unmerged;\ndiff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh\nindex 0f2dd26f74..90c765df3a 100755\n--- a/t/t1450-fsck.sh\n+++ b/t/t1450-fsck.sh\n@@ -754,7 +754,7 @@ test_expect_success 'detect corrupt index file in fsck' '\n \ttest_when_finished \"mv .git/index.backup .git/index\" &&\n \tcorrupt_index_checksum &&\n \ttest_must_fail git fsck --cache 2>errors &&\n-\tgrep \"bad index file\" errors\n+\ttest_i18ngrep \"bad index file\" errors\n '\n \n test_done\n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361831","messageId":"20181028065157.26727-7-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 06/12] read-cache.c: add missing colon separators","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:51Z","receivedAt":"2018-10-28T06:52:13Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"typechange_fmt and added_fmt should have a colon before \"needs\nupdate\". Align the statements to make it easier to read and see. Also\ndrop the unnecessary ().\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n read-cache.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/read-cache.c b/read-cache.c\nindex 5083cd8333..02a49e957d 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1492,11 +1492,11 @@ int refresh_index(struct index_state *istate, unsigned int flags,\n \t\t\t\t\t\t  istate->cache_nr);\n \n \ttrace_performance_enter();\n-\tmodified_fmt = (in_porcelain ? \"M\\t%s\\n\" : \"%s: needs update\\n\");\n-\tdeleted_fmt = (in_porcelain ? \"D\\t%s\\n\" : \"%s: needs update\\n\");\n-\ttypechange_fmt = (in_porcelain ? \"T\\t%s\\n\" : \"%s needs update\\n\");\n-\tadded_fmt = (in_porcelain ? \"A\\t%s\\n\" : \"%s needs update\\n\");\n-\tunmerged_fmt = (in_porcelain ? \"U\\t%s\\n\" : \"%s: needs merge\\n\");\n+\tmodified_fmt   = in_porcelain ? \"M\\t%s\\n\" : \"%s: needs update\\n\";\n+\tdeleted_fmt    = in_porcelain ? \"D\\t%s\\n\" : \"%s: needs update\\n\";\n+\ttypechange_fmt = in_porcelain ? \"T\\t%s\\n\" : \"%s: needs update\\n\";\n+\tadded_fmt      = in_porcelain ? \"A\\t%s\\n\" : \"%s: needs update\\n\";\n+\tunmerged_fmt   = in_porcelain ? \"U\\t%s\\n\" : \"%s: needs merge\\n\";\n \tfor (i = 0; i < istate->cache_nr; i++) {\n \t\tstruct cache_entry *ce, *new_entry;\n \t\tint cache_errno = 0;\n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361832","messageId":"20181028065157.26727-8-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 07/12] reflog: mark strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:52Z","receivedAt":"2018-10-28T06:52:15Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/reflog.c | 34 +++++++++++++++++++---------------\n 1 file changed, 19 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex b5941c1ff3..33cb20b7d8 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -13,11 +13,15 @@\n \n /* NEEDSWORK: switch to using parse_options */\n static const char reflog_expire_usage[] =\n-\"git reflog expire [--expire=<time>] [--expire-unreachable=<time>] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] <refs>...\";\n+\tN_(\"git reflog expire [--expire=<time>] \"\n+\t   \"[--expire-unreachable=<time>] \"\n+\t   \"[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] \"\n+\t   \"[--verbose] [--all] <refs>...\");\n static const char reflog_delete_usage[] =\n-\"git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] <refs>...\";\n+\tN_(\"git reflog delete [--rewrite] [--updateref] \"\n+\t   \"[--dry-run | -n] [--verbose] <refs>...\");\n static const char reflog_exists_usage[] =\n-\"git reflog exists <ref>\";\n+\tN_(\"git reflog exists <ref>\");\n \n static timestamp_t default_reflog_expire;\n static timestamp_t default_reflog_expire_unreachable;\n@@ -556,7 +560,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \t\t\tbreak;\n \t\t}\n \t\telse if (arg[0] == '-')\n-\t\t\tusage(reflog_expire_usage);\n+\t\t\tusage(_(reflog_expire_usage));\n \t\telse\n \t\t\tbreak;\n \t}\n@@ -569,7 +573,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \tif (cb.cmd.stalefix) {\n \t\trepo_init_revisions(the_repository, &cb.cmd.revs, prefix);\n \t\tif (flags & EXPIRE_REFLOGS_VERBOSE)\n-\t\t\tprintf(\"Marking reachable objects...\");\n+\t\t\tprintf(_(\"Marking reachable objects...\"));\n \t\tmark_reachable_objects(&cb.cmd.revs, 0, 0, NULL);\n \t\tif (flags & EXPIRE_REFLOGS_VERBOSE)\n \t\t\tputchar('\\n');\n@@ -598,7 +602,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \t\tchar *ref;\n \t\tstruct object_id oid;\n \t\tif (!dwim_log(argv[i], strlen(argv[i]), &oid, &ref)) {\n-\t\t\tstatus |= error(\"%s points nowhere!\", argv[i]);\n+\t\t\tstatus |= error(_(\"%s points nowhere!\"), argv[i]);\n \t\t\tcontinue;\n \t\t}\n \t\tset_reflog_expiry_param(&cb.cmd, explicit_expiry, ref);\n@@ -644,13 +648,13 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)\n \t\t\tbreak;\n \t\t}\n \t\telse if (arg[0] == '-')\n-\t\t\tusage(reflog_delete_usage);\n+\t\t\tusage(_(reflog_delete_usage));\n \t\telse\n \t\t\tbreak;\n \t}\n \n \tif (argc - i < 1)\n-\t\treturn error(\"Nothing to delete?\");\n+\t\treturn error(_(\"nothing to delete?\"));\n \n \tfor ( ; i < argc; i++) {\n \t\tconst char *spec = strstr(argv[i], \"@{\");\n@@ -659,12 +663,12 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)\n \t\tint recno;\n \n \t\tif (!spec) {\n-\t\t\tstatus |= error(\"Not a reflog: %s\", argv[i]);\n+\t\t\tstatus |= error(_(\"not a reflog: %s\"), argv[i]);\n \t\t\tcontinue;\n \t\t}\n \n \t\tif (!dwim_log(argv[i], spec - argv[i], &oid, &ref)) {\n-\t\t\tstatus |= error(\"no reflog for '%s'\", argv[i]);\n+\t\t\tstatus |= error(_(\"no reflog for '%s'\"), argv[i]);\n \t\t\tcontinue;\n \t\t}\n \n@@ -699,7 +703,7 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n \t\t\tbreak;\n \t\t}\n \t\telse if (arg[0] == '-')\n-\t\t\tusage(reflog_exists_usage);\n+\t\t\tusage(_(reflog_exists_usage));\n \t\telse\n \t\t\tbreak;\n \t}\n@@ -707,10 +711,10 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n \tstart = i;\n \n \tif (argc - start != 1)\n-\t\tusage(reflog_exists_usage);\n+\t\tusage(_(reflog_exists_usage));\n \n \tif (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL))\n-\t\tdie(\"invalid ref format: %s\", argv[start]);\n+\t\tdie(_(\"invalid ref format: %s\"), argv[start]);\n \treturn !reflog_exists(argv[start]);\n }\n \n@@ -719,12 +723,12 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n  */\n \n static const char reflog_usage[] =\n-\"git reflog [ show | expire | delete | exists ]\";\n+\tN_(\"git reflog [ show | expire | delete | exists ]\");\n \n int cmd_reflog(int argc, const char **argv, const char *prefix)\n {\n \tif (argc > 1 && !strcmp(argv[1], \"-h\"))\n-\t\tusage(reflog_usage);\n+\t\tusage(_(reflog_usage));\n \n \t/* With no command, we default to showing it. */\n \tif (argc < 2 || *argv[1] == '-')\n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361833","messageId":"20181028065157.26727-10-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 09/12] repack: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:54Z","receivedAt":"2018-10-28T06:52:15Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/repack.c | 26 +++++++++++++-------------\n 1 file changed, 13 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/repack.c b/builtin/repack.c\nindex c6a7943d5c..0af20fa0fc 100644\n--- a/builtin/repack.c\n+++ b/builtin/repack.c\n@@ -197,7 +197,7 @@ static int write_oid(const struct object_id *oid, struct packed_git *pack,\n \n \tif (cmd->in == -1) {\n \t\tif (start_command(cmd))\n-\t\t\tdie(\"Could not start pack-objects to repack promisor objects\");\n+\t\t\tdie(_(\"could not start pack-objects to repack promisor objects\"));\n \t}\n \n \txwrite(cmd->in, oid_to_hex(oid), GIT_SHA1_HEXSZ);\n@@ -236,7 +236,7 @@ static void repack_promisor_objects(const struct pack_objects_args *args,\n \t\tchar *promisor_name;\n \t\tint fd;\n \t\tif (line.len != 40)\n-\t\t\tdie(\"repack: Expecting 40 character sha1 lines only from pack-objects.\");\n+\t\t\tdie(_(\"repack: Expecting 40 character sha1 lines only from pack-objects.\"));\n \t\tstring_list_append(names, line.buf);\n \n \t\t/*\n@@ -247,13 +247,13 @@ static void repack_promisor_objects(const struct pack_objects_args *args,\n \t\t\t\t\t  line.buf);\n \t\tfd = open(promisor_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\tif (fd < 0)\n-\t\t\tdie_errno(\"unable to create '%s'\", promisor_name);\n+\t\t\tdie_errno((\"unable to create '%s'\"), promisor_name);\n \t\tclose(fd);\n \t\tfree(promisor_name);\n \t}\n \tfclose(out);\n \tif (finish_command(&cmd))\n-\t\tdie(\"Could not finish pack-objects to repack promisor objects\");\n+\t\tdie(_(\"could not finish pack-objects to repack promisor objects\"));\n }\n \n #define ALL_INTO_ONE 1\n@@ -408,7 +408,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \tout = xfdopen(cmd.out, \"r\");\n \twhile (strbuf_getline_lf(&line, out) != EOF) {\n \t\tif (line.len != 40)\n-\t\t\tdie(\"repack: Expecting 40 character sha1 lines only from pack-objects.\");\n+\t\t\tdie(_(\"repack: Expecting 40 character sha1 lines only from pack-objects\"));\n \t\tstring_list_append(&names, line.buf);\n \t}\n \tfclose(out);\n@@ -417,7 +417,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\treturn ret;\n \n \tif (!names.nr && !po_args.quiet)\n-\t\tprintf(\"Nothing new to pack.\\n\");\n+\t\tprintf_ln(_(\"Nothing new to pack.\"));\n \n \t/*\n \t * Ok we have prepared all new packfiles.\n@@ -477,13 +477,13 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\tif (rollback_failure.nr) {\n \t\t\tint i;\n \t\t\tfprintf(stderr,\n-\t\t\t\t\"WARNING: Some packs in use have been renamed by\\n\"\n-\t\t\t\t\"WARNING: prefixing old- to their name, in order to\\n\"\n-\t\t\t\t\"WARNING: replace them with the new version of the\\n\"\n-\t\t\t\t\"WARNING: file.  But the operation failed, and the\\n\"\n-\t\t\t\t\"WARNING: attempt to rename them back to their\\n\"\n-\t\t\t\t\"WARNING: original names also failed.\\n\"\n-\t\t\t\t\"WARNING: Please rename them in %s manually:\\n\", packdir);\n+\t\t\t\t_(\"WARNING: Some packs in use have been renamed by\\n\"\n+\t\t\t\t  \"WARNING: prefixing old- to their name, in order to\\n\"\n+\t\t\t\t  \"WARNING: replace them with the new version of the\\n\"\n+\t\t\t\t  \"WARNING: file.  But the operation failed, and the\\n\"\n+\t\t\t\t  \"WARNING: attempt to rename them back to their\\n\"\n+\t\t\t\t  \"WARNING: original names also failed.\\n\"\n+\t\t\t\t  \"WARNING: Please rename them in %s manually:\\n\"), packdir);\n \t\t\tfor (i = 0; i < rollback_failure.nr; i++)\n \t\t\t\tfprintf(stderr, \"WARNING:   old-%s -> %s\\n\",\n \t\t\t\t\trollback_failure.items[i].string,\n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361834","messageId":"20181028065157.26727-9-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 08/12] remote.c: mark messages for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:53Z","receivedAt":"2018-10-28T06:52:18Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n remote.c | 49 +++++++++++++++++++++++++------------------------\n 1 file changed, 25 insertions(+), 24 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex 81f4f01b00..11b33d1625 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -359,7 +359,7 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\treturn 0;\n \t/* Handle remote.<name>.* variables */\n \tif (*name == '/') {\n-\t\twarning(\"Config remote shorthand cannot begin with '/': %s\",\n+\t\twarning(_(\"config remote shorthand cannot begin with '/': %s\"),\n \t\t\tname);\n \t\treturn 0;\n \t}\n@@ -406,7 +406,7 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\tif (!remote->receivepack)\n \t\t\tremote->receivepack = v;\n \t\telse\n-\t\t\terror(\"more than one receivepack given, using the first\");\n+\t\t\terror(_(\"more than one receivepack given, using the first\"));\n \t} else if (!strcmp(subkey, \"uploadpack\")) {\n \t\tconst char *v;\n \t\tif (git_config_string(&v, key, value))\n@@ -414,7 +414,7 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\tif (!remote->uploadpack)\n \t\t\tremote->uploadpack = v;\n \t\telse\n-\t\t\terror(\"more than one uploadpack given, using the first\");\n+\t\t\terror(_(\"more than one uploadpack given, using the first\"));\n \t} else if (!strcmp(subkey, \"tagopt\")) {\n \t\tif (!strcmp(value, \"--no-tags\"))\n \t\t\tremote->fetch_tags = -1;\n@@ -620,7 +620,7 @@ static void handle_duplicate(struct ref *ref1, struct ref *ref2)\n \t\t\t * FETCH_HEAD_IGNORE entries always appear at\n \t\t\t * the end of the list.\n \t\t\t */\n-\t\t\tdie(_(\"Internal error\"));\n+\t\t\tBUG(\"Internal error\");\n \t\t}\n \t}\n \tfree(ref2->peer_ref);\n@@ -680,7 +680,7 @@ static int match_name_with_pattern(const char *key, const char *name,\n \tsize_t namelen;\n \tint ret;\n \tif (!kstar)\n-\t\tdie(\"Key '%s' of pattern had no '*'\", key);\n+\t\tdie(_(\"key '%s' of pattern had no '*'\"), key);\n \tklen = kstar - key;\n \tksuffixlen = strlen(kstar + 1);\n \tnamelen = strlen(name);\n@@ -690,7 +690,7 @@ static int match_name_with_pattern(const char *key, const char *name,\n \t\tstruct strbuf sb = STRBUF_INIT;\n \t\tconst char *vstar = strchr(value, '*');\n \t\tif (!vstar)\n-\t\t\tdie(\"Value '%s' of pattern has no '*'\", value);\n+\t\t\tdie(_(\"value '%s' of pattern has no '*'\"), value);\n \t\tstrbuf_add(&sb, value, vstar - value);\n \t\tstrbuf_add(&sb, name + klen, namelen - klen - ksuffixlen);\n \t\tstrbuf_addstr(&sb, vstar + 1);\n@@ -707,7 +707,7 @@ static void query_refspecs_multiple(struct refspec *rs,\n \tint find_src = !query->src;\n \n \tif (find_src && !query->dst)\n-\t\terror(\"query_refspecs_multiple: need either src or dst\");\n+\t\tBUG(\"query_refspecs_multiple: need either src or dst\");\n \n \tfor (i = 0; i < rs->nr; i++) {\n \t\tstruct refspec_item *refspec = &rs->items[i];\n@@ -735,7 +735,7 @@ int query_refspecs(struct refspec *rs, struct refspec_item *query)\n \tchar **result = find_src ? &query->src : &query->dst;\n \n \tif (find_src && !query->dst)\n-\t\treturn error(\"query_refspecs: need either src or dst\");\n+\t\tBUG(\"query_refspecs: need either src or dst\");\n \n \tfor (i = 0; i < rs->nr; i++) {\n \t\tstruct refspec_item *refspec = &rs->items[i];\n@@ -995,12 +995,12 @@ static int match_explicit_lhs(struct ref *src,\n \t\t * way to delete 'other' ref at the remote end.\n \t\t */\n \t\tif (try_explicit_object_name(rs->src, match) < 0)\n-\t\t\treturn error(\"src refspec %s does not match any.\", rs->src);\n+\t\t\treturn error(_(\"src refspec %s does not match any\"), rs->src);\n \t\tif (allocated_match)\n \t\t\t*allocated_match = 1;\n \t\treturn 0;\n \tdefault:\n-\t\treturn error(\"src refspec %s matches more than one.\", rs->src);\n+\t\treturn error(_(\"src refspec %s matches more than one\"), rs->src);\n \t}\n }\n \n@@ -1030,7 +1030,7 @@ static int match_explicit(struct ref *src, struct ref *dst,\n \t\tif (!dst_value ||\n \t\t    ((flag & REF_ISSYMREF) &&\n \t\t     !starts_with(dst_value, \"refs/heads/\")))\n-\t\t\tdie(\"%s cannot be resolved to branch.\",\n+\t\t\tdie(_(\"%s cannot be resolved to branch\"),\n \t\t\t    matched_src->name);\n \t}\n \n@@ -1041,30 +1041,30 @@ static int match_explicit(struct ref *src, struct ref *dst,\n \t\tif (starts_with(dst_value, \"refs/\"))\n \t\t\tmatched_dst = make_linked_ref(dst_value, dst_tail);\n \t\telse if (is_null_oid(&matched_src->new_oid))\n-\t\t\terror(\"unable to delete '%s': remote ref does not exist\",\n+\t\t\terror(_(\"unable to delete '%s': remote ref does not exist\"),\n \t\t\t      dst_value);\n \t\telse if ((dst_guess = guess_ref(dst_value, matched_src))) {\n \t\t\tmatched_dst = make_linked_ref(dst_guess, dst_tail);\n \t\t\tfree(dst_guess);\n \t\t} else\n-\t\t\terror(\"unable to push to unqualified destination: %s\\n\"\n-\t\t\t      \"The destination refspec neither matches an \"\n-\t\t\t      \"existing ref on the remote nor\\n\"\n-\t\t\t      \"begins with refs/, and we are unable to \"\n-\t\t\t      \"guess a prefix based on the source ref.\",\n+\t\t\terror(_(\"unable to push to unqualified destination: %s\\n\"\n+\t\t\t\t\"The destination refspec neither matches an \"\n+\t\t\t\t\"existing ref on the remote nor\\n\"\n+\t\t\t\t\"begins with refs/, and we are unable to \"\n+\t\t\t\t\"guess a prefix based on the source ref.\"),\n \t\t\t      dst_value);\n \t\tbreak;\n \tdefault:\n \t\tmatched_dst = NULL;\n-\t\terror(\"dst refspec %s matches more than one.\",\n+\t\terror(_(\"dst refspec %s matches more than one\"),\n \t\t      dst_value);\n \t\tbreak;\n \t}\n \tif (!matched_dst)\n \t\treturn -1;\n \tif (matched_dst->peer_ref)\n-\t\treturn error(\"dst ref %s receives from more than one src.\",\n-\t\t      matched_dst->name);\n+\t\treturn error(_(\"dst ref %s receives from more than one src\"),\n+\t\t\t     matched_dst->name);\n \telse {\n \t\tmatched_dst->peer_ref = allocated_src ?\n \t\t\t\t\tmatched_src :\n@@ -1750,7 +1750,7 @@ int get_fetch_map(const struct ref *remote_refs,\n \t\t\tref_map = get_remote_ref(remote_refs, name);\n \t\t}\n \t\tif (!missing_ok && !ref_map)\n-\t\t\tdie(\"Couldn't find remote ref %s\", name);\n+\t\t\tdie(_(\"couldn't find remote ref %s\"), name);\n \t\tif (ref_map) {\n \t\t\tref_map->peer_ref = get_local_ref(refspec->dst);\n \t\t\tif (ref_map->peer_ref && refspec->force)\n@@ -1763,7 +1763,7 @@ int get_fetch_map(const struct ref *remote_refs,\n \t\t\tif (!starts_with((*rmp)->peer_ref->name, \"refs/\") ||\n \t\t\t    check_refname_format((*rmp)->peer_ref->name, 0)) {\n \t\t\t\tstruct ref *ignore = *rmp;\n-\t\t\t\terror(\"* Ignoring funny ref '%s' locally\",\n+\t\t\t\terror(_(\"* Ignoring funny ref '%s' locally\"),\n \t\t\t\t      (*rmp)->peer_ref->name);\n \t\t\t\t*rmp = (*rmp)->next;\n \t\t\t\tfree(ignore->peer_ref);\n@@ -1858,7 +1858,7 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,\n \trepo_init_revisions(the_repository, &revs, NULL);\n \tsetup_revisions(argv.argc, argv.argv, &revs, NULL);\n \tif (prepare_revision_walk(&revs))\n-\t\tdie(\"revision walk setup failed\");\n+\t\tdie(_(\"revision walk setup failed\"));\n \n \t/* ... and count the commits on each side. */\n \twhile (1) {\n@@ -2131,7 +2131,8 @@ static int parse_push_cas_option(struct push_cas_option *cas, const char *arg, i\n \telse if (!colon[1])\n \t\toidclr(&entry->expect);\n \telse if (get_oid(colon + 1, &entry->expect))\n-\t\treturn error(\"cannot parse expected object name '%s'\", colon + 1);\n+\t\treturn error(_(\"cannot parse expected object name '%s'\"),\n+\t\t\t     colon + 1);\n \treturn 0;\n }\n \n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361835","messageId":"20181028065157.26727-12-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 11/12] parse-options.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:56Z","receivedAt":"2018-10-28T06:52:19Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n parse-options.c          | 18 +++++++++---------\n t/t0040-parse-options.sh |  4 ++--\n 2 files changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex 0bf817193d..949aac287f 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -197,7 +197,7 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\treturn 0;\n \n \tdefault:\n-\t\tdie(\"should not happen, someone must be hit on the forehead\");\n+\t\tBUG(\"opt->type %d should not happen, someone must be hit on the forehead\", opt->type);\n \t}\n }\n \n@@ -319,8 +319,8 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,\n \t}\n \n \tif (ambiguous_option) {\n-\t\terror(\"Ambiguous option: %s \"\n-\t\t\t\"(could be --%s%s or --%s%s)\",\n+\t\terror(_(\"ambiguous option: %s \"\n+\t\t\t\"(could be --%s%s or --%s%s)\"),\n \t\t\targ,\n \t\t\t(ambiguous_flags & OPT_UNSET) ?  \"no-\" : \"\",\n \t\t\tambiguous_option->long_name,\n@@ -353,7 +353,7 @@ static void check_typos(const char *arg, const struct option *options)\n \t\treturn;\n \n \tif (starts_with(arg, \"no-\")) {\n-\t\terror (\"did you mean `--%s` (with two dashes ?)\", arg);\n+\t\terror(_(\"did you mean `--%s` (with two dashes ?)\"), arg);\n \t\texit(129);\n \t}\n \n@@ -361,7 +361,7 @@ static void check_typos(const char *arg, const struct option *options)\n \t\tif (!options->long_name)\n \t\t\tcontinue;\n \t\tif (starts_with(options->long_name, arg)) {\n-\t\t\terror (\"did you mean `--%s` (with two dashes ?)\", arg);\n+\t\t\terror(_(\"did you mean `--%s` (with two dashes ?)\"), arg);\n \t\t\texit(129);\n \t\t}\n \t}\n@@ -424,7 +424,7 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,\n \tctx->flags = flags;\n \tif ((flags & PARSE_OPT_KEEP_UNKNOWN) &&\n \t    (flags & PARSE_OPT_STOP_AT_NON_OPTION))\n-\t\tdie(\"STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together\");\n+\t\tBUG(\"STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together\");\n \tparse_options_check(options);\n }\n \n@@ -644,11 +644,11 @@ int parse_options(int argc, const char **argv, const char *prefix,\n \t\tbreak;\n \tdefault: /* PARSE_OPT_UNKNOWN */\n \t\tif (ctx.argv[0][1] == '-') {\n-\t\t\terror(\"unknown option `%s'\", ctx.argv[0] + 2);\n+\t\t\terror(_(\"unknown option `%s'\"), ctx.argv[0] + 2);\n \t\t} else if (isascii(*ctx.opt)) {\n-\t\t\terror(\"unknown switch `%c'\", *ctx.opt);\n+\t\t\terror(_(\"unknown switch `%c'\"), *ctx.opt);\n \t\t} else {\n-\t\t\terror(\"unknown non-ascii option in string: `%s'\",\n+\t\t\terror(_(\"unknown non-ascii option in string: `%s'\"),\n \t\t\t      ctx.argv[0]);\n \t\t}\n \t\tusage_with_options(usagestr, options);\ndiff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh\nindex 17d0c18feb..e46b1e02f0 100755\n--- a/t/t0040-parse-options.sh\n+++ b/t/t0040-parse-options.sh\n@@ -228,7 +228,7 @@ EOF\n test_expect_success 'detect possible typos' '\n \ttest_must_fail test-tool parse-options -boolean >output 2>output.err &&\n \ttest_must_be_empty output &&\n-\ttest_cmp typo.err output.err\n+\ttest_i18ncmp typo.err output.err\n '\n \n cat >typo.err <<\\EOF\n@@ -238,7 +238,7 @@ EOF\n test_expect_success 'detect possible typos' '\n \ttest_must_fail test-tool parse-options -ambiguous >output 2>output.err &&\n \ttest_must_be_empty output &&\n-\ttest_cmp typo.err output.err\n+\ttest_i18ncmp typo.err output.err\n '\n \n test_expect_success 'keep some options as arguments' '\n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361836","messageId":"20181028065157.26727-11-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 10/12] parse-options: replace opterror() with optname()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:55Z","receivedAt":"2018-10-28T06:52:19Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"There are a few issues with opterror()\n\n- it tries to assemble an English sentence from pieces. This is not\n  great for translators because we give them pieces instead of a full\n  sentence.\n\n- It's a wrapper around error() and needs some hack to let the\n  compiler know it always returns -1.\n\n- Since it takes a string instead of printf format, one call site has\n  to assemble the string manually before passing to it.\n\nKill it and produce the option name with optname(). The user will use\nerror() directly. This solves the second and third problems.\n\nIt kind helps the first problem as well because \"%s does foo\" does\ngive a translator a full sentence in a sense and let them reorder if\nneeded. But it has limitations, if the subject part has to change\nbased on the rest of the sentence, that language is screwed. This is\nalso why I try to avoid calling optname() when 'flags' is known in\nadvance.\n\nMark of these strings for translation as well while at there.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/merge.c     |  2 +-\n builtin/revert.c    |  3 ++-\n parse-options-cb.c  |  7 ++++---\n parse-options.c     | 46 +++++++++++++++++++++++++--------------------\n parse-options.h     |  5 +----\n ref-filter.c        |  8 +++++---\n t/t4211-line-log.sh |  2 +-\n 7 files changed, 40 insertions(+), 33 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 92ba7e1c6d..82248d43c3 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -128,7 +128,7 @@ static int option_read_message(struct parse_opt_ctx_t *ctx,\n \t\tctx->argc--;\n \t\targ = *++ctx->argv;\n \t} else\n-\t\treturn opterror(opt, \"requires a value\", 0);\n+\t\treturn error(_(\"option `%s' requires a value\"), opt->long_name);\n \n \tif (buf->len)\n \t\tstrbuf_addch(buf, '\\n');\ndiff --git a/builtin/revert.c b/builtin/revert.c\nindex c93393c89b..11190d2ab4 100644\n--- a/builtin/revert.c\n+++ b/builtin/revert.c\n@@ -69,7 +69,8 @@ static int option_parse_m(const struct option *opt,\n \n \treplay->mainline = strtol(arg, &end, 10);\n \tif (*end || replay->mainline <= 0)\n-\t\treturn opterror(opt, \"expects a number greater than zero\", 0);\n+\t\treturn error(_(\"option `%s' expects a number greater than zero\"),\n+\t\t\t     opt->long_name);\n \n \treturn 0;\n }\ndiff --git a/parse-options-cb.c b/parse-options-cb.c\nindex e8236534ac..813eb6301b 100644\n--- a/parse-options-cb.c\n+++ b/parse-options-cb.c\n@@ -18,7 +18,8 @@ int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)\n \t} else {\n \t\tv = strtol(arg, (char **)&arg, 10);\n \t\tif (*arg)\n-\t\t\treturn opterror(opt, \"expects a numerical value\", 0);\n+\t\t\treturn error(_(\"option `%s' expects a numerical value\"),\n+\t\t\t\t     opt->long_name);\n \t\tif (v && v < MINIMUM_ABBREV)\n \t\t\tv = MINIMUM_ABBREV;\n \t\telse if (v > 40)\n@@ -54,8 +55,8 @@ int parse_opt_color_flag_cb(const struct option *opt, const char *arg,\n \t\targ = unset ? \"never\" : (const char *)opt->defval;\n \tvalue = git_config_colorbool(NULL, arg);\n \tif (value < 0)\n-\t\treturn opterror(opt,\n-\t\t\t\"expects \\\"always\\\", \\\"auto\\\", or \\\"never\\\"\", 0);\n+\t\treturn error(_(\"option `%s' expects \\\"always\\\", \\\"auto\\\", or \\\"never\\\"\"),\n+\t\t\t     opt->long_name);\n \t*(int *)opt->value = value;\n \treturn 0;\n }\ndiff --git a/parse-options.c b/parse-options.c\nindex 3b874a83a0..0bf817193d 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -32,7 +32,7 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,\n \t\tp->argc--;\n \t\t*arg = *++p->argv;\n \t} else\n-\t\treturn opterror(opt, \"requires a value\", flags);\n+\t\treturn error(_(\"%s requires a value\"), optname(opt, flags));\n \treturn 0;\n }\n \n@@ -49,7 +49,6 @@ static int opt_command_mode_error(const struct option *opt,\n \t\t\t\t  int flags)\n {\n \tconst struct option *that;\n-\tstruct strbuf message = STRBUF_INIT;\n \tstruct strbuf that_name = STRBUF_INIT;\n \n \t/*\n@@ -67,13 +66,13 @@ static int opt_command_mode_error(const struct option *opt,\n \t\t\tstrbuf_addf(&that_name, \"--%s\", that->long_name);\n \t\telse\n \t\t\tstrbuf_addf(&that_name, \"-%c\", that->short_name);\n-\t\tstrbuf_addf(&message, \": incompatible with %s\", that_name.buf);\n+\t\terror(_(\"%s is incompatible with %s\"),\n+\t\t      optname(opt, flags), that_name.buf);\n \t\tstrbuf_release(&that_name);\n-\t\topterror(opt, message.buf, flags);\n-\t\tstrbuf_release(&message);\n \t\treturn -1;\n \t}\n-\treturn opterror(opt, \": incompatible with something else\", flags);\n+\treturn error(_(\"%s : incompatible with something else\"),\n+\t\t     optname(opt, flags));\n }\n \n static int get_value(struct parse_opt_ctx_t *p,\n@@ -86,11 +85,11 @@ static int get_value(struct parse_opt_ctx_t *p,\n \tint err;\n \n \tif (unset && p->opt)\n-\t\treturn opterror(opt, \"takes no value\", flags);\n+\t\treturn error(_(\"%s takes no value\"), optname(opt, flags));\n \tif (unset && (opt->flags & PARSE_OPT_NONEG))\n-\t\treturn opterror(opt, \"isn't available\", flags);\n+\t\treturn error(_(\"%s isn't available\"), optname(opt, flags));\n \tif (!(flags & OPT_SHORT) && p->opt && (opt->flags & PARSE_OPT_NOARG))\n-\t\treturn opterror(opt, \"takes no value\", flags);\n+\t\treturn error(_(\"%s takes no value\"), optname(opt, flags));\n \n \tswitch (opt->type) {\n \tcase OPTION_LOWLEVEL_CALLBACK:\n@@ -176,7 +175,8 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\t\treturn -1;\n \t\t*(int *)opt->value = strtol(arg, (char **)&s, 10);\n \t\tif (*s)\n-\t\t\treturn opterror(opt, \"expects a numerical value\", flags);\n+\t\t\treturn error(_(\"%s expects a numerical value\"),\n+\t\t\t\t     optname(opt, flags));\n \t\treturn 0;\n \n \tcase OPTION_MAGNITUDE:\n@@ -191,9 +191,9 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\tif (get_arg(p, opt, flags, &arg))\n \t\t\treturn -1;\n \t\tif (!git_parse_ulong(arg, opt->value))\n-\t\t\treturn opterror(opt,\n-\t\t\t\t\"expects a non-negative integer value with an optional k/m/g suffix\",\n-\t\t\t\tflags);\n+\t\t\treturn error(_(\"%s expects a non-negative integer value\"\n+\t\t\t\t       \" with an optional k/m/g suffix\"),\n+\t\t\t\t     optname(opt, flags));\n \t\treturn 0;\n \n \tdefault:\n@@ -257,7 +257,8 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,\n \t\t\tif (!rest)\n \t\t\t\tcontinue;\n \t\t\tif (*rest == '=')\n-\t\t\t\treturn opterror(options, \"takes no value\", flags);\n+\t\t\t\treturn error(_(\"%s takes no value\"),\n+\t\t\t\t\t     optname(options, flags));\n \t\t\tif (*rest)\n \t\t\t\tcontinue;\n \t\t\tp->out[p->cpidx++] = arg - 2;\n@@ -773,12 +774,17 @@ void NORETURN usage_msg_opt(const char *msg,\n \tusage_with_options(usagestr, options);\n }\n \n-#undef opterror\n-int opterror(const struct option *opt, const char *reason, int flags)\n+const char *optname(const struct option *opt, int flags)\n {\n+\tstatic struct strbuf sb = STRBUF_INIT;\n+\n+\tstrbuf_reset(&sb);\n \tif (flags & OPT_SHORT)\n-\t\treturn error(\"switch `%c' %s\", opt->short_name, reason);\n-\tif (flags & OPT_UNSET)\n-\t\treturn error(\"option `no-%s' %s\", opt->long_name, reason);\n-\treturn error(\"option `%s' %s\", opt->long_name, reason);\n+\t\tstrbuf_addf(&sb, \"switch `%c'\", opt->short_name);\n+\telse if (flags & OPT_UNSET)\n+\t\tstrbuf_addf(&sb, \"option `no-%s'\", opt->long_name);\n+\telse\n+\t\tstrbuf_addf(&sb, \"option `%s'\", opt->long_name);\n+\n+\treturn sb.buf;\n }\ndiff --git a/parse-options.h b/parse-options.h\nindex dd14911a29..2e146aa6fa 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -189,10 +189,7 @@ extern NORETURN void usage_msg_opt(const char *msg,\n \t\t\t\t   const struct option *options);\n \n extern int optbug(const struct option *opt, const char *reason);\n-extern int opterror(const struct option *opt, const char *reason, int flags);\n-#if defined(__GNUC__)\n-#define opterror(o,r,f) (opterror((o),(r),(f)), const_error())\n-#endif\n+const char *optname(const struct option *opt, int flags);\n \n /*----- incremental advanced APIs -----*/\n \ndiff --git a/ref-filter.c b/ref-filter.c\nindex 2a05619211..0681359100 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -2302,9 +2302,11 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n \n \tif (rf->merge) {\n \t\tif (no_merged) {\n-\t\t\treturn opterror(opt, \"is incompatible with --merged\", 0);\n+\t\t\treturn error(_(\"option `%s' is incompatible with --merged\"),\n+\t\t\t\t     opt->long_name);\n \t\t} else {\n-\t\t\treturn opterror(opt, \"is incompatible with --no-merged\", 0);\n+\t\t\treturn error(_(\"option `%s' is incompatible with --no-merged\"),\n+\t\t\t\t     opt->long_name);\n \t\t}\n \t}\n \n@@ -2318,7 +2320,7 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n \trf->merge_commit = lookup_commit_reference_gently(the_repository,\n \t\t\t\t\t\t\t  &oid, 0);\n \tif (!rf->merge_commit)\n-\t\treturn opterror(opt, \"must point to a commit\", 0);\n+\t\treturn error(_(\"option `%s' must point to a commit\"), opt->long_name);\n \n \treturn 0;\n }\ndiff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh\nindex ef1322148e..bd5fe4d148 100755\n--- a/t/t4211-line-log.sh\n+++ b/t/t4211-line-log.sh\n@@ -25,7 +25,7 @@ canned_test_failure () {\n test_bad_opts () {\n \ttest_expect_success \"invalid args: $1\" \"\n \t\ttest_must_fail git log $1 2>errors &&\n-\t\tgrep '$2' errors\n+\t\ttest_i18ngrep '$2' errors\n \t\"\n }\n \n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361837","messageId":"20181028065157.26727-13-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH 12/12] fsck: mark strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-28T06:51:57Z","receivedAt":"2018-10-28T06:52:21Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/fsck.c             | 113 ++++++++++++++++++++-----------------\n t/t1410-reflog.sh          |   6 +-\n t/t1450-fsck.sh            |  50 ++++++++--------\n t/t6050-replace.sh         |   4 +-\n t/t7415-submodule-names.sh |   6 +-\n 5 files changed, 94 insertions(+), 85 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex 06eb421720..13f8fe35c5 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -108,8 +108,9 @@ static int fsck_config(const char *var, const char *value, void *cb)\n static void objreport(struct object *obj, const char *msg_type,\n \t\t\tconst char *err)\n {\n-\tfprintf(stderr, \"%s in %s %s: %s\\n\",\n-\t\tmsg_type, printable_type(obj), describe_object(obj), err);\n+\tfprintf_ln(stderr, _(\"%s in %s %s: %s\"),\n+\t\t   msg_type, printable_type(obj),\n+\t\t   describe_object(obj), err);\n }\n \n static int objerror(struct object *obj, const char *err)\n@@ -139,17 +140,18 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt\n \t */\n \tif (!obj) {\n \t\t/* ... these references to parent->fld are safe here */\n-\t\tprintf(\"broken link from %7s %s\\n\",\n-\t\t\t   printable_type(parent), describe_object(parent));\n-\t\tprintf(\"broken link from %7s %s\\n\",\n-\t\t\t   (type == OBJ_ANY ? \"unknown\" : type_name(type)), \"unknown\");\n+\t\tprintf_ln(_(\"broken link from %7s %s\"),\n+\t\t\t  printable_type(parent), describe_object(parent));\n+\t\tprintf_ln(_(\"broken link from %7s %s\"),\n+\t\t\t  (type == OBJ_ANY ? _(\"unknown\") : type_name(type)),\n+\t\t\t  _(\"unknown\"));\n \t\terrors_found |= ERROR_REACHABLE;\n \t\treturn 1;\n \t}\n \n \tif (type != OBJ_ANY && obj->type != type)\n \t\t/* ... and the reference to parent is safe here */\n-\t\tobjerror(parent, \"wrong object type in link\");\n+\t\tobjerror(parent, _(\"wrong object type in link\"));\n \n \tif (obj->flags & REACHABLE)\n \t\treturn 0;\n@@ -165,10 +167,12 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt\n \n \tif (!(obj->flags & HAS_OBJ)) {\n \t\tif (parent && !has_object_file(&obj->oid)) {\n-\t\t\tprintf(\"broken link from %7s %s\\n\",\n-\t\t\t\t printable_type(parent), describe_object(parent));\n-\t\t\tprintf(\"              to %7s %s\\n\",\n-\t\t\t\t printable_type(obj), describe_object(obj));\n+\t\t\tprintf_ln(_(\"broken link from %7s %s\\n\"\n+\t\t\t\t    \"              to %7s %s\"),\n+\t\t\t\t  printable_type(parent),\n+\t\t\t\t  describe_object(parent),\n+\t\t\t\t  printable_type(obj),\n+\t\t\t\t  describe_object(obj));\n \t\t\terrors_found |= ERROR_REACHABLE;\n \t\t}\n \t\treturn 1;\n@@ -232,8 +236,8 @@ static void check_reachable_object(struct object *obj)\n \t\t\treturn;\n \t\tif (has_object_pack(&obj->oid))\n \t\t\treturn; /* it is in pack - forget about it */\n-\t\tprintf(\"missing %s %s\\n\", printable_type(obj),\n-\t\t\tdescribe_object(obj));\n+\t\tprintf_ln(_(\"missing %s %s\"), printable_type(obj),\n+\t\t\t  describe_object(obj));\n \t\terrors_found |= ERROR_REACHABLE;\n \t\treturn;\n \t}\n@@ -258,8 +262,8 @@ static void check_unreachable_object(struct object *obj)\n \t * since this is something that is prunable.\n \t */\n \tif (show_unreachable) {\n-\t\tprintf(\"unreachable %s %s\\n\", printable_type(obj),\n-\t\t\tdescribe_object(obj));\n+\t\tprintf_ln(_(\"unreachable %s %s\"), printable_type(obj),\n+\t\t\t  describe_object(obj));\n \t\treturn;\n \t}\n \n@@ -277,8 +281,8 @@ static void check_unreachable_object(struct object *obj)\n \t */\n \tif (!(obj->flags & USED)) {\n \t\tif (show_dangling)\n-\t\t\tprintf(\"dangling %s %s\\n\", printable_type(obj),\n-\t\t\t       describe_object(obj));\n+\t\t\tprintf_ln(_(\"dangling %s %s\"), printable_type(obj),\n+\t\t\t\t  describe_object(obj));\n \t\tif (write_lost_and_found) {\n \t\t\tchar *filename = git_pathdup(\"lost-found/%s/%s\",\n \t\t\t\tobj->type == OBJ_COMMIT ? \"commit\" : \"other\",\n@@ -286,18 +290,18 @@ static void check_unreachable_object(struct object *obj)\n \t\t\tFILE *f;\n \n \t\t\tif (safe_create_leading_directories_const(filename)) {\n-\t\t\t\terror(\"Could not create lost-found\");\n+\t\t\t\terror(_(\"could not create lost-found\"));\n \t\t\t\tfree(filename);\n \t\t\t\treturn;\n \t\t\t}\n \t\t\tf = xfopen(filename, \"w\");\n \t\t\tif (obj->type == OBJ_BLOB) {\n \t\t\t\tif (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1))\n-\t\t\t\t\tdie_errno(\"Could not write '%s'\", filename);\n+\t\t\t\t\tdie_errno(_(\"could not write '%s'\"), filename);\n \t\t\t} else\n \t\t\t\tfprintf(f, \"%s\\n\", describe_object(obj));\n \t\t\tif (fclose(f))\n-\t\t\t\tdie_errno(\"Could not finish '%s'\",\n+\t\t\t\tdie_errno(_(\"could not finish '%s'\"),\n \t\t\t\t\t  filename);\n \t\t\tfree(filename);\n \t\t}\n@@ -314,7 +318,7 @@ static void check_unreachable_object(struct object *obj)\n static void check_object(struct object *obj)\n {\n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking %s\\n\", describe_object(obj));\n+\t\tfprintf_ln(stderr, _(\"Checking %s\"), describe_object(obj));\n \n \tif (obj->flags & REACHABLE)\n \t\tcheck_reachable_object(obj);\n@@ -332,7 +336,7 @@ static void check_connectivity(void)\n \t/* Look up all the requirements, warn about missing objects.. */\n \tmax = get_max_object_index();\n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking connectivity (%d objects)\\n\", max);\n+\t\tfprintf_ln(stderr, _(\"Checking connectivity (%d objects)\"), max);\n \n \tfor (i = 0; i < max; i++) {\n \t\tstruct object *obj = get_indexed_object(i);\n@@ -351,11 +355,11 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)\n \tobj->flags |= SEEN;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking %s %s\\n\",\n-\t\t\tprintable_type(obj), describe_object(obj));\n+\t\tfprintf_ln(stderr, _(\"Checking %s %s\"),\n+\t\t\t   printable_type(obj), describe_object(obj));\n \n \tif (fsck_walk(obj, NULL, &fsck_obj_options))\n-\t\tobjerror(obj, \"broken links\");\n+\t\tobjerror(obj, _(\"broken links\"));\n \terr = fsck_object(obj, buffer, size, &fsck_obj_options);\n \tif (err)\n \t\tgoto out;\n@@ -364,17 +368,19 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)\n \t\tstruct commit *commit = (struct commit *) obj;\n \n \t\tif (!commit->parents && show_root)\n-\t\t\tprintf(\"root %s\\n\", describe_object(&commit->object));\n+\t\t\tprintf_ln(_(\"root %s\"),\n+\t\t\t\t  describe_object(&commit->object));\n \t}\n \n \tif (obj->type == OBJ_TAG) {\n \t\tstruct tag *tag = (struct tag *) obj;\n \n \t\tif (show_tags && tag->tagged) {\n-\t\t\tprintf(\"tagged %s %s\", printable_type(tag->tagged),\n-\t\t\t\tdescribe_object(tag->tagged));\n-\t\t\tprintf(\" (%s) in %s\\n\", tag->tag,\n-\t\t\t\tdescribe_object(&tag->object));\n+\t\t\tprintf(_(\"tagged %s %s (%s) in %s\"),\n+\t\t\t       printable_type(tag->tagged),\n+\t\t\t       describe_object(tag->tagged),\n+\t\t\t       tag->tag,\n+\t\t\t       describe_object(&tag->object));\n \t\t}\n \t}\n \n@@ -398,7 +404,8 @@ static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,\n \t\t\t\t  eaten);\n \tif (!obj) {\n \t\terrors_found |= ERROR_OBJECT;\n-\t\treturn error(\"%s: object corrupt or missing\", oid_to_hex(oid));\n+\t\treturn error(_(\"%s: object corrupt or missing\"),\n+\t\t\t     oid_to_hex(oid));\n \t}\n \tobj->flags &= ~(REACHABLE | SEEN);\n \tobj->flags |= HAS_OBJ;\n@@ -422,7 +429,8 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,\n \t\t\tobj->flags |= USED;\n \t\t\tmark_object_reachable(obj);\n \t\t} else if (!is_promisor_object(oid)) {\n-\t\t\terror(\"%s: invalid reflog entry %s\", refname, oid_to_hex(oid));\n+\t\t\terror(_(\"%s: invalid reflog entry %s\"),\n+\t\t\t      refname, oid_to_hex(oid));\n \t\t\terrors_found |= ERROR_REACHABLE;\n \t\t}\n \t}\n@@ -435,8 +443,8 @@ static int fsck_handle_reflog_ent(struct object_id *ooid, struct object_id *noid\n \tconst char *refname = cb_data;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking reflog %s->%s\\n\",\n-\t\t\toid_to_hex(ooid), oid_to_hex(noid));\n+\t\tfprintf_ln(stderr, _(\"Checking reflog %s->%s\"),\n+\t\t\t   oid_to_hex(ooid), oid_to_hex(noid));\n \n \tfsck_handle_reflog_oid(refname, ooid, 0);\n \tfsck_handle_reflog_oid(refname, noid, timestamp);\n@@ -465,13 +473,14 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid,\n \t\t\t default_refs++;\n \t\t\t return 0;\n \t\t}\n-\t\terror(\"%s: invalid sha1 pointer %s\", refname, oid_to_hex(oid));\n+\t\terror(_(\"%s: invalid sha1 pointer %s\"),\n+\t\t      refname, oid_to_hex(oid));\n \t\terrors_found |= ERROR_REACHABLE;\n \t\t/* We'll continue with the rest despite the error.. */\n \t\treturn 0;\n \t}\n \tif (obj->type != OBJ_COMMIT && is_branch(refname)) {\n-\t\terror(\"%s: not a commit\", refname);\n+\t\terror(_(\"%s: not a commit\"), refname);\n \t\terrors_found |= ERROR_REFS;\n \t}\n \tdefault_refs++;\n@@ -505,7 +514,7 @@ static void get_default_heads(void)\n \t * \"show_unreachable\" flag.\n \t */\n \tif (!default_refs) {\n-\t\tfprintf(stderr, \"notice: No default references\\n\");\n+\t\tfprintf_ln(stderr, _(\"notice: No default references\"));\n \t\tshow_unreachable = 0;\n \t}\n }\n@@ -520,7 +529,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n \n \tif (read_loose_object(path, oid, &type, &size, &contents) < 0) {\n \t\terrors_found |= ERROR_OBJECT;\n-\t\terror(\"%s: object corrupt or missing: %s\",\n+\t\terror(_(\"%s: object corrupt or missing: %s\"),\n \t\t      oid_to_hex(oid), path);\n \t\treturn 0; /* keep checking other objects */\n \t}\n@@ -533,7 +542,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n \n \tif (!obj) {\n \t\terrors_found |= ERROR_OBJECT;\n-\t\terror(\"%s: object could not be parsed: %s\",\n+\t\terror(_(\"%s: object could not be parsed: %s\"),\n \t\t      oid_to_hex(oid), path);\n \t\tif (!eaten)\n \t\t\tfree(contents);\n@@ -553,7 +562,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n static int fsck_cruft(const char *basename, const char *path, void *data)\n {\n \tif (!starts_with(basename, \"tmp_obj_\"))\n-\t\tfprintf(stderr, \"bad sha1 file: %s\\n\", path);\n+\t\tfprintf_ln(stderr, _(\"bad sha1 file: %s\"), path);\n \treturn 0;\n }\n \n@@ -568,7 +577,7 @@ static void fsck_object_dir(const char *path)\n \tstruct progress *progress = NULL;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking object directory\\n\");\n+\t\tfprintf_ln(stderr, _(\"Checking object directory\"));\n \n \tif (show_progress)\n \t\tprogress = start_progress(_(\"Checking object directories\"), 256);\n@@ -584,28 +593,28 @@ static int fsck_head_link(void)\n \tint null_is_error = 0;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking HEAD link\\n\");\n+\t\tfprintf_ln(stderr, _(\"Checking HEAD link\"));\n \n \thead_points_at = resolve_ref_unsafe(\"HEAD\", 0, &head_oid, NULL);\n \tif (!head_points_at) {\n \t\terrors_found |= ERROR_REFS;\n-\t\treturn error(\"Invalid HEAD\");\n+\t\treturn error(_(\"invalid HEAD\"));\n \t}\n \tif (!strcmp(head_points_at, \"HEAD\"))\n \t\t/* detached HEAD */\n \t\tnull_is_error = 1;\n \telse if (!starts_with(head_points_at, \"refs/heads/\")) {\n \t\terrors_found |= ERROR_REFS;\n-\t\treturn error(\"HEAD points to something strange (%s)\",\n+\t\treturn error(_(\"HEAD points to something strange (%s)\"),\n \t\t\t     head_points_at);\n \t}\n \tif (is_null_oid(&head_oid)) {\n \t\tif (null_is_error) {\n \t\t\terrors_found |= ERROR_REFS;\n-\t\t\treturn error(\"HEAD: detached HEAD points at nothing\");\n+\t\t\treturn error(_(\"HEAD: detached HEAD points at nothing\"));\n \t\t}\n-\t\tfprintf(stderr, \"notice: HEAD points to an unborn branch (%s)\\n\",\n-\t\t\thead_points_at + 11);\n+\t\tfprintf_ln(stderr, _(\"notice: HEAD points to an unborn branch (%s)\"),\n+\t\t\t   head_points_at + 11);\n \t}\n \treturn 0;\n }\n@@ -616,12 +625,12 @@ static int fsck_cache_tree(struct cache_tree *it)\n \tint err = 0;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking cache tree\\n\");\n+\t\tfprintf_ln(stderr, _(\"Checking cache tree\"));\n \n \tif (0 <= it->entry_count) {\n \t\tstruct object *obj = parse_object(the_repository, &it->oid);\n \t\tif (!obj) {\n-\t\t\terror(\"%s: invalid sha1 pointer in cache-tree\",\n+\t\t\terror(_(\"%s: invalid sha1 pointer in cache-tree\"),\n \t\t\t      oid_to_hex(&it->oid));\n \t\t\terrors_found |= ERROR_REFS;\n \t\t\treturn 1;\n@@ -632,7 +641,7 @@ static int fsck_cache_tree(struct cache_tree *it)\n \t\t\t\tobj, xstrdup(\":\"));\n \t\tmark_object_reachable(obj);\n \t\tif (obj->type != OBJ_TREE)\n-\t\t\terr |= objerror(obj, \"non-tree in cache-tree\");\n+\t\t\terr |= objerror(obj, _(\"non-tree in cache-tree\"));\n \t}\n \tfor (i = 0; i < it->subtree_nr; i++)\n \t\terr |= fsck_cache_tree(it->down[i]->cache_tree);\n@@ -774,7 +783,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \t\t\tif (!obj || !(obj->flags & HAS_OBJ)) {\n \t\t\t\tif (is_promisor_object(&oid))\n \t\t\t\t\tcontinue;\n-\t\t\t\terror(\"%s: object missing\", oid_to_hex(&oid));\n+\t\t\t\terror(_(\"%s: object missing\"), oid_to_hex(&oid));\n \t\t\t\terrors_found |= ERROR_OBJECT;\n \t\t\t\tcontinue;\n \t\t\t}\n@@ -786,7 +795,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \t\t\tmark_object_reachable(obj);\n \t\t\tcontinue;\n \t\t}\n-\t\terror(\"invalid parameter: expected sha1, got '%s'\", arg);\n+\t\terror(_(\"invalid parameter: expected sha1, got '%s'\"), arg);\n \t\terrors_found |= ERROR_OBJECT;\n \t}\n \ndiff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh\nindex 388b0611d8..353bdfd415 100755\n--- a/t/t1410-reflog.sh\n+++ b/t/t1410-reflog.sh\n@@ -20,12 +20,12 @@ check_have () {\n }\n \n check_fsck () {\n-\toutput=$(git fsck --full)\n+\tgit fsck --full >fsck.output\n \tcase \"$1\" in\n \t'')\n-\t\ttest -z \"$output\" ;;\n+\t\ttest_must_be_empty fsck.output ;;\n \t*)\n-\t\techo \"$output\" | grep \"$1\" ;;\n+\t\ttest_i18ngrep \"$1\" fsck.output ;;\n \tesac\n }\n \ndiff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh\nindex 90c765df3a..500c21366e 100755\n--- a/t/t1450-fsck.sh\n+++ b/t/t1450-fsck.sh\n@@ -70,7 +70,7 @@ test_expect_success 'object with bad sha1' '\n \n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"$sha.*corrupt\" out\n+\ttest_i18ngrep \"$sha.*corrupt\" out\n '\n \n test_expect_success 'branch pointing to non-commit' '\n@@ -78,7 +78,7 @@ test_expect_success 'branch pointing to non-commit' '\n \ttest_when_finished \"git update-ref -d refs/heads/invalid\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"not a commit\" out\n+\ttest_i18ngrep \"not a commit\" out\n '\n \n test_expect_success 'HEAD link pointing at a funny object' '\n@@ -88,7 +88,7 @@ test_expect_success 'HEAD link pointing at a funny object' '\n \t# avoid corrupt/broken HEAD from interfering with repo discovery\n \ttest_must_fail env GIT_DIR=.git git fsck 2>out &&\n \tcat out &&\n-\tgrep \"detached HEAD points\" out\n+\ttest_i18ngrep \"detached HEAD points\" out\n '\n \n test_expect_success 'HEAD link pointing at a funny place' '\n@@ -98,7 +98,7 @@ test_expect_success 'HEAD link pointing at a funny place' '\n \t# avoid corrupt/broken HEAD from interfering with repo discovery\n \ttest_must_fail env GIT_DIR=.git git fsck 2>out &&\n \tcat out &&\n-\tgrep \"HEAD points to something strange\" out\n+\ttest_i18ngrep \"HEAD points to something strange\" out\n '\n \n test_expect_success 'email without @ is okay' '\n@@ -122,7 +122,7 @@ test_expect_success 'email with embedded > is not okay' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new\" out\n+\ttest_i18ngrep \"error in commit $new\" out\n '\n \n test_expect_success 'missing < email delimiter is reported nicely' '\n@@ -134,7 +134,7 @@ test_expect_success 'missing < email delimiter is reported nicely' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.* - bad name\" out\n+\ttest_i18ngrep \"error in commit $new.* - bad name\" out\n '\n \n test_expect_success 'missing email is reported nicely' '\n@@ -146,7 +146,7 @@ test_expect_success 'missing email is reported nicely' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.* - missing email\" out\n+\ttest_i18ngrep \"error in commit $new.* - missing email\" out\n '\n \n test_expect_success '> in name is reported' '\n@@ -158,7 +158,7 @@ test_expect_success '> in name is reported' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new\" out\n+\ttest_i18ngrep \"error in commit $new\" out\n '\n \n # date is 2^64 + 1\n@@ -172,7 +172,7 @@ test_expect_success 'integer overflow in timestamps is reported' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.*integer overflow\" out\n+\ttest_i18ngrep \"error in commit $new.*integer overflow\" out\n '\n \n test_expect_success 'commit with NUL in header' '\n@@ -184,7 +184,7 @@ test_expect_success 'commit with NUL in header' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.*unterminated header: NUL at offset\" out\n+\ttest_i18ngrep \"error in commit $new.*unterminated header: NUL at offset\" out\n '\n \n test_expect_success 'tree object with duplicate entries' '\n@@ -205,7 +205,7 @@ test_expect_success 'tree object with duplicate entries' '\n \t\tgit hash-object -w -t tree --stdin\n \t) &&\n \ttest_must_fail git fsck 2>out &&\n-\tgrep \"error in tree .*contains duplicate file entries\" out\n+\ttest_i18ngrep \"error in tree .*contains duplicate file entries\" out\n '\n \n test_expect_success 'unparseable tree object' '\n@@ -259,7 +259,7 @@ test_expect_success 'tag pointing to nonexistent' '\n \ttest_when_finished \"git update-ref -d refs/tags/invalid\" &&\n \ttest_must_fail git fsck --tags >out &&\n \tcat out &&\n-\tgrep \"broken link\" out\n+\ttest_i18ngrep \"broken link\" out\n '\n \n test_expect_success 'tag pointing to something else than its type' '\n@@ -301,7 +301,7 @@ test_expect_success 'tag with incorrect tag name & missing tagger' '\n \twarning in tag $tag: badTagName: invalid '\\''tag'\\'' name: wrong name format\n \twarning in tag $tag: missingTaggerEntry: invalid format - expected '\\''tagger'\\'' line\n \tEOF\n-\ttest_cmp expect out\n+\ttest_i18ncmp expect out\n '\n \n test_expect_success 'tag with bad tagger' '\n@@ -320,7 +320,7 @@ test_expect_success 'tag with bad tagger' '\n \techo $tag >.git/refs/tags/wrong &&\n \ttest_when_finished \"git update-ref -d refs/tags/wrong\" &&\n \ttest_must_fail git fsck --tags 2>out &&\n-\tgrep \"error in tag .*: invalid author/committer\" out\n+\ttest_i18ngrep \"error in tag .*: invalid author/committer\" out\n '\n \n test_expect_success 'tag with NUL in header' '\n@@ -340,7 +340,7 @@ test_expect_success 'tag with NUL in header' '\n \ttest_when_finished \"git update-ref -d refs/tags/wrong\" &&\n \ttest_must_fail git fsck --tags 2>out &&\n \tcat out &&\n-\tgrep \"error in tag $tag.*unterminated header: NUL at offset\" out\n+\ttest_i18ngrep \"error in tag $tag.*unterminated header: NUL at offset\" out\n '\n \n test_expect_success 'cleaned up' '\n@@ -396,7 +396,7 @@ test_expect_success 'fsck notices blob entry pointing to null sha1' '\n \t       git hash-object -w --stdin -t tree) &&\n \t  git fsck 2>out &&\n \t  cat out &&\n-\t  grep \"warning.*null sha1\" out\n+\t  test_i18ngrep \"warning.*null sha1\" out\n \t)\n '\n \n@@ -407,7 +407,7 @@ test_expect_success 'fsck notices submodule entry pointing to null sha1' '\n \t       git hash-object -w --stdin -t tree) &&\n \t  git fsck 2>out &&\n \t  cat out &&\n-\t  grep \"warning.*null sha1\" out\n+\t  test_i18ngrep \"warning.*null sha1\" out\n \t)\n '\n \n@@ -428,7 +428,7 @@ while read name path pretty; do\n \t\t\tbad_tree=$(git mktree <bad) &&\n \t\t\tgit fsck 2>out &&\n \t\t\tcat out &&\n-\t\t\tgrep \"warning.*tree $bad_tree\" out\n+\t\t\ttest_i18ngrep \"warning.*tree $bad_tree\" out\n \t\t)'\n \tdone <<-\\EOF\n \t100644 blob\n@@ -474,9 +474,9 @@ test_expect_success 'NUL in commit' '\n \t\tgit branch bad $(cat name) &&\n \n \t\ttest_must_fail git -c fsck.nulInCommit=error fsck 2>warn.1 &&\n-\t\tgrep nulInCommit warn.1 &&\n+\t\ttest_i18ngrep nulInCommit warn.1 &&\n \t\tgit fsck 2>warn.2 &&\n-\t\tgrep nulInCommit warn.2\n+\t\ttest_i18ngrep nulInCommit warn.2\n \t)\n '\n \n@@ -594,7 +594,7 @@ test_expect_success 'fsck --name-objects' '\n \t\tremove_object $(git rev-parse julius:caesar.t) &&\n \t\ttest_must_fail git fsck --name-objects >out &&\n \t\ttree=$(git rev-parse --verify julius:) &&\n-\t\tegrep \"$tree \\((refs/heads/master|HEAD)@\\{[0-9]*\\}:\" out\n+\t\ttest -n \"$GETTEXT_POISON\" || egrep \"$tree \\((refs/heads/master|HEAD)@\\{[0-9]*\\}:\" out\n \t)\n '\n \n@@ -605,7 +605,7 @@ test_expect_success 'alternate objects are correctly blamed' '\n \tmkdir alt.git/objects/12 &&\n \t>alt.git/objects/12/34567890123456789012345678901234567890 &&\n \ttest_must_fail git fsck >out 2>&1 &&\n-\tgrep alt.git out\n+\ttest_i18ngrep alt.git out\n '\n \n test_expect_success 'fsck errors in packed objects' '\n@@ -624,8 +624,8 @@ test_expect_success 'fsck errors in packed objects' '\n \tremove_object $one &&\n \tremove_object $two &&\n \ttest_must_fail git fsck 2>out &&\n-\tgrep \"error in commit $one.* - bad name\" out &&\n-\tgrep \"error in commit $two.* - bad name\" out &&\n+\ttest_i18ngrep \"error in commit $one.* - bad name\" out &&\n+\ttest_i18ngrep \"error in commit $two.* - bad name\" out &&\n \t! grep corrupt out\n '\n \n@@ -706,7 +706,7 @@ test_expect_success 'fsck notices dangling objects' '\n \t\tgit fsck >actual &&\n \t\t# the output order is non-deterministic, as it comes from a hash\n \t\tsort <actual >actual.sorted &&\n-\t\ttest_cmp expect actual.sorted\n+\t\ttest_i18ncmp expect actual.sorted\n \t)\n '\n \ndiff --git a/t/t6050-replace.sh b/t/t6050-replace.sh\nindex 86374a9c52..7700a8e793 100755\n--- a/t/t6050-replace.sh\n+++ b/t/t6050-replace.sh\n@@ -133,8 +133,8 @@ test_expect_success 'tag replaced commit' '\n \n test_expect_success '\"git fsck\" works' '\n      git fsck master >fsck_master.out &&\n-     grep \"dangling commit $R\" fsck_master.out &&\n-     grep \"dangling tag $(cat .git/refs/tags/mytag)\" fsck_master.out &&\n+     test_i18ngrep \"dangling commit $R\" fsck_master.out &&\n+     test_i18ngrep \"dangling tag $(cat .git/refs/tags/mytag)\" fsck_master.out &&\n      test -z \"$(git fsck)\"\n '\n \ndiff --git a/t/t7415-submodule-names.sh b/t/t7415-submodule-names.sh\nindex 293e2e1963..49a37efe9c 100755\n--- a/t/t7415-submodule-names.sh\n+++ b/t/t7415-submodule-names.sh\n@@ -154,7 +154,7 @@ test_expect_success 'fsck detects symlinked .gitmodules file' '\n \t\t# symlink detector; this grep string comes from the config\n \t\t# variable name and will not be translated.\n \t\ttest_must_fail git fsck 2>output &&\n-\t\tgrep gitmodulesSymlink output\n+\t\ttest_i18ngrep gitmodulesSymlink output\n \t)\n '\n \n@@ -172,7 +172,7 @@ test_expect_success 'fsck detects non-blob .gitmodules' '\n \t\tgit ls-tree HEAD | sed s/subdir/.gitmodules/ | git mktree &&\n \n \t\ttest_must_fail git fsck 2>output &&\n-\t\tgrep gitmodulesBlob output\n+\t\ttest_i18ngrep gitmodulesBlob output\n \t)\n '\n \n@@ -186,7 +186,7 @@ test_expect_success 'fsck detects corrupt .gitmodules' '\n \t\tgit commit -m \"broken gitmodules\" &&\n \n \t\tgit fsck 2>output &&\n-\t\tgrep gitmodulesParse output &&\n+\t\ttest_i18ngrep gitmodulesParse output &&\n \t\ttest_i18ngrep ! \"bad config\" output\n \t)\n '\n-- \n2.19.1.647.g708186aaf9\n\n"},{"id":"361882","messageId":"xmqq36sp425p.fsf@gitster-ct.c.googlers.com","threadId":"49702","inReplyTo":"20181028065157.26727-9-pclouds@gmail.com","subject":"Re: [PATCH 08/12] remote.c: mark messages for translation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-10-29T07:56:02Z","receivedAt":"2018-10-29T07:56:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> @@ -995,12 +995,12 @@ static int match_explicit_lhs(struct ref *src,\n>  \t\t * way to delete 'other' ref at the remote end.\n>  \t\t */\n>  \t\tif (try_explicit_object_name(rs->src, match) < 0)\n> -\t\t\treturn error(\"src refspec %s does not match any.\", rs->src);\n> +\t\t\treturn error(_(\"src refspec %s does not match any\"), rs->src);\n>  \t\tif (allocated_match)\n>  \t\t\t*allocated_match = 1;\n>  \t\treturn 0;\n>  \tdefault:\n> -\t\treturn error(\"src refspec %s matches more than one.\", rs->src);\n> +\t\treturn error(_(\"src refspec %s matches more than one\"), rs->src);\n>  \t}\n>  }\n\nThese minor changes that are not accompanied by their own\njustification mean that the patches in this series cannot blindly be\ntrusted, which in turn means that I won't have bandwidth to process\nthis series properly for now.\n\nI also saw die() -> BUG() that was not highlighted in the proposed\nlog message; the single instance I happened to notice looked\nsensible, but I am not sure about the others.\n\nThere are other series in flight that touch the same area of code\nand in different ways, causing unnecessary conflicts, which does not\nhelp us either X-<.\n\n\n"},{"id":"361888","messageId":"20181029105304.GP30222@szeder.dev","threadId":"49702","inReplyTo":"20181028065157.26727-13-pclouds@gmail.com","subject":"Re: [PATCH 12/12] fsck: mark strings for translation","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2018-10-29T10:53:04Z","receivedAt":"2018-10-29T11:53:12Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Sun, Oct 28, 2018 at 07:51:57AM +0100, Nguyễn Thái Ngọc Duy wrote:\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  builtin/fsck.c             | 113 ++++++++++++++++++++-----------------\n>  t/t1410-reflog.sh          |   6 +-\n>  t/t1450-fsck.sh            |  50 ++++++++--------\n>  t/t6050-replace.sh         |   4 +-\n>  t/t7415-submodule-names.sh |   6 +-\n>  5 files changed, 94 insertions(+), 85 deletions(-)\n> \n> diff --git a/builtin/fsck.c b/builtin/fsck.c\n> index 06eb421720..13f8fe35c5 100644\n> --- a/builtin/fsck.c\n> +++ b/builtin/fsck.c\n> @@ -108,8 +108,9 @@ static int fsck_config(const char *var, const char *value, void *cb)\n>  static void objreport(struct object *obj, const char *msg_type,\n>  \t\t\tconst char *err)\n>  {\n> -\tfprintf(stderr, \"%s in %s %s: %s\\n\",\n> -\t\tmsg_type, printable_type(obj), describe_object(obj), err);\n> +\tfprintf_ln(stderr, _(\"%s in %s %s: %s\"),\n\nAre the (f)printf() -> (f)printf_ln() changes all over\n'builtin/fsck.c' really necessary to mark strings for translation?\n\n> diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh\n> index 90c765df3a..500c21366e 100755\n> --- a/t/t1450-fsck.sh\n> +++ b/t/t1450-fsck.sh\n\n> @@ -594,7 +594,7 @@ test_expect_success 'fsck --name-objects' '\n>  \t\tremove_object $(git rev-parse julius:caesar.t) &&\n>  \t\ttest_must_fail git fsck --name-objects >out &&\n>  \t\ttree=$(git rev-parse --verify julius:) &&\n> -\t\tegrep \"$tree \\((refs/heads/master|HEAD)@\\{[0-9]*\\}:\" out\n> +\t\ttest -n \"$GETTEXT_POISON\" || egrep \"$tree \\((refs/heads/master|HEAD)@\\{[0-9]*\\}:\" out\n\n'test_i18ngrep' accepts all 'grep' options, so this could be written\nas:\n\n  test_i18ngrep -E \"...\" out\n\n\nThere might be something else wrong with the patch, because now this\ntest tends to fail on current 'pu' on Travis CI:\n\n  [... snipped output from 'test_commit' ...]\n  +git rev-parse julius:caesar.t\n  +remove_object be45bbd3809e0829297cefa576e699c134abacfd\n  +sha1_file be45bbd3809e0829297cefa576e699c134abacfd\n  +remainder=45bbd3809e0829297cefa576e699c134abacfd\n  +firsttwo=be\n  +echo .git/objects/be/45bbd3809e0829297cefa576e699c134abacfd\n  +rm .git/objects/be/45bbd3809e0829297cefa576e699c134abacfd\n  +test_must_fail git fsck --name-objects\n  +_test_ok=\n  +git fsck --name-objects\n  +exit_code=2\n  +test 2 -eq 0\n  +test_match_signal 13 2\n  +test 2 = 141\n  +test 2 = 269\n  +return 1\n  +test 2 -gt 129\n  +test 2 -eq 127\n  +test 2 -eq 126\n  +return 0\n  +git rev-parse --verify julius:\n  +tree=c2fab98f409a47394d992eca10a20e0b22377c0c\n  +test -n \n  +egrep c2fab98f409a47394d992eca10a20e0b22377c0c \\((refs/heads/master|HEAD)@\\{[0-9]*\\}: out\n  error: last command exited with $?=1\n  not ok 65 - fsck --name-objects\n\nThe contents of 'out':\n\n  broken link from    tree be45bbd3809e0829297cefa576e699c134abacfd (refs/heads/master@{1112912113}:caesar.t)\n                to    blob be45bbd3809e0829297cefa576e699c134abacfd (refs/heads/master@{1112912113}:caesar.t)\n  missing blob be45bbd3809e0829297cefa576e699c134abacfd (refs/heads/master@{1112912113}:caesar.t)\n\nOn a related (side)note, I think it would be better if this 'grep'\npattern were more explicit about which of the three lines it is\nsupposed to match.\n\n\nAnyway, I couldn't reproduce the failure locally yet, but, admittedly,\nI didn't try that hard...  And my builds on Travis CI haven't yet come\nthat far to try this topic on its own.\n\n"},{"id":"361896","messageId":"xmqqsh0o3kuw.fsf@gitster-ct.c.googlers.com","threadId":"49702","inReplyTo":"20181029105304.GP30222@szeder.dev","subject":"Re: [PATCH 12/12] fsck: mark strings for translation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-10-29T14:09:43Z","receivedAt":"2018-10-29T14:09:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"SZEDER Gábor <szeder.dev@gmail.com> writes:\n\n>> -\tfprintf(stderr, \"%s in %s %s: %s\\n\",\n>> -\t\tmsg_type, printable_type(obj), describe_object(obj), err);\n>> +\tfprintf_ln(stderr, _(\"%s in %s %s: %s\"),\n>\n> Are the (f)printf() -> (f)printf_ln() changes all over\n> 'builtin/fsck.c' really necessary to mark strings for translation?\n\nIt is beyond absolute minimum but I saw it argued here that this\nmakes it easier to manage the .po and .pot files if your message\nstrings do not end with LF, a you are much less likely to _add_\nunneeded LF to the translated string than _lose_ LF at the end of\ntranslated string.\n"},{"id":"361915","messageId":"CACsJy8CE2mi69kXcs2sFYm34txfDb24Qqm4bgv_w3WAcYEEFLg@mail.gmail.com","threadId":"49702","inReplyTo":"xmqqsh0o3kuw.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH 12/12] fsck: mark strings for translation","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-29T16:14:37Z","receivedAt":"2018-10-29T16:15:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Oct 29, 2018 at 3:09 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> SZEDER Gábor <szeder.dev@gmail.com> writes:\n>\n> >> -    fprintf(stderr, \"%s in %s %s: %s\\n\",\n> >> -            msg_type, printable_type(obj), describe_object(obj), err);\n> >> +    fprintf_ln(stderr, _(\"%s in %s %s: %s\"),\n> >\n> > Are the (f)printf() -> (f)printf_ln() changes all over\n> > 'builtin/fsck.c' really necessary to mark strings for translation?\n>\n> It is beyond absolute minimum but I saw it argued here that this\n> makes it easier to manage the .po and .pot files if your message\n> strings do not end with LF, a you are much less likely to _add_\n> unneeded LF to the translated string than _lose_ LF at the end of\n> translated string.\n\nEspecially when \\n plays an important role and we don't trust\ntranslators to keep it [1] [2]. It's probably a too defensive stance\nand often does not apply, so nowadays I do it just to keep a\nconsistent pattern in the code.\n\n[1] https://public-inbox.org/git/20120308220131.GA10122@burratino/#t\n[2] but then translators can crash programs anyway (e.g. changing %d\nto %s...) we just trust gettext tools to catch problems early.\n-- \nDuy\n"},{"id":"361916","messageId":"CACsJy8DZ2d-qReY-LZTg50dc1Y-N_iXsUPNi3OnrVdL7ZLR9Eg@mail.gmail.com","threadId":"49702","inReplyTo":"xmqq36sp425p.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH 08/12] remote.c: mark messages for translation","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-10-29T16:16:25Z","receivedAt":"2018-10-29T16:16:58Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Oct 29, 2018 at 8:56 AM Junio C Hamano <gitster@pobox.com> wrote:\n> There are other series in flight that touch the same area of code\n> and in different ways, causing unnecessary conflicts, which does not\n> help us either X-<.\n\nI will of course fix all other comments, but I can hold this off if\nit's causing too much trouble. I'm in no hurry to get anything merged\nfast.\n-- \nDuy\n"},{"id":"361931","messageId":"87ftwolkl4.fsf@evledraar.gmail.com","threadId":"49702","inReplyTo":"CACsJy8CE2mi69kXcs2sFYm34txfDb24Qqm4bgv_w3WAcYEEFLg@mail.gmail.com","subject":"Re: [PATCH 12/12] fsck: mark strings for translation","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2018-10-29T17:38:15Z","receivedAt":"2018-10-29T17:38:22Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Mon, Oct 29 2018, Duy Nguyen wrote:\n\n> On Mon, Oct 29, 2018 at 3:09 PM Junio C Hamano <gitster@pobox.com> wrote:\n>>\n>> SZEDER Gábor <szeder.dev@gmail.com> writes:\n>>\n>> >> -    fprintf(stderr, \"%s in %s %s: %s\\n\",\n>> >> -            msg_type, printable_type(obj), describe_object(obj), err);\n>> >> +    fprintf_ln(stderr, _(\"%s in %s %s: %s\"),\n>> >\n>> > Are the (f)printf() -> (f)printf_ln() changes all over\n>> > 'builtin/fsck.c' really necessary to mark strings for translation?\n>>\n>> It is beyond absolute minimum but I saw it argued here that this\n>> makes it easier to manage the .po and .pot files if your message\n>> strings do not end with LF, a you are much less likely to _add_\n>> unneeded LF to the translated string than _lose_ LF at the end of\n>> translated string.\n>\n> Especially when \\n plays an important role and we don't trust\n> translators to keep it [1] [2]. It's probably a too defensive stance\n> and often does not apply, so nowadays I do it just to keep a\n> consistent pattern in the code.\n>\n> [1] https://public-inbox.org/git/20120308220131.GA10122@burratino/#t\n> [2] but then translators can crash programs anyway (e.g. changing %d\n> to %s...) we just trust gettext tools to catch problems early.\n\nAs Jonathan pointed out in the follow-up message[1] this sort of thing\nis checked for in msgfmt, so sure, let's strip the \\n, but it's really\nnot something we need to worry about. Likewise with translators turning\n\"%s\" into \"%d\" (or \"% s\") or whatever.\n\n    $ git diff -U0\n    diff --git a/po/de.po b/po/de.po\n    index 47986814c9..62de46c63d 100644\n    --- a/po/de.po\n    +++ b/po/de.po\n    @@ -23 +23 @@ msgid \"%shint: %.*s%s\\n\"\n    -msgstr \"%sHinweis: %.*s%s\\n\"\n    +msgstr \"%sHinweis: %.*s%s\"\n    $ make [...]\n    [...]\n    po/de.po:23: 'msgid' and 'msgstr' entries do not both end with '\\n'\n    msgfmt: found 1 fatal error\n    3470 translated messages.\n    make: *** [Makefile:2488: po/build/locale/de/LC_MESSAGES/git.mo] Error 1\n\n1. https://public-inbox.org/git/CACsJy8AcUy9FZiiehGc7mEL4i+XP6u0pmH1rGoR-WZnhYT1UMQ@mail.gmail.com/\n"},{"id":"361932","messageId":"87efc8lkcd.fsf@evledraar.gmail.com","threadId":"49702","inReplyTo":"87ftwolkl4.fsf@evledraar.gmail.com","subject":"Re: [PATCH 12/12] fsck: mark strings for translation","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2018-10-29T17:43:30Z","receivedAt":"2018-10-29T17:43:36Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Mon, Oct 29 2018, Ævar Arnfjörð Bjarmason wrote:\n\n> On Mon, Oct 29 2018, Duy Nguyen wrote:\n>\n>> On Mon, Oct 29, 2018 at 3:09 PM Junio C Hamano <gitster@pobox.com> wrote:\n>>>\n>>> SZEDER Gábor <szeder.dev@gmail.com> writes:\n>>>\n>>> >> -    fprintf(stderr, \"%s in %s %s: %s\\n\",\n>>> >> -            msg_type, printable_type(obj), describe_object(obj), err);\n>>> >> +    fprintf_ln(stderr, _(\"%s in %s %s: %s\"),\n>>> >\n>>> > Are the (f)printf() -> (f)printf_ln() changes all over\n>>> > 'builtin/fsck.c' really necessary to mark strings for translation?\n>>>\n>>> It is beyond absolute minimum but I saw it argued here that this\n>>> makes it easier to manage the .po and .pot files if your message\n>>> strings do not end with LF, a you are much less likely to _add_\n>>> unneeded LF to the translated string than _lose_ LF at the end of\n>>> translated string.\n>>\n>> Especially when \\n plays an important role and we don't trust\n>> translators to keep it [1] [2]. It's probably a too defensive stance\n>> and often does not apply, so nowadays I do it just to keep a\n>> consistent pattern in the code.\n>>\n>> [1] https://public-inbox.org/git/20120308220131.GA10122@burratino/#t\n>> [2] but then translators can crash programs anyway (e.g. changing %d\n>> to %s...) we just trust gettext tools to catch problems early.\n>\n> As Jonathan pointed out in the follow-up message[1] this sort of thing\n> is checked for in msgfmt, so sure, let's strip the \\n, but it's really\n> not something we need to worry about. Likewise with translators turning\n> \"%s\" into \"%d\" (or \"% s\") or whatever.\n>\n>     $ git diff -U0\n>     diff --git a/po/de.po b/po/de.po\n>     index 47986814c9..62de46c63d 100644\n>     --- a/po/de.po\n>     +++ b/po/de.po\n>     @@ -23 +23 @@ msgid \"%shint: %.*s%s\\n\"\n>     -msgstr \"%sHinweis: %.*s%s\\n\"\n>     +msgstr \"%sHinweis: %.*s%s\"\n>     $ make [...]\n>     [...]\n>     po/de.po:23: 'msgid' and 'msgstr' entries do not both end with '\\n'\n>     msgfmt: found 1 fatal error\n>     3470 translated messages.\n>     make: *** [Makefile:2488: po/build/locale/de/LC_MESSAGES/git.mo] Error 1\n>\n> 1. https://public-inbox.org/git/CACsJy8AcUy9FZiiehGc7mEL4i+XP6u0pmH1rGoR-WZnhYT1UMQ@mail.gmail.com/\n\n...to add to that, if there *are* formatting errors that --check doesn't\nspot let's hear about it so we can just patch gettext upstream:\nhttps://github.com/autotools-mirror/gettext/blob/master/gettext-tools/src/msgl-check.c#L572-L756\n\nUnlike the rest of our stack where we need to support however many years\nold tools we can freely rely on bleeding-edge gettext features, since\nthe only person we need to convince to upgrade is Jiang. I.e. he accepts\nthe PRs from translators, (presumably) runs msgfmt --check and then\nsubmits the result to Junio.\n\nSee the \"Usually...\" paragraph in my 66f5f6dca9 (\"C style: use standard\nstyle for \"TRANSLATORS\" comments\", 2017-05-11) for an example. We\nalready rely on a fairly recent gettext toolchain.\n"},{"id":"362048","messageId":"20181030232725.GA149989@google.com","threadId":"49702","inReplyTo":"87ftwolkl4.fsf@evledraar.gmail.com","subject":"Re: [PATCH 12/12] fsck: mark strings for translation","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2018-10-30T23:27:25Z","receivedAt":"2018-10-30T23:54:49Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi,\n\nÆvar Arnfjörð Bjarmason wrote:\n>> On Mon, Oct 29, 2018 at 3:09 PM Junio C Hamano <gitster@pobox.com> wrote:\n>>> SZEDER Gábor <szeder.dev@gmail.com> writes:\n>>>> Nguyễn Thái Ngọc Duy wrote:\n\n>>>>> -    fprintf(stderr, \"%s in %s %s: %s\\n\",\n>>>>> -            msg_type, printable_type(obj), describe_object(obj), err);\n>>>>> +    fprintf_ln(stderr, _(\"%s in %s %s: %s\"),\n>>>>\n>>>> Are the (f)printf() -> (f)printf_ln() changes all over\n>>>> 'builtin/fsck.c' really necessary to mark strings for translation?\n>>>\n>>> It is beyond absolute minimum but I saw it argued here that this\n>>> makes it easier to manage the .po and .pot files if your message\n>>> strings do not end with LF, a you are much less likely to _add_\n>>> unneeded LF to the translated string than _lose_ LF at the end of\n>>> translated string.\n[...]\n> As Jonathan pointed out in the follow-up message[1] this sort of thing\n> is checked for in msgfmt, so sure, let's strip the \\n, but it's really\n> not something we need to worry about. Likewise with translators turning\n> \"%s\" into \"%d\" (or \"% s\") or whatever.\n\nIMHO the advantage of leaving the \\n out in the message is not so much\nthat we don't trust translators but more that where we can make their\nlives easier, we should.\n\nIn other words, I'm glad the patch does that, and Ævar, I agree.\n\nThanks, both.\n\nJonathan\n\n> 1. https://public-inbox.org/git/CACsJy8AcUy9FZiiehGc7mEL4i+XP6u0pmH1rGoR-WZnhYT1UMQ@mail.gmail.com/\n"},{"id":"362140","messageId":"CANYiYbGwCwu5FXuir4bE_=eMjRaKtXKxk9h6LO_=xeWiabJuaA@mail.gmail.com","threadId":"49702","inReplyTo":"87efc8lkcd.fsf@evledraar.gmail.com","subject":"Re: [PATCH 12/12] fsck: mark strings for translation","fromName":"Jiang Xin","fromEmail":"worldhello.net@gmail.com","sentAt":"2018-11-01T01:36:13Z","receivedAt":"2018-11-01T01:36:27Z","isPatch":true,"sender":{"key":"worldhello.net@gmail.com","avatar":"https://avatars.githubusercontent.com/u/183860?v=4"},"body":"Ævar Arnfjörð Bjarmason <avarab@gmail.com> 于2018年10月30日周二 上午1:43写道：\n> On Mon, Oct 29 2018, Ævar Arnfjörð Bjarmason wrote:\n> Unlike the rest of our stack where we need to support however many years\n> old tools we can freely rely on bleeding-edge gettext features, since\n> the only person we need to convince to upgrade is Jiang. I.e. he accepts\n> the PRs from translators, (presumably) runs msgfmt --check and then\n> submits the result to Junio.\n\nI used a shell script to check commits before I send a pull request to Junio.\nThis script is in the po-helper branch, see:\nhttps://github.com/git-l10n/git-po/tree/po-helper\n\nIt can catch unmatched '\\n' errors (missing or unnecessary '\\n').\n\n    $ git diff\n   diff --git a/po/zh_CN.po b/po/zh_CN.po\n   index eabd4d1f8e..6b0d9ebc60 100644\n   --- a/po/zh_CN.po\n   +++ b/po/zh_CN.po\n   @@ -5157,7 +5157,7 @@ msgstr  \"略过补丁 '%s'。\"\n    #\n    #, perl-format\n    msgid   \"Skipping %s with backup suffix '%s'.\\n\"\n   -msgstr  \"略过 %s 含备份后缀 '%s'。\\n\"\n   +msgstr  \"略过 %s 含备份后缀 '%s'。\"\n    #\n    #, c-format\n    msgid   \"Skipping repository %s\\n\"\n\n   $ LC_ALL=C po-helper.sh check\n   ------------------------------------------------------------\n   bg.po     : 3958 translated messages.\n   ca.po     : 3328 translated messages, 18 fuzzy translations, 30\nuntranslated messages.\n   de.po     : 3958 translated messages.\n   es.po     : 3958 translated messages.\n   fr.po     : 3957 translated messages, 1 fuzzy translation.\n   is.po     : 14 translated messages.\n   it.po     : 716 translated messages, 350 untranslated messages.\n   ko.po     : 3608 translated messages.\n   pt_PT.po  : 3198 translated messages.\n   ru.po     : 3366 translated messages, 594 untranslated messages.\n   sv.po     : 3958 translated messages.\n   vi.po     : 3958 translated messages.\n   zh_CN.po  : po/zh_CN.po:19717: 'msgid' and 'msgstr' entries do not\nboth end with '\\n'\n   msgfmt: found 1 fatal error\n   3958 translated messages.\n   ------------------------------------------------------------\n   Show updates of git.pot...\n\n   # Nothing changed. (run 'make pot' first)\n   ------------------------------------------------------------\n   Check commits...\n\n   0 commits checked complete.\n   ------------------------------------------------------------\n   Note: If you want to check for upstream l10n update, run:\n   Note:\n   Note:     po-helper.sh check update <remote>\n   ------------------------------------------------------------\n\nSo, no warry about it. BTW, I agree with Jonathan.\n\n> Jonathan said:\n> IMHO the advantage of leaving the \\n out in the message is not so much\n> that we don't trust translators but more that where we can make their\n> lives easier, we should.\n\n--\nJiang Xin\n"},{"id":"362494","messageId":"CACsJy8AG6BT6n0T=WWsoXauX_gpLHBaMSou5FJvBA58fU_wi5w@mail.gmail.com","threadId":"49702","inReplyTo":"20181029105304.GP30222@szeder.dev","subject":"Re: [PATCH 12/12] fsck: mark strings for translation","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T17:21:43Z","receivedAt":"2018-11-05T17:22:12Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Oct 29, 2018 at 12:53 PM SZEDER Gábor <szeder.dev@gmail.com> wrote:\n> The contents of 'out':\n>\n>   broken link from    tree be45bbd3809e0829297cefa576e699c134abacfd (refs/heads/master@{1112912113}:caesar.t)\n>                 to    blob be45bbd3809e0829297cefa576e699c134abacfd (refs/heads/master@{1112912113}:caesar.t)\n>   missing blob be45bbd3809e0829297cefa576e699c134abacfd (refs/heads/master@{1112912113}:caesar.t)\n>\n> On a related (side)note, I think it would be better if this 'grep'\n\nI found the problem. Some function returns static string which works\nfine when we do two printf()'s, one call of that function per\nprintf(). But when combining two printf() in one, we have a problem.\nThanks for catching.\n-- \nDuy\n"},{"id":"362504","messageId":"20181105192059.20303-1-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181028065157.26727-1-pclouds@gmail.com","subject":"[PATCH v2 00/16] Mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:43Z","receivedAt":"2018-11-05T19:21:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"v2 splits non-trivial changes out to keep i18n patches simpler. A few\nmore word legos in fsck are removed. v2 also fixes a bug in fsck that\nmakes it print object id incorrectly.\n\nNguyễn Thái Ngọc Duy (16):\n  git.c: mark more strings for translation\n  alias.c: mark split_cmdline_strerror() strings for translation\n  archive.c: mark more strings for translation\n  attr.c: mark more string for translation\n  read-cache.c: turn die(\"internal error\") to BUG()\n  read-cache.c: mark more strings for translation\n  read-cache.c: add missing colon separators\n  reflog: mark strings for translation\n  remote.c: turn some error() or die() to BUG()\n  remote.c: mark messages for translation\n  repack: mark more strings for translation\n  parse-options: replace opterror() with optname()\n  parse-options.c: turn some die() to BUG()\n  parse-options.c: mark more strings for translation\n  fsck: reduce word legos to help i18n\n  fsck: mark strings for translation\n\n alias.c                    |   4 +-\n archive.c                  |   8 +-\n attr.c                     |   4 +-\n builtin/fsck.c             | 156 +++++++++++++++++++++----------------\n builtin/merge.c            |   4 +-\n builtin/reflog.c           |  34 ++++----\n builtin/repack.c           |  26 +++----\n builtin/revert.c           |   3 +-\n git.c                      |  32 ++++----\n parse-options-cb.c         |   7 +-\n parse-options.c            |  64 ++++++++-------\n parse-options.h            |   5 +-\n read-cache.c               |  73 ++++++++---------\n ref-filter.c               |   8 +-\n remote.c                   |  49 ++++++------\n t/t0040-parse-options.sh   |   4 +-\n t/t1410-reflog.sh          |   6 +-\n t/t1450-fsck.sh            |  52 ++++++-------\n t/t4211-line-log.sh        |   2 +-\n t/t6050-replace.sh         |   4 +-\n t/t7415-submodule-names.sh |   6 +-\n 21 files changed, 292 insertions(+), 259 deletions(-)\n\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362505","messageId":"20181105192059.20303-2-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 01/16] git.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:44Z","receivedAt":"2018-11-05T19:21:10Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"One string is slightly updated to keep consistency with the rest:\ndie() should with lowercase.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n git.c | 30 +++++++++++++++---------------\n 1 file changed, 15 insertions(+), 15 deletions(-)\n\ndiff --git a/git.c b/git.c\nindex adac132956..5fd30da093 100644\n--- a/git.c\n+++ b/git.c\n@@ -338,27 +338,27 @@ static int handle_alias(int *argcp, const char ***argv)\n \t\t\tif (ret >= 0)   /* normal exit */\n \t\t\t\texit(ret);\n \n-\t\t\tdie_errno(\"while expanding alias '%s': '%s'\",\n-\t\t\t    alias_command, alias_string + 1);\n+\t\t\tdie_errno(_(\"while expanding alias '%s': '%s'\"),\n+\t\t\t\t  alias_command, alias_string + 1);\n \t\t}\n \t\tcount = split_cmdline(alias_string, &new_argv);\n \t\tif (count < 0)\n-\t\t\tdie(\"Bad alias.%s string: %s\", alias_command,\n+\t\t\tdie(_(\"bad alias.%s string: %s\"), alias_command,\n \t\t\t    split_cmdline_strerror(count));\n \t\toption_count = handle_options(&new_argv, &count, &envchanged);\n \t\tif (envchanged)\n-\t\t\tdie(\"alias '%s' changes environment variables.\\n\"\n-\t\t\t\t \"You can use '!git' in the alias to do this\",\n-\t\t\t\t alias_command);\n+\t\t\tdie(_(\"alias '%s' changes environment variables.\\n\"\n+\t\t\t      \"You can use '!git' in the alias to do this\"),\n+\t\t\t    alias_command);\n \t\tmemmove(new_argv - option_count, new_argv,\n \t\t\t\tcount * sizeof(char *));\n \t\tnew_argv -= option_count;\n \n \t\tif (count < 1)\n-\t\t\tdie(\"empty alias for %s\", alias_command);\n+\t\t\tdie(_(\"empty alias for %s\"), alias_command);\n \n \t\tif (!strcmp(alias_command, new_argv[0]))\n-\t\t\tdie(\"recursive alias: %s\", alias_command);\n+\t\t\tdie(_(\"recursive alias: %s\"), alias_command);\n \n \t\ttrace_argv_printf(new_argv,\n \t\t\t\t  \"trace: alias expansion: %s =>\",\n@@ -409,7 +409,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n \n \tif (!help && get_super_prefix()) {\n \t\tif (!(p->option & SUPPORT_SUPER_PREFIX))\n-\t\t\tdie(\"%s doesn't support --super-prefix\", p->cmd);\n+\t\t\tdie(_(\"%s doesn't support --super-prefix\"), p->cmd);\n \t}\n \n \tif (!help && p->option & NEED_WORK_TREE)\n@@ -433,11 +433,11 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n \n \t/* Check for ENOSPC and EIO errors.. */\n \tif (fflush(stdout))\n-\t\tdie_errno(\"write failure on standard output\");\n+\t\tdie_errno(_(\"write failure on standard output\"));\n \tif (ferror(stdout))\n-\t\tdie(\"unknown write failure on standard output\");\n+\t\tdie(_(\"unknown write failure on standard output\"));\n \tif (fclose(stdout))\n-\t\tdie_errno(\"close failed on standard output\");\n+\t\tdie_errno(_(\"close failed on standard output\"));\n \treturn 0;\n }\n \n@@ -648,7 +648,7 @@ static void execv_dashed_external(const char **argv)\n \tint status;\n \n \tif (get_super_prefix())\n-\t\tdie(\"%s doesn't support --super-prefix\", argv[0]);\n+\t\tdie(_(\"%s doesn't support --super-prefix\"), argv[0]);\n \n \tif (use_pager == -1 && !is_builtin(argv[0]))\n \t\tuse_pager = check_pager_config(argv[0]);\n@@ -760,7 +760,7 @@ int cmd_main(int argc, const char **argv)\n \tif (skip_prefix(cmd, \"git-\", &cmd)) {\n \t\targv[0] = cmd;\n \t\thandle_builtin(argc, argv);\n-\t\tdie(\"cannot handle %s as a builtin\", cmd);\n+\t\tdie(_(\"cannot handle %s as a builtin\"), cmd);\n \t}\n \n \t/* Look for flags.. */\n@@ -773,7 +773,7 @@ int cmd_main(int argc, const char **argv)\n \t} else {\n \t\t/* The user didn't specify a command; give them help */\n \t\tcommit_pager_choice();\n-\t\tprintf(\"usage: %s\\n\\n\", git_usage_string);\n+\t\tprintf(_(\"usage: %s\\n\\n\"), git_usage_string);\n \t\tlist_common_cmds_help();\n \t\tprintf(\"\\n%s\\n\", _(git_more_info_string));\n \t\texit(1);\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362506","messageId":"20181105192059.20303-3-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 02/16] alias.c: mark split_cmdline_strerror() strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:45Z","receivedAt":"2018-11-05T19:21:11Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This function can be part of translated messages. To make sure we\ndon't have a sentence with mixed languages, mark the strings for\ntranslation, but only use translated strings in places we know we will\noutput translated strings.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n alias.c         | 4 ++--\n builtin/merge.c | 2 +-\n git.c           | 2 +-\n 3 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/alias.c b/alias.c\nindex a7e4e57130..c471538020 100644\n--- a/alias.c\n+++ b/alias.c\n@@ -47,8 +47,8 @@ void list_aliases(struct string_list *list)\n #define SPLIT_CMDLINE_BAD_ENDING 1\n #define SPLIT_CMDLINE_UNCLOSED_QUOTE 2\n static const char *split_cmdline_errors[] = {\n-\t\"cmdline ends with \\\\\",\n-\t\"unclosed quote\"\n+\tN_(\"cmdline ends with \\\\\"),\n+\tN_(\"unclosed quote\")\n };\n \n int split_cmdline(char *cmdline, const char ***argv)\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 4aa6071598..92ba7e1c6d 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -577,7 +577,7 @@ static void parse_branch_merge_options(char *bmo)\n \targc = split_cmdline(bmo, &argv);\n \tif (argc < 0)\n \t\tdie(_(\"Bad branch.%s.mergeoptions string: %s\"), branch,\n-\t\t    split_cmdline_strerror(argc));\n+\t\t    _(split_cmdline_strerror(argc)));\n \tREALLOC_ARRAY(argv, argc + 2);\n \tMOVE_ARRAY(argv + 1, argv, argc + 1);\n \targc++;\ndiff --git a/git.c b/git.c\nindex 5fd30da093..c7e122cfc1 100644\n--- a/git.c\n+++ b/git.c\n@@ -344,7 +344,7 @@ static int handle_alias(int *argcp, const char ***argv)\n \t\tcount = split_cmdline(alias_string, &new_argv);\n \t\tif (count < 0)\n \t\t\tdie(_(\"bad alias.%s string: %s\"), alias_command,\n-\t\t\t    split_cmdline_strerror(count));\n+\t\t\t    _(split_cmdline_strerror(count)));\n \t\toption_count = handle_options(&new_argv, &count, &envchanged);\n \t\tif (envchanged)\n \t\t\tdie(_(\"alias '%s' changes environment variables.\\n\"\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362507","messageId":"20181105192059.20303-4-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 03/16] archive.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:46Z","receivedAt":"2018-11-05T19:21:13Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Two messages also print extra information to be more useful\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n archive.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 9d16b7fadf..d8f6e1ce30 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -385,12 +385,12 @@ static void parse_treeish_arg(const char **argv,\n \t\tint refnamelen = colon - name;\n \n \t\tif (!dwim_ref(name, refnamelen, &oid, &ref))\n-\t\t\tdie(\"no such ref: %.*s\", refnamelen, name);\n+\t\t\tdie(_(\"no such ref: %.*s\"), refnamelen, name);\n \t\tfree(ref);\n \t}\n \n \tif (get_oid(name, &oid))\n-\t\tdie(\"Not a valid object name\");\n+\t\tdie(_(\"not a valid object name: %s\"), name);\n \n \tcommit = lookup_commit_reference_gently(ar_args->repo, &oid, 1);\n \tif (commit) {\n@@ -403,7 +403,7 @@ static void parse_treeish_arg(const char **argv,\n \n \ttree = parse_tree_indirect(&oid);\n \tif (tree == NULL)\n-\t\tdie(\"not a tree object\");\n+\t\tdie(_(\"not a tree object: %s\"), oid_to_hex(&oid));\n \n \tif (prefix) {\n \t\tstruct object_id tree_oid;\n@@ -413,7 +413,7 @@ static void parse_treeish_arg(const char **argv,\n \t\terr = get_tree_entry(&tree->object.oid, prefix, &tree_oid,\n \t\t\t\t     &mode);\n \t\tif (err || !S_ISDIR(mode))\n-\t\t\tdie(\"current working directory is untracked\");\n+\t\t\tdie(_(\"current working directory is untracked\"));\n \n \t\ttree = parse_tree_indirect(&tree_oid);\n \t}\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362508","messageId":"20181105192059.20303-5-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 04/16] attr.c: mark more string for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:47Z","receivedAt":"2018-11-05T19:21:15Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n attr.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 60d284796d..3770bc1a11 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -372,8 +372,8 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,\n \tif (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen &&\n \t    starts_with(name, ATTRIBUTE_MACRO_PREFIX)) {\n \t\tif (!macro_ok) {\n-\t\t\tfprintf(stderr, \"%s not allowed: %s:%d\\n\",\n-\t\t\t\tname, src, lineno);\n+\t\t\tfprintf_ln(stderr, _(\"%s not allowed: %s:%d\"),\n+\t\t\t\t   name, src, lineno);\n \t\t\tgoto fail_return;\n \t\t}\n \t\tis_macro = 1;\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362509","messageId":"20181105192059.20303-6-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 05/16] read-cache.c: turn die(\"internal error\") to BUG()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:48Z","receivedAt":"2018-11-05T19:21:16Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n read-cache.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/read-cache.c b/read-cache.c\nindex d57958233e..0c37f4885e 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -316,7 +316,7 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)\n \t\t\tchanged |= DATA_CHANGED;\n \t\treturn changed;\n \tdefault:\n-\t\tdie(\"internal error: ce_mode is %o\", ce->ce_mode);\n+\t\tBUG(\"unsupported ce_mode: %o\", ce->ce_mode);\n \t}\n \n \tchanged |= match_stat_data(&ce->ce_stat_data, st);\n@@ -2356,14 +2356,14 @@ void validate_cache_entries(const struct index_state *istate)\n \n \tfor (i = 0; i < istate->cache_nr; i++) {\n \t\tif (!istate) {\n-\t\t\tdie(\"internal error: cache entry is not allocated from expected memory pool\");\n+\t\t\tBUG(\"cache entry is not allocated from expected memory pool\");\n \t\t} else if (!istate->ce_mem_pool ||\n \t\t\t!mem_pool_contains(istate->ce_mem_pool, istate->cache[i])) {\n \t\t\tif (!istate->split_index ||\n \t\t\t\t!istate->split_index->base ||\n \t\t\t\t!istate->split_index->base->ce_mem_pool ||\n \t\t\t\t!mem_pool_contains(istate->split_index->base->ce_mem_pool, istate->cache[i])) {\n-\t\t\t\tdie(\"internal error: cache entry is not allocated from expected memory pool\");\n+\t\t\t\tBUG(\"cache entry is not allocated from expected memory pool\");\n \t\t\t}\n \t\t}\n \t}\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362510","messageId":"20181105192059.20303-7-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 06/16] read-cache.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:49Z","receivedAt":"2018-11-05T19:21:18Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"There are a couple other improvements on these strings as well:\n\n - add missing colon (as separator)\n - quote paths\n - provide more information on error messages\n - keep first word in lowercase\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n read-cache.c    | 57 +++++++++++++++++++++++++------------------------\n t/t1450-fsck.sh |  2 +-\n 2 files changed, 30 insertions(+), 29 deletions(-)\n\ndiff --git a/read-cache.c b/read-cache.c\nindex 0c37f4885e..858befe738 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -672,7 +672,8 @@ static struct cache_entry *create_alias_ce(struct index_state *istate,\n \tstruct cache_entry *new_entry;\n \n \tif (alias->ce_flags & CE_ADDED)\n-\t\tdie(\"Will not add file alias '%s' ('%s' already exists in index)\", ce->name, alias->name);\n+\t\tdie(_(\"will not add file alias '%s' ('%s' already exists in index)\"),\n+\t\t    ce->name, alias->name);\n \n \t/* Ok, create the new entry using the name of the existing alias */\n \tlen = ce_namelen(alias);\n@@ -687,7 +688,7 @@ void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)\n {\n \tstruct object_id oid;\n \tif (write_object_file(\"\", 0, blob_type, &oid))\n-\t\tdie(\"cannot create an empty blob in the object database\");\n+\t\tdie(_(\"cannot create an empty blob in the object database\"));\n \toidcpy(&ce->oid, &oid);\n }\n \n@@ -708,7 +709,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \t\tnewflags |= HASH_RENORMALIZE;\n \n \tif (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))\n-\t\treturn error(\"%s: can only add regular files, symbolic links or git-directories\", path);\n+\t\treturn error(_(\"%s: can only add regular files, symbolic links or git-directories\"), path);\n \n \tnamelen = strlen(path);\n \tif (S_ISDIR(st_mode)) {\n@@ -763,7 +764,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \tif (!intent_only) {\n \t\tif (index_path(istate, &ce->oid, path, st, newflags)) {\n \t\t\tdiscard_cache_entry(ce);\n-\t\t\treturn error(\"unable to index file %s\", path);\n+\t\t\treturn error(_(\"unable to index file '%s'\"), path);\n \t\t}\n \t} else\n \t\tset_object_name_for_intent_to_add_entry(ce);\n@@ -782,7 +783,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \t\tdiscard_cache_entry(ce);\n \telse if (add_index_entry(istate, ce, add_option)) {\n \t\tdiscard_cache_entry(ce);\n-\t\treturn error(\"unable to add %s to index\", path);\n+\t\treturn error(_(\"unable to add '%s' to index\"), path);\n \t}\n \tif (verbose && !was_same)\n \t\tprintf(\"add '%s'\\n\", path);\n@@ -793,7 +794,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int flags)\n {\n \tstruct stat st;\n \tif (lstat(path, &st))\n-\t\tdie_errno(\"unable to stat '%s'\", path);\n+\t\tdie_errno(_(\"unable to stat '%s'\"), path);\n \treturn add_to_index(istate, path, &st, flags);\n }\n \n@@ -818,7 +819,7 @@ struct cache_entry *make_cache_entry(struct index_state *istate,\n \tint len;\n \n \tif (!verify_path(path, mode)) {\n-\t\terror(\"Invalid path '%s'\", path);\n+\t\terror(_(\"invalid path '%s'\"), path);\n \t\treturn NULL;\n \t}\n \n@@ -844,7 +845,7 @@ struct cache_entry *make_transient_cache_entry(unsigned int mode, const struct o\n \tint len;\n \n \tif (!verify_path(path, mode)) {\n-\t\terror(\"Invalid path '%s'\", path);\n+\t\terror(_(\"invalid path '%s'\"), path);\n \t\treturn NULL;\n \t}\n \n@@ -1297,12 +1298,12 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e\n \tif (!ok_to_add)\n \t\treturn -1;\n \tif (!verify_path(ce->name, ce->ce_mode))\n-\t\treturn error(\"Invalid path '%s'\", ce->name);\n+\t\treturn error(_(\"invalid path '%s'\"), ce->name);\n \n \tif (!skip_df_check &&\n \t    check_file_directory_conflict(istate, ce, pos, ok_to_replace)) {\n \t\tif (!ok_to_replace)\n-\t\t\treturn error(\"'%s' appears as both a file and as a directory\",\n+\t\t\treturn error(_(\"'%s' appears as both a file and as a directory\"),\n \t\t\t\t     ce->name);\n \t\tpos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce));\n \t\tpos = -pos-1;\n@@ -1676,10 +1677,10 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)\n \tint hdr_version;\n \n \tif (hdr->hdr_signature != htonl(CACHE_SIGNATURE))\n-\t\treturn error(\"bad signature\");\n+\t\treturn error(_(\"bad signature 0x%08x\"), hdr->hdr_signature);\n \thdr_version = ntohl(hdr->hdr_version);\n \tif (hdr_version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < hdr_version)\n-\t\treturn error(\"bad index version %d\", hdr_version);\n+\t\treturn error(_(\"bad index version %d\"), hdr_version);\n \n \tif (!verify_index_checksum)\n \t\treturn 0;\n@@ -1688,7 +1689,7 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)\n \tthe_hash_algo->update_fn(&c, hdr, size - the_hash_algo->rawsz);\n \tthe_hash_algo->final_fn(hash, &c);\n \tif (!hasheq(hash, (unsigned char *)hdr + size - the_hash_algo->rawsz))\n-\t\treturn error(\"bad index file sha1 signature\");\n+\t\treturn error(_(\"bad index file sha1 signature\"));\n \treturn 0;\n }\n \n@@ -1718,9 +1719,9 @@ static int read_index_extension(struct index_state *istate,\n \t\tbreak;\n \tdefault:\n \t\tif (*ext < 'A' || 'Z' < *ext)\n-\t\t\treturn error(\"index uses %.4s extension, which we do not understand\",\n+\t\t\treturn error(_(\"index uses %.4s extension, which we do not understand\"),\n \t\t\t\t     ext);\n-\t\tfprintf(stderr, \"ignoring %.4s extension\\n\", ext);\n+\t\tfprintf_ln(stderr, _(\"ignoring %.4s extension\"), ext);\n \t\tbreak;\n \t}\n \treturn 0;\n@@ -1767,7 +1768,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,\n \t\textended_flags = get_be16(&ondisk2->flags2) << 16;\n \t\t/* We do not yet understand any bit out of CE_EXTENDED_FLAGS */\n \t\tif (extended_flags & ~CE_EXTENDED_FLAGS)\n-\t\t\tdie(\"Unknown index entry format %08x\", extended_flags);\n+\t\t\tdie(_(\"unknown index entry format 0x%08x\"), extended_flags);\n \t\tflags |= extended_flags;\n \t\tname = ondisk2->name;\n \t}\n@@ -1840,13 +1841,13 @@ static void check_ce_order(struct index_state *istate)\n \t\tint name_compare = strcmp(ce->name, next_ce->name);\n \n \t\tif (0 < name_compare)\n-\t\t\tdie(\"unordered stage entries in index\");\n+\t\t\tdie(_(\"unordered stage entries in index\"));\n \t\tif (!name_compare) {\n \t\t\tif (!ce_stage(ce))\n-\t\t\t\tdie(\"multiple stage entries for merged file '%s'\",\n+\t\t\t\tdie(_(\"multiple stage entries for merged file '%s'\"),\n \t\t\t\t    ce->name);\n \t\t\tif (ce_stage(ce) > ce_stage(next_ce))\n-\t\t\t\tdie(\"unordered stage entries for '%s'\",\n+\t\t\t\tdie(_(\"unordered stage entries for '%s'\"),\n \t\t\t\t    ce->name);\n \t\t}\n \t}\n@@ -2149,19 +2150,19 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n \tif (fd < 0) {\n \t\tif (!must_exist && errno == ENOENT)\n \t\t\treturn 0;\n-\t\tdie_errno(\"%s: index file open failed\", path);\n+\t\tdie_errno(_(\"%s: index file open failed\"), path);\n \t}\n \n \tif (fstat(fd, &st))\n-\t\tdie_errno(\"cannot stat the open index\");\n+\t\tdie_errno(_(\"%s: cannot stat the open index\"), path);\n \n \tmmap_size = xsize_t(st.st_size);\n \tif (mmap_size < sizeof(struct cache_header) + the_hash_algo->rawsz)\n-\t\tdie(\"index file smaller than expected\");\n+\t\tdie(_(\"%s: index file smaller than expected\"), path);\n \n \tmmap = xmmap(NULL, mmap_size, PROT_READ, MAP_PRIVATE, fd, 0);\n \tif (mmap == MAP_FAILED)\n-\t\tdie_errno(\"unable to map index file\");\n+\t\tdie_errno(_(\"%s: unable to map index file\"), path);\n \tclose(fd);\n \n \thdr = (const struct cache_header *)mmap;\n@@ -2243,7 +2244,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n \n unmap:\n \tmunmap((void *)mmap, mmap_size);\n-\tdie(\"index file corrupt\");\n+\tdie(_(\"index file corrupt\"));\n }\n \n /*\n@@ -2255,7 +2256,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n static void freshen_shared_index(const char *shared_index, int warn)\n {\n \tif (!check_and_freshen_file(shared_index, 1) && warn)\n-\t\twarning(\"could not freshen shared index '%s'\", shared_index);\n+\t\twarning(_(\"could not freshen shared index '%s'\"), shared_index);\n }\n \n int read_index_from(struct index_state *istate, const char *path,\n@@ -2290,7 +2291,7 @@ int read_index_from(struct index_state *istate, const char *path,\n \tbase_path = xstrfmt(\"%s/sharedindex.%s\", gitdir, base_oid_hex);\n \tret = do_read_index(split_index->base, base_path, 1);\n \tif (!oideq(&split_index->base_oid, &split_index->base->oid))\n-\t\tdie(\"broken index, expect %s in %s, got %s\",\n+\t\tdie(_(\"broken index, expect %s in %s, got %s\"),\n \t\t    base_oid_hex, base_path,\n \t\t    oid_to_hex(&split_index->base->oid));\n \n@@ -3076,7 +3077,7 @@ static int write_shared_index(struct index_state *istate,\n \t\treturn ret;\n \tret = adjust_shared_perm(get_tempfile_path(*temp));\n \tif (ret) {\n-\t\terror(\"cannot fix permission bits on %s\", get_tempfile_path(*temp));\n+\t\terror(_(\"cannot fix permission bits on '%s'\"), get_tempfile_path(*temp));\n \t\treturn ret;\n \t}\n \tret = rename_tempfile(temp,\n@@ -3222,7 +3223,7 @@ int read_index_unmerged(struct index_state *istate)\n \t\tnew_ce->ce_namelen = len;\n \t\tnew_ce->ce_mode = ce->ce_mode;\n \t\tif (add_index_entry(istate, new_ce, ADD_CACHE_SKIP_DFCHECK))\n-\t\t\treturn error(\"%s: cannot drop to stage #0\",\n+\t\t\treturn error(_(\"%s: cannot drop to stage #0\"),\n \t\t\t\t     new_ce->name);\n \t}\n \treturn unmerged;\ndiff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh\nindex 0f2dd26f74..90c765df3a 100755\n--- a/t/t1450-fsck.sh\n+++ b/t/t1450-fsck.sh\n@@ -754,7 +754,7 @@ test_expect_success 'detect corrupt index file in fsck' '\n \ttest_when_finished \"mv .git/index.backup .git/index\" &&\n \tcorrupt_index_checksum &&\n \ttest_must_fail git fsck --cache 2>errors &&\n-\tgrep \"bad index file\" errors\n+\ttest_i18ngrep \"bad index file\" errors\n '\n \n test_done\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362511","messageId":"20181105192059.20303-8-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 07/16] read-cache.c: add missing colon separators","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:50Z","receivedAt":"2018-11-05T19:21:20Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"typechange_fmt and added_fmt should have a colon before \"needs\nupdate\". Align the statements to make it easier to read and see. Also\ndrop the unnecessary ().\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n read-cache.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/read-cache.c b/read-cache.c\nindex 858befe738..8d99ae376c 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1492,11 +1492,11 @@ int refresh_index(struct index_state *istate, unsigned int flags,\n \t\t\t\t\t\t  istate->cache_nr);\n \n \ttrace_performance_enter();\n-\tmodified_fmt = (in_porcelain ? \"M\\t%s\\n\" : \"%s: needs update\\n\");\n-\tdeleted_fmt = (in_porcelain ? \"D\\t%s\\n\" : \"%s: needs update\\n\");\n-\ttypechange_fmt = (in_porcelain ? \"T\\t%s\\n\" : \"%s needs update\\n\");\n-\tadded_fmt = (in_porcelain ? \"A\\t%s\\n\" : \"%s needs update\\n\");\n-\tunmerged_fmt = (in_porcelain ? \"U\\t%s\\n\" : \"%s: needs merge\\n\");\n+\tmodified_fmt   = in_porcelain ? \"M\\t%s\\n\" : \"%s: needs update\\n\";\n+\tdeleted_fmt    = in_porcelain ? \"D\\t%s\\n\" : \"%s: needs update\\n\";\n+\ttypechange_fmt = in_porcelain ? \"T\\t%s\\n\" : \"%s: needs update\\n\";\n+\tadded_fmt      = in_porcelain ? \"A\\t%s\\n\" : \"%s: needs update\\n\";\n+\tunmerged_fmt   = in_porcelain ? \"U\\t%s\\n\" : \"%s: needs merge\\n\";\n \tfor (i = 0; i < istate->cache_nr; i++) {\n \t\tstruct cache_entry *ce, *new_entry;\n \t\tint cache_errno = 0;\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362512","messageId":"20181105192059.20303-10-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 09/16] remote.c: turn some error() or die() to BUG()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:52Z","receivedAt":"2018-11-05T19:21:21Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The first error, \"internal error\", is clearly a BUG(). The second two\nare meant to catch calls with invalid parameters and should never\nhappen outside the test suite.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n remote.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex 81f4f01b00..257630ff21 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -620,7 +620,7 @@ static void handle_duplicate(struct ref *ref1, struct ref *ref2)\n \t\t\t * FETCH_HEAD_IGNORE entries always appear at\n \t\t\t * the end of the list.\n \t\t\t */\n-\t\t\tdie(_(\"Internal error\"));\n+\t\t\tBUG(\"Internal error\");\n \t\t}\n \t}\n \tfree(ref2->peer_ref);\n@@ -707,7 +707,7 @@ static void query_refspecs_multiple(struct refspec *rs,\n \tint find_src = !query->src;\n \n \tif (find_src && !query->dst)\n-\t\terror(\"query_refspecs_multiple: need either src or dst\");\n+\t\tBUG(\"query_refspecs_multiple: need either src or dst\");\n \n \tfor (i = 0; i < rs->nr; i++) {\n \t\tstruct refspec_item *refspec = &rs->items[i];\n@@ -735,7 +735,7 @@ int query_refspecs(struct refspec *rs, struct refspec_item *query)\n \tchar **result = find_src ? &query->src : &query->dst;\n \n \tif (find_src && !query->dst)\n-\t\treturn error(\"query_refspecs: need either src or dst\");\n+\t\tBUG(\"query_refspecs: need either src or dst\");\n \n \tfor (i = 0; i < rs->nr; i++) {\n \t\tstruct refspec_item *refspec = &rs->items[i];\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362513","messageId":"20181105192059.20303-9-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 08/16] reflog: mark strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:51Z","receivedAt":"2018-11-05T19:21:22Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"One string \"nothing to delete?\" is rephrased to be more helpful.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/reflog.c | 34 +++++++++++++++++++---------------\n 1 file changed, 19 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex b5941c1ff3..5a74ccf7ab 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -13,11 +13,15 @@\n \n /* NEEDSWORK: switch to using parse_options */\n static const char reflog_expire_usage[] =\n-\"git reflog expire [--expire=<time>] [--expire-unreachable=<time>] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] <refs>...\";\n+N_(\"git reflog expire [--expire=<time>] \"\n+   \"[--expire-unreachable=<time>] \"\n+   \"[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] \"\n+   \"[--verbose] [--all] <refs>...\");\n static const char reflog_delete_usage[] =\n-\"git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] <refs>...\";\n+N_(\"git reflog delete [--rewrite] [--updateref] \"\n+   \"[--dry-run | -n] [--verbose] <refs>...\");\n static const char reflog_exists_usage[] =\n-\"git reflog exists <ref>\";\n+N_(\"git reflog exists <ref>\");\n \n static timestamp_t default_reflog_expire;\n static timestamp_t default_reflog_expire_unreachable;\n@@ -556,7 +560,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \t\t\tbreak;\n \t\t}\n \t\telse if (arg[0] == '-')\n-\t\t\tusage(reflog_expire_usage);\n+\t\t\tusage(_(reflog_expire_usage));\n \t\telse\n \t\t\tbreak;\n \t}\n@@ -569,7 +573,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \tif (cb.cmd.stalefix) {\n \t\trepo_init_revisions(the_repository, &cb.cmd.revs, prefix);\n \t\tif (flags & EXPIRE_REFLOGS_VERBOSE)\n-\t\t\tprintf(\"Marking reachable objects...\");\n+\t\t\tprintf(_(\"Marking reachable objects...\"));\n \t\tmark_reachable_objects(&cb.cmd.revs, 0, 0, NULL);\n \t\tif (flags & EXPIRE_REFLOGS_VERBOSE)\n \t\t\tputchar('\\n');\n@@ -598,7 +602,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \t\tchar *ref;\n \t\tstruct object_id oid;\n \t\tif (!dwim_log(argv[i], strlen(argv[i]), &oid, &ref)) {\n-\t\t\tstatus |= error(\"%s points nowhere!\", argv[i]);\n+\t\t\tstatus |= error(_(\"%s points nowhere!\"), argv[i]);\n \t\t\tcontinue;\n \t\t}\n \t\tset_reflog_expiry_param(&cb.cmd, explicit_expiry, ref);\n@@ -644,13 +648,13 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)\n \t\t\tbreak;\n \t\t}\n \t\telse if (arg[0] == '-')\n-\t\t\tusage(reflog_delete_usage);\n+\t\t\tusage(_(reflog_delete_usage));\n \t\telse\n \t\t\tbreak;\n \t}\n \n \tif (argc - i < 1)\n-\t\treturn error(\"Nothing to delete?\");\n+\t\treturn error(_(\"no reflog specified to delete\"));\n \n \tfor ( ; i < argc; i++) {\n \t\tconst char *spec = strstr(argv[i], \"@{\");\n@@ -659,12 +663,12 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)\n \t\tint recno;\n \n \t\tif (!spec) {\n-\t\t\tstatus |= error(\"Not a reflog: %s\", argv[i]);\n+\t\t\tstatus |= error(_(\"not a reflog: %s\"), argv[i]);\n \t\t\tcontinue;\n \t\t}\n \n \t\tif (!dwim_log(argv[i], spec - argv[i], &oid, &ref)) {\n-\t\t\tstatus |= error(\"no reflog for '%s'\", argv[i]);\n+\t\t\tstatus |= error(_(\"no reflog for '%s'\"), argv[i]);\n \t\t\tcontinue;\n \t\t}\n \n@@ -699,7 +703,7 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n \t\t\tbreak;\n \t\t}\n \t\telse if (arg[0] == '-')\n-\t\t\tusage(reflog_exists_usage);\n+\t\t\tusage(_(reflog_exists_usage));\n \t\telse\n \t\t\tbreak;\n \t}\n@@ -707,10 +711,10 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n \tstart = i;\n \n \tif (argc - start != 1)\n-\t\tusage(reflog_exists_usage);\n+\t\tusage(_(reflog_exists_usage));\n \n \tif (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL))\n-\t\tdie(\"invalid ref format: %s\", argv[start]);\n+\t\tdie(_(\"invalid ref format: %s\"), argv[start]);\n \treturn !reflog_exists(argv[start]);\n }\n \n@@ -719,12 +723,12 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n  */\n \n static const char reflog_usage[] =\n-\"git reflog [ show | expire | delete | exists ]\";\n+N_(\"git reflog [ show | expire | delete | exists ]\");\n \n int cmd_reflog(int argc, const char **argv, const char *prefix)\n {\n \tif (argc > 1 && !strcmp(argv[1], \"-h\"))\n-\t\tusage(reflog_usage);\n+\t\tusage(_(reflog_usage));\n \n \t/* With no command, we default to showing it. */\n \tif (argc < 2 || *argv[1] == '-')\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362514","messageId":"20181105192059.20303-12-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 11/16] repack: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:54Z","receivedAt":"2018-11-05T19:21:24Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Two strings are slightly updated to be consistent with the rest: die()\nstarts with lowercase.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/repack.c | 26 +++++++++++++-------------\n 1 file changed, 13 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/repack.c b/builtin/repack.c\nindex c6a7943d5c..0af20fa0fc 100644\n--- a/builtin/repack.c\n+++ b/builtin/repack.c\n@@ -197,7 +197,7 @@ static int write_oid(const struct object_id *oid, struct packed_git *pack,\n \n \tif (cmd->in == -1) {\n \t\tif (start_command(cmd))\n-\t\t\tdie(\"Could not start pack-objects to repack promisor objects\");\n+\t\t\tdie(_(\"could not start pack-objects to repack promisor objects\"));\n \t}\n \n \txwrite(cmd->in, oid_to_hex(oid), GIT_SHA1_HEXSZ);\n@@ -236,7 +236,7 @@ static void repack_promisor_objects(const struct pack_objects_args *args,\n \t\tchar *promisor_name;\n \t\tint fd;\n \t\tif (line.len != 40)\n-\t\t\tdie(\"repack: Expecting 40 character sha1 lines only from pack-objects.\");\n+\t\t\tdie(_(\"repack: Expecting 40 character sha1 lines only from pack-objects.\"));\n \t\tstring_list_append(names, line.buf);\n \n \t\t/*\n@@ -247,13 +247,13 @@ static void repack_promisor_objects(const struct pack_objects_args *args,\n \t\t\t\t\t  line.buf);\n \t\tfd = open(promisor_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\tif (fd < 0)\n-\t\t\tdie_errno(\"unable to create '%s'\", promisor_name);\n+\t\t\tdie_errno(_(\"unable to create '%s'\"), promisor_name);\n \t\tclose(fd);\n \t\tfree(promisor_name);\n \t}\n \tfclose(out);\n \tif (finish_command(&cmd))\n-\t\tdie(\"Could not finish pack-objects to repack promisor objects\");\n+\t\tdie(_(\"could not finish pack-objects to repack promisor objects\"));\n }\n \n #define ALL_INTO_ONE 1\n@@ -408,7 +408,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \tout = xfdopen(cmd.out, \"r\");\n \twhile (strbuf_getline_lf(&line, out) != EOF) {\n \t\tif (line.len != 40)\n-\t\t\tdie(\"repack: Expecting 40 character sha1 lines only from pack-objects.\");\n+\t\t\tdie(_(\"repack: Expecting 40 character sha1 lines only from pack-objects\"));\n \t\tstring_list_append(&names, line.buf);\n \t}\n \tfclose(out);\n@@ -417,7 +417,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\treturn ret;\n \n \tif (!names.nr && !po_args.quiet)\n-\t\tprintf(\"Nothing new to pack.\\n\");\n+\t\tprintf_ln(_(\"Nothing new to pack.\"));\n \n \t/*\n \t * Ok we have prepared all new packfiles.\n@@ -477,13 +477,13 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\tif (rollback_failure.nr) {\n \t\t\tint i;\n \t\t\tfprintf(stderr,\n-\t\t\t\t\"WARNING: Some packs in use have been renamed by\\n\"\n-\t\t\t\t\"WARNING: prefixing old- to their name, in order to\\n\"\n-\t\t\t\t\"WARNING: replace them with the new version of the\\n\"\n-\t\t\t\t\"WARNING: file.  But the operation failed, and the\\n\"\n-\t\t\t\t\"WARNING: attempt to rename them back to their\\n\"\n-\t\t\t\t\"WARNING: original names also failed.\\n\"\n-\t\t\t\t\"WARNING: Please rename them in %s manually:\\n\", packdir);\n+\t\t\t\t_(\"WARNING: Some packs in use have been renamed by\\n\"\n+\t\t\t\t  \"WARNING: prefixing old- to their name, in order to\\n\"\n+\t\t\t\t  \"WARNING: replace them with the new version of the\\n\"\n+\t\t\t\t  \"WARNING: file.  But the operation failed, and the\\n\"\n+\t\t\t\t  \"WARNING: attempt to rename them back to their\\n\"\n+\t\t\t\t  \"WARNING: original names also failed.\\n\"\n+\t\t\t\t  \"WARNING: Please rename them in %s manually:\\n\"), packdir);\n \t\t\tfor (i = 0; i < rollback_failure.nr; i++)\n \t\t\t\tfprintf(stderr, \"WARNING:   old-%s -> %s\\n\",\n \t\t\t\t\trollback_failure.items[i].string,\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362517","messageId":"20181105192059.20303-11-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 10/16] remote.c: mark messages for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:53Z","receivedAt":"2018-11-05T19:21:24Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The two strings are slightly modified to be consistent with the rest:\ndie() and error() start with a lowercase.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n remote.c | 43 ++++++++++++++++++++++---------------------\n 1 file changed, 22 insertions(+), 21 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex 257630ff21..11b33d1625 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -359,7 +359,7 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\treturn 0;\n \t/* Handle remote.<name>.* variables */\n \tif (*name == '/') {\n-\t\twarning(\"Config remote shorthand cannot begin with '/': %s\",\n+\t\twarning(_(\"config remote shorthand cannot begin with '/': %s\"),\n \t\t\tname);\n \t\treturn 0;\n \t}\n@@ -406,7 +406,7 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\tif (!remote->receivepack)\n \t\t\tremote->receivepack = v;\n \t\telse\n-\t\t\terror(\"more than one receivepack given, using the first\");\n+\t\t\terror(_(\"more than one receivepack given, using the first\"));\n \t} else if (!strcmp(subkey, \"uploadpack\")) {\n \t\tconst char *v;\n \t\tif (git_config_string(&v, key, value))\n@@ -414,7 +414,7 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\tif (!remote->uploadpack)\n \t\t\tremote->uploadpack = v;\n \t\telse\n-\t\t\terror(\"more than one uploadpack given, using the first\");\n+\t\t\terror(_(\"more than one uploadpack given, using the first\"));\n \t} else if (!strcmp(subkey, \"tagopt\")) {\n \t\tif (!strcmp(value, \"--no-tags\"))\n \t\t\tremote->fetch_tags = -1;\n@@ -680,7 +680,7 @@ static int match_name_with_pattern(const char *key, const char *name,\n \tsize_t namelen;\n \tint ret;\n \tif (!kstar)\n-\t\tdie(\"Key '%s' of pattern had no '*'\", key);\n+\t\tdie(_(\"key '%s' of pattern had no '*'\"), key);\n \tklen = kstar - key;\n \tksuffixlen = strlen(kstar + 1);\n \tnamelen = strlen(name);\n@@ -690,7 +690,7 @@ static int match_name_with_pattern(const char *key, const char *name,\n \t\tstruct strbuf sb = STRBUF_INIT;\n \t\tconst char *vstar = strchr(value, '*');\n \t\tif (!vstar)\n-\t\t\tdie(\"Value '%s' of pattern has no '*'\", value);\n+\t\t\tdie(_(\"value '%s' of pattern has no '*'\"), value);\n \t\tstrbuf_add(&sb, value, vstar - value);\n \t\tstrbuf_add(&sb, name + klen, namelen - klen - ksuffixlen);\n \t\tstrbuf_addstr(&sb, vstar + 1);\n@@ -995,12 +995,12 @@ static int match_explicit_lhs(struct ref *src,\n \t\t * way to delete 'other' ref at the remote end.\n \t\t */\n \t\tif (try_explicit_object_name(rs->src, match) < 0)\n-\t\t\treturn error(\"src refspec %s does not match any.\", rs->src);\n+\t\t\treturn error(_(\"src refspec %s does not match any\"), rs->src);\n \t\tif (allocated_match)\n \t\t\t*allocated_match = 1;\n \t\treturn 0;\n \tdefault:\n-\t\treturn error(\"src refspec %s matches more than one.\", rs->src);\n+\t\treturn error(_(\"src refspec %s matches more than one\"), rs->src);\n \t}\n }\n \n@@ -1030,7 +1030,7 @@ static int match_explicit(struct ref *src, struct ref *dst,\n \t\tif (!dst_value ||\n \t\t    ((flag & REF_ISSYMREF) &&\n \t\t     !starts_with(dst_value, \"refs/heads/\")))\n-\t\t\tdie(\"%s cannot be resolved to branch.\",\n+\t\t\tdie(_(\"%s cannot be resolved to branch\"),\n \t\t\t    matched_src->name);\n \t}\n \n@@ -1041,30 +1041,30 @@ static int match_explicit(struct ref *src, struct ref *dst,\n \t\tif (starts_with(dst_value, \"refs/\"))\n \t\t\tmatched_dst = make_linked_ref(dst_value, dst_tail);\n \t\telse if (is_null_oid(&matched_src->new_oid))\n-\t\t\terror(\"unable to delete '%s': remote ref does not exist\",\n+\t\t\terror(_(\"unable to delete '%s': remote ref does not exist\"),\n \t\t\t      dst_value);\n \t\telse if ((dst_guess = guess_ref(dst_value, matched_src))) {\n \t\t\tmatched_dst = make_linked_ref(dst_guess, dst_tail);\n \t\t\tfree(dst_guess);\n \t\t} else\n-\t\t\terror(\"unable to push to unqualified destination: %s\\n\"\n-\t\t\t      \"The destination refspec neither matches an \"\n-\t\t\t      \"existing ref on the remote nor\\n\"\n-\t\t\t      \"begins with refs/, and we are unable to \"\n-\t\t\t      \"guess a prefix based on the source ref.\",\n+\t\t\terror(_(\"unable to push to unqualified destination: %s\\n\"\n+\t\t\t\t\"The destination refspec neither matches an \"\n+\t\t\t\t\"existing ref on the remote nor\\n\"\n+\t\t\t\t\"begins with refs/, and we are unable to \"\n+\t\t\t\t\"guess a prefix based on the source ref.\"),\n \t\t\t      dst_value);\n \t\tbreak;\n \tdefault:\n \t\tmatched_dst = NULL;\n-\t\terror(\"dst refspec %s matches more than one.\",\n+\t\terror(_(\"dst refspec %s matches more than one\"),\n \t\t      dst_value);\n \t\tbreak;\n \t}\n \tif (!matched_dst)\n \t\treturn -1;\n \tif (matched_dst->peer_ref)\n-\t\treturn error(\"dst ref %s receives from more than one src.\",\n-\t\t      matched_dst->name);\n+\t\treturn error(_(\"dst ref %s receives from more than one src\"),\n+\t\t\t     matched_dst->name);\n \telse {\n \t\tmatched_dst->peer_ref = allocated_src ?\n \t\t\t\t\tmatched_src :\n@@ -1750,7 +1750,7 @@ int get_fetch_map(const struct ref *remote_refs,\n \t\t\tref_map = get_remote_ref(remote_refs, name);\n \t\t}\n \t\tif (!missing_ok && !ref_map)\n-\t\t\tdie(\"Couldn't find remote ref %s\", name);\n+\t\t\tdie(_(\"couldn't find remote ref %s\"), name);\n \t\tif (ref_map) {\n \t\t\tref_map->peer_ref = get_local_ref(refspec->dst);\n \t\t\tif (ref_map->peer_ref && refspec->force)\n@@ -1763,7 +1763,7 @@ int get_fetch_map(const struct ref *remote_refs,\n \t\t\tif (!starts_with((*rmp)->peer_ref->name, \"refs/\") ||\n \t\t\t    check_refname_format((*rmp)->peer_ref->name, 0)) {\n \t\t\t\tstruct ref *ignore = *rmp;\n-\t\t\t\terror(\"* Ignoring funny ref '%s' locally\",\n+\t\t\t\terror(_(\"* Ignoring funny ref '%s' locally\"),\n \t\t\t\t      (*rmp)->peer_ref->name);\n \t\t\t\t*rmp = (*rmp)->next;\n \t\t\t\tfree(ignore->peer_ref);\n@@ -1858,7 +1858,7 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,\n \trepo_init_revisions(the_repository, &revs, NULL);\n \tsetup_revisions(argv.argc, argv.argv, &revs, NULL);\n \tif (prepare_revision_walk(&revs))\n-\t\tdie(\"revision walk setup failed\");\n+\t\tdie(_(\"revision walk setup failed\"));\n \n \t/* ... and count the commits on each side. */\n \twhile (1) {\n@@ -2131,7 +2131,8 @@ static int parse_push_cas_option(struct push_cas_option *cas, const char *arg, i\n \telse if (!colon[1])\n \t\toidclr(&entry->expect);\n \telse if (get_oid(colon + 1, &entry->expect))\n-\t\treturn error(\"cannot parse expected object name '%s'\", colon + 1);\n+\t\treturn error(_(\"cannot parse expected object name '%s'\"),\n+\t\t\t     colon + 1);\n \treturn 0;\n }\n \n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362515","messageId":"20181105192059.20303-14-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 13/16] parse-options.c: turn some die() to BUG()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:56Z","receivedAt":"2018-11-05T19:21:26Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"These two strings are clearly not for the user to see. Reduce the\nviolence in one string while at there.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n parse-options.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex 0bf817193d..3f5f985c1e 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -197,7 +197,7 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\treturn 0;\n \n \tdefault:\n-\t\tdie(\"should not happen, someone must be hit on the forehead\");\n+\t\tBUG(\"opt->type %d should not happen\", opt->type);\n \t}\n }\n \n@@ -424,7 +424,7 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,\n \tctx->flags = flags;\n \tif ((flags & PARSE_OPT_KEEP_UNKNOWN) &&\n \t    (flags & PARSE_OPT_STOP_AT_NON_OPTION))\n-\t\tdie(\"STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together\");\n+\t\tBUG(\"STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together\");\n \tparse_options_check(options);\n }\n \n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362516","messageId":"20181105192059.20303-15-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 14/16] parse-options.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:57Z","receivedAt":"2018-11-05T19:21:27Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"One error is updated to start with lowercase to be consistent with the\nrest.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n parse-options.c          | 14 +++++++-------\n t/t0040-parse-options.sh |  4 ++--\n 2 files changed, 9 insertions(+), 9 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex 3f5f985c1e..86aad2e185 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -319,8 +319,8 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,\n \t}\n \n \tif (ambiguous_option) {\n-\t\terror(\"Ambiguous option: %s \"\n-\t\t\t\"(could be --%s%s or --%s%s)\",\n+\t\terror(_(\"ambiguous option: %s \"\n+\t\t\t\"(could be --%s%s or --%s%s)\"),\n \t\t\targ,\n \t\t\t(ambiguous_flags & OPT_UNSET) ?  \"no-\" : \"\",\n \t\t\tambiguous_option->long_name,\n@@ -353,7 +353,7 @@ static void check_typos(const char *arg, const struct option *options)\n \t\treturn;\n \n \tif (starts_with(arg, \"no-\")) {\n-\t\terror (\"did you mean `--%s` (with two dashes ?)\", arg);\n+\t\terror(_(\"did you mean `--%s` (with two dashes ?)\"), arg);\n \t\texit(129);\n \t}\n \n@@ -361,7 +361,7 @@ static void check_typos(const char *arg, const struct option *options)\n \t\tif (!options->long_name)\n \t\t\tcontinue;\n \t\tif (starts_with(options->long_name, arg)) {\n-\t\t\terror (\"did you mean `--%s` (with two dashes ?)\", arg);\n+\t\t\terror(_(\"did you mean `--%s` (with two dashes ?)\"), arg);\n \t\t\texit(129);\n \t\t}\n \t}\n@@ -644,11 +644,11 @@ int parse_options(int argc, const char **argv, const char *prefix,\n \t\tbreak;\n \tdefault: /* PARSE_OPT_UNKNOWN */\n \t\tif (ctx.argv[0][1] == '-') {\n-\t\t\terror(\"unknown option `%s'\", ctx.argv[0] + 2);\n+\t\t\terror(_(\"unknown option `%s'\"), ctx.argv[0] + 2);\n \t\t} else if (isascii(*ctx.opt)) {\n-\t\t\terror(\"unknown switch `%c'\", *ctx.opt);\n+\t\t\terror(_(\"unknown switch `%c'\"), *ctx.opt);\n \t\t} else {\n-\t\t\terror(\"unknown non-ascii option in string: `%s'\",\n+\t\t\terror(_(\"unknown non-ascii option in string: `%s'\"),\n \t\t\t      ctx.argv[0]);\n \t\t}\n \t\tusage_with_options(usagestr, options);\ndiff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh\nindex 17d0c18feb..e46b1e02f0 100755\n--- a/t/t0040-parse-options.sh\n+++ b/t/t0040-parse-options.sh\n@@ -228,7 +228,7 @@ EOF\n test_expect_success 'detect possible typos' '\n \ttest_must_fail test-tool parse-options -boolean >output 2>output.err &&\n \ttest_must_be_empty output &&\n-\ttest_cmp typo.err output.err\n+\ttest_i18ncmp typo.err output.err\n '\n \n cat >typo.err <<\\EOF\n@@ -238,7 +238,7 @@ EOF\n test_expect_success 'detect possible typos' '\n \ttest_must_fail test-tool parse-options -ambiguous >output 2>output.err &&\n \ttest_must_be_empty output &&\n-\ttest_cmp typo.err output.err\n+\ttest_i18ncmp typo.err output.err\n '\n \n test_expect_success 'keep some options as arguments' '\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362518","messageId":"20181105192059.20303-13-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 12/16] parse-options: replace opterror() with optname()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:55Z","receivedAt":"2018-11-05T19:21:28Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"There are a few issues with opterror()\n\n- it tries to assemble an English sentence from pieces. This is not\n  great for translators because we give them pieces instead of a full\n  sentence.\n\n- It's a wrapper around error() and needs some hack to let the\n  compiler know it always returns -1.\n\n- Since it takes a string instead of printf format, one call site has\n  to assemble the string manually before passing to it.\n\nKill it and produce the option name with optname(). The user will use\nerror() directly. This solves the second and third problems.\n\nIt kind helps the first problem as well because \"%s does foo\" does\ngive a translator a full sentence in a sense and let them reorder if\nneeded. But it has limitations, if the subject part has to change\nbased on the rest of the sentence, that language is screwed. This is\nalso why I try to avoid calling optname() when 'flags' is known in\nadvance.\n\nMark of these strings for translation as well while at there.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/merge.c     |  2 +-\n builtin/revert.c    |  3 ++-\n parse-options-cb.c  |  7 ++++---\n parse-options.c     | 46 +++++++++++++++++++++++++--------------------\n parse-options.h     |  5 +----\n ref-filter.c        |  8 +++++---\n t/t4211-line-log.sh |  2 +-\n 7 files changed, 40 insertions(+), 33 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 92ba7e1c6d..82248d43c3 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -128,7 +128,7 @@ static int option_read_message(struct parse_opt_ctx_t *ctx,\n \t\tctx->argc--;\n \t\targ = *++ctx->argv;\n \t} else\n-\t\treturn opterror(opt, \"requires a value\", 0);\n+\t\treturn error(_(\"option `%s' requires a value\"), opt->long_name);\n \n \tif (buf->len)\n \t\tstrbuf_addch(buf, '\\n');\ndiff --git a/builtin/revert.c b/builtin/revert.c\nindex c93393c89b..11190d2ab4 100644\n--- a/builtin/revert.c\n+++ b/builtin/revert.c\n@@ -69,7 +69,8 @@ static int option_parse_m(const struct option *opt,\n \n \treplay->mainline = strtol(arg, &end, 10);\n \tif (*end || replay->mainline <= 0)\n-\t\treturn opterror(opt, \"expects a number greater than zero\", 0);\n+\t\treturn error(_(\"option `%s' expects a number greater than zero\"),\n+\t\t\t     opt->long_name);\n \n \treturn 0;\n }\ndiff --git a/parse-options-cb.c b/parse-options-cb.c\nindex e8236534ac..813eb6301b 100644\n--- a/parse-options-cb.c\n+++ b/parse-options-cb.c\n@@ -18,7 +18,8 @@ int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)\n \t} else {\n \t\tv = strtol(arg, (char **)&arg, 10);\n \t\tif (*arg)\n-\t\t\treturn opterror(opt, \"expects a numerical value\", 0);\n+\t\t\treturn error(_(\"option `%s' expects a numerical value\"),\n+\t\t\t\t     opt->long_name);\n \t\tif (v && v < MINIMUM_ABBREV)\n \t\t\tv = MINIMUM_ABBREV;\n \t\telse if (v > 40)\n@@ -54,8 +55,8 @@ int parse_opt_color_flag_cb(const struct option *opt, const char *arg,\n \t\targ = unset ? \"never\" : (const char *)opt->defval;\n \tvalue = git_config_colorbool(NULL, arg);\n \tif (value < 0)\n-\t\treturn opterror(opt,\n-\t\t\t\"expects \\\"always\\\", \\\"auto\\\", or \\\"never\\\"\", 0);\n+\t\treturn error(_(\"option `%s' expects \\\"always\\\", \\\"auto\\\", or \\\"never\\\"\"),\n+\t\t\t     opt->long_name);\n \t*(int *)opt->value = value;\n \treturn 0;\n }\ndiff --git a/parse-options.c b/parse-options.c\nindex 3b874a83a0..0bf817193d 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -32,7 +32,7 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,\n \t\tp->argc--;\n \t\t*arg = *++p->argv;\n \t} else\n-\t\treturn opterror(opt, \"requires a value\", flags);\n+\t\treturn error(_(\"%s requires a value\"), optname(opt, flags));\n \treturn 0;\n }\n \n@@ -49,7 +49,6 @@ static int opt_command_mode_error(const struct option *opt,\n \t\t\t\t  int flags)\n {\n \tconst struct option *that;\n-\tstruct strbuf message = STRBUF_INIT;\n \tstruct strbuf that_name = STRBUF_INIT;\n \n \t/*\n@@ -67,13 +66,13 @@ static int opt_command_mode_error(const struct option *opt,\n \t\t\tstrbuf_addf(&that_name, \"--%s\", that->long_name);\n \t\telse\n \t\t\tstrbuf_addf(&that_name, \"-%c\", that->short_name);\n-\t\tstrbuf_addf(&message, \": incompatible with %s\", that_name.buf);\n+\t\terror(_(\"%s is incompatible with %s\"),\n+\t\t      optname(opt, flags), that_name.buf);\n \t\tstrbuf_release(&that_name);\n-\t\topterror(opt, message.buf, flags);\n-\t\tstrbuf_release(&message);\n \t\treturn -1;\n \t}\n-\treturn opterror(opt, \": incompatible with something else\", flags);\n+\treturn error(_(\"%s : incompatible with something else\"),\n+\t\t     optname(opt, flags));\n }\n \n static int get_value(struct parse_opt_ctx_t *p,\n@@ -86,11 +85,11 @@ static int get_value(struct parse_opt_ctx_t *p,\n \tint err;\n \n \tif (unset && p->opt)\n-\t\treturn opterror(opt, \"takes no value\", flags);\n+\t\treturn error(_(\"%s takes no value\"), optname(opt, flags));\n \tif (unset && (opt->flags & PARSE_OPT_NONEG))\n-\t\treturn opterror(opt, \"isn't available\", flags);\n+\t\treturn error(_(\"%s isn't available\"), optname(opt, flags));\n \tif (!(flags & OPT_SHORT) && p->opt && (opt->flags & PARSE_OPT_NOARG))\n-\t\treturn opterror(opt, \"takes no value\", flags);\n+\t\treturn error(_(\"%s takes no value\"), optname(opt, flags));\n \n \tswitch (opt->type) {\n \tcase OPTION_LOWLEVEL_CALLBACK:\n@@ -176,7 +175,8 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\t\treturn -1;\n \t\t*(int *)opt->value = strtol(arg, (char **)&s, 10);\n \t\tif (*s)\n-\t\t\treturn opterror(opt, \"expects a numerical value\", flags);\n+\t\t\treturn error(_(\"%s expects a numerical value\"),\n+\t\t\t\t     optname(opt, flags));\n \t\treturn 0;\n \n \tcase OPTION_MAGNITUDE:\n@@ -191,9 +191,9 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\tif (get_arg(p, opt, flags, &arg))\n \t\t\treturn -1;\n \t\tif (!git_parse_ulong(arg, opt->value))\n-\t\t\treturn opterror(opt,\n-\t\t\t\t\"expects a non-negative integer value with an optional k/m/g suffix\",\n-\t\t\t\tflags);\n+\t\t\treturn error(_(\"%s expects a non-negative integer value\"\n+\t\t\t\t       \" with an optional k/m/g suffix\"),\n+\t\t\t\t     optname(opt, flags));\n \t\treturn 0;\n \n \tdefault:\n@@ -257,7 +257,8 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,\n \t\t\tif (!rest)\n \t\t\t\tcontinue;\n \t\t\tif (*rest == '=')\n-\t\t\t\treturn opterror(options, \"takes no value\", flags);\n+\t\t\t\treturn error(_(\"%s takes no value\"),\n+\t\t\t\t\t     optname(options, flags));\n \t\t\tif (*rest)\n \t\t\t\tcontinue;\n \t\t\tp->out[p->cpidx++] = arg - 2;\n@@ -773,12 +774,17 @@ void NORETURN usage_msg_opt(const char *msg,\n \tusage_with_options(usagestr, options);\n }\n \n-#undef opterror\n-int opterror(const struct option *opt, const char *reason, int flags)\n+const char *optname(const struct option *opt, int flags)\n {\n+\tstatic struct strbuf sb = STRBUF_INIT;\n+\n+\tstrbuf_reset(&sb);\n \tif (flags & OPT_SHORT)\n-\t\treturn error(\"switch `%c' %s\", opt->short_name, reason);\n-\tif (flags & OPT_UNSET)\n-\t\treturn error(\"option `no-%s' %s\", opt->long_name, reason);\n-\treturn error(\"option `%s' %s\", opt->long_name, reason);\n+\t\tstrbuf_addf(&sb, \"switch `%c'\", opt->short_name);\n+\telse if (flags & OPT_UNSET)\n+\t\tstrbuf_addf(&sb, \"option `no-%s'\", opt->long_name);\n+\telse\n+\t\tstrbuf_addf(&sb, \"option `%s'\", opt->long_name);\n+\n+\treturn sb.buf;\n }\ndiff --git a/parse-options.h b/parse-options.h\nindex dd14911a29..2e146aa6fa 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -189,10 +189,7 @@ extern NORETURN void usage_msg_opt(const char *msg,\n \t\t\t\t   const struct option *options);\n \n extern int optbug(const struct option *opt, const char *reason);\n-extern int opterror(const struct option *opt, const char *reason, int flags);\n-#if defined(__GNUC__)\n-#define opterror(o,r,f) (opterror((o),(r),(f)), const_error())\n-#endif\n+const char *optname(const struct option *opt, int flags);\n \n /*----- incremental advanced APIs -----*/\n \ndiff --git a/ref-filter.c b/ref-filter.c\nindex 2a05619211..0681359100 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -2302,9 +2302,11 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n \n \tif (rf->merge) {\n \t\tif (no_merged) {\n-\t\t\treturn opterror(opt, \"is incompatible with --merged\", 0);\n+\t\t\treturn error(_(\"option `%s' is incompatible with --merged\"),\n+\t\t\t\t     opt->long_name);\n \t\t} else {\n-\t\t\treturn opterror(opt, \"is incompatible with --no-merged\", 0);\n+\t\t\treturn error(_(\"option `%s' is incompatible with --no-merged\"),\n+\t\t\t\t     opt->long_name);\n \t\t}\n \t}\n \n@@ -2318,7 +2320,7 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n \trf->merge_commit = lookup_commit_reference_gently(the_repository,\n \t\t\t\t\t\t\t  &oid, 0);\n \tif (!rf->merge_commit)\n-\t\treturn opterror(opt, \"must point to a commit\", 0);\n+\t\treturn error(_(\"option `%s' must point to a commit\"), opt->long_name);\n \n \treturn 0;\n }\ndiff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh\nindex ef1322148e..bd5fe4d148 100755\n--- a/t/t4211-line-log.sh\n+++ b/t/t4211-line-log.sh\n@@ -25,7 +25,7 @@ canned_test_failure () {\n test_bad_opts () {\n \ttest_expect_success \"invalid args: $1\" \"\n \t\ttest_must_fail git log $1 2>errors &&\n-\t\tgrep '$2' errors\n+\t\ttest_i18ngrep '$2' errors\n \t\"\n }\n \n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362519","messageId":"20181105192059.20303-16-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 15/16] fsck: reduce word legos to help i18n","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:58Z","receivedAt":"2018-11-05T19:21:29Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"These messages will be marked for translation later. Reduce word legos\nand give translators almost full phrases. describe_object() is updated\nso that it can be called from printf() twice.\n\nWhile at there, remove \\n from the strings to reduce a bit of work\nfrom translators.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/fsck.c | 62 ++++++++++++++++++++++++++++++--------------------\n 1 file changed, 37 insertions(+), 25 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex 06eb421720..504f47d7a4 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -52,16 +52,24 @@ static int name_objects;\n \n static const char *describe_object(struct object *obj)\n {\n-\tstatic struct strbuf buf = STRBUF_INIT;\n-\tchar *name = name_objects ?\n-\t\tlookup_decoration(fsck_walk_options.object_names, obj) : NULL;\n+\tstatic struct strbuf bufs[4] = {\n+\t\tSTRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT\n+\t};\n+\tstatic int b = 0;\n+\tstruct strbuf *buf;\n+\tchar *name = NULL;\n \n-\tstrbuf_reset(&buf);\n-\tstrbuf_addstr(&buf, oid_to_hex(&obj->oid));\n+\tif (name_objects)\n+\t\tname = lookup_decoration(fsck_walk_options.object_names, obj);\n+\n+\tbuf = bufs + b;\n+\tb = (b + 1) % ARRAY_SIZE(bufs);\n+\tstrbuf_reset(buf);\n+\tstrbuf_addstr(buf, oid_to_hex(&obj->oid));\n \tif (name)\n-\t\tstrbuf_addf(&buf, \" (%s)\", name);\n+\t\tstrbuf_addf(buf, \" (%s)\", name);\n \n-\treturn buf.buf;\n+\treturn buf->buf;\n }\n \n static const char *printable_type(struct object *obj)\n@@ -105,25 +113,26 @@ static int fsck_config(const char *var, const char *value, void *cb)\n \treturn git_default_config(var, value, cb);\n }\n \n-static void objreport(struct object *obj, const char *msg_type,\n-\t\t\tconst char *err)\n-{\n-\tfprintf(stderr, \"%s in %s %s: %s\\n\",\n-\t\tmsg_type, printable_type(obj), describe_object(obj), err);\n-}\n-\n static int objerror(struct object *obj, const char *err)\n {\n \terrors_found |= ERROR_OBJECT;\n-\tobjreport(obj, \"error\", err);\n+\tfprintf_ln(stderr, \"error in %s %s: %s\",\n+\t\t   printable_type(obj), describe_object(obj), err);\n \treturn -1;\n }\n \n static int fsck_error_func(struct fsck_options *o,\n \tstruct object *obj, int type, const char *message)\n {\n-\tobjreport(obj, (type == FSCK_WARN) ? \"warning\" : \"error\", message);\n-\treturn (type == FSCK_WARN) ? 0 : 1;\n+\tif (type == FSCK_WARN) {\n+\t\tfprintf_ln(stderr, \"warning in %s %s: %s\",\n+\t\t\t   printable_type(obj), describe_object(obj), message);\n+\t\treturn 0;\n+\t}\n+\n+\tfprintf_ln(stderr, \"error in %s %s: %s\",\n+\t\t   printable_type(obj), describe_object(obj), message);\n+\treturn 1;\n }\n \n static struct object_array pending;\n@@ -165,10 +174,12 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt\n \n \tif (!(obj->flags & HAS_OBJ)) {\n \t\tif (parent && !has_object_file(&obj->oid)) {\n-\t\t\tprintf(\"broken link from %7s %s\\n\",\n-\t\t\t\t printable_type(parent), describe_object(parent));\n-\t\t\tprintf(\"              to %7s %s\\n\",\n-\t\t\t\t printable_type(obj), describe_object(obj));\n+\t\t\tprintf_ln(\"broken link from %7s %s\\n\"\n+\t\t\t\t  \"              to %7s %s\",\n+\t\t\t\t  printable_type(parent),\n+\t\t\t\t  describe_object(parent),\n+\t\t\t\t  printable_type(obj),\n+\t\t\t\t  describe_object(obj));\n \t\t\terrors_found |= ERROR_REACHABLE;\n \t\t}\n \t\treturn 1;\n@@ -371,10 +382,11 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)\n \t\tstruct tag *tag = (struct tag *) obj;\n \n \t\tif (show_tags && tag->tagged) {\n-\t\t\tprintf(\"tagged %s %s\", printable_type(tag->tagged),\n-\t\t\t\tdescribe_object(tag->tagged));\n-\t\t\tprintf(\" (%s) in %s\\n\", tag->tag,\n-\t\t\t\tdescribe_object(&tag->object));\n+\t\t\tprintf_ln(\"tagged %s %s (%s) in %s\",\n+\t\t\t\t  printable_type(tag->tagged),\n+\t\t\t\t  describe_object(tag->tagged),\n+\t\t\t\t  tag->tag,\n+\t\t\t\t  describe_object(&tag->object));\n \t\t}\n \t}\n \n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362520","messageId":"20181105192059.20303-17-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v2 16/16] fsck: mark strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-05T19:20:59Z","receivedAt":"2018-11-05T19:21:31Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Two die() are updated to start with lowercase to be consistent with\nthe rest.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/fsck.c             | 106 ++++++++++++++++++++-----------------\n t/t1410-reflog.sh          |   6 +--\n t/t1450-fsck.sh            |  50 ++++++++---------\n t/t6050-replace.sh         |   4 +-\n t/t7415-submodule-names.sh |   6 +--\n 5 files changed, 90 insertions(+), 82 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex 504f47d7a4..0720708977 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -85,7 +85,7 @@ static const char *printable_type(struct object *obj)\n \n \tret = type_name(obj->type);\n \tif (!ret)\n-\t\tret = \"unknown\";\n+\t\tret = _(\"unknown\");\n \n \treturn ret;\n }\n@@ -116,7 +116,8 @@ static int fsck_config(const char *var, const char *value, void *cb)\n static int objerror(struct object *obj, const char *err)\n {\n \terrors_found |= ERROR_OBJECT;\n-\tfprintf_ln(stderr, \"error in %s %s: %s\",\n+\t/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */\n+\tfprintf_ln(stderr, _(\"error in %s %s: %s\"),\n \t\t   printable_type(obj), describe_object(obj), err);\n \treturn -1;\n }\n@@ -125,12 +126,14 @@ static int fsck_error_func(struct fsck_options *o,\n \tstruct object *obj, int type, const char *message)\n {\n \tif (type == FSCK_WARN) {\n-\t\tfprintf_ln(stderr, \"warning in %s %s: %s\",\n+\t\t/* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */\n+\t\tfprintf_ln(stderr, _(\"warning in %s %s: %s\"),\n \t\t\t   printable_type(obj), describe_object(obj), message);\n \t\treturn 0;\n \t}\n \n-\tfprintf_ln(stderr, \"error in %s %s: %s\",\n+\t/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */\n+\tfprintf_ln(stderr, _(\"error in %s %s: %s\"),\n \t\t   printable_type(obj), describe_object(obj), message);\n \treturn 1;\n }\n@@ -148,17 +151,18 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt\n \t */\n \tif (!obj) {\n \t\t/* ... these references to parent->fld are safe here */\n-\t\tprintf(\"broken link from %7s %s\\n\",\n-\t\t\t   printable_type(parent), describe_object(parent));\n-\t\tprintf(\"broken link from %7s %s\\n\",\n-\t\t\t   (type == OBJ_ANY ? \"unknown\" : type_name(type)), \"unknown\");\n+\t\tprintf_ln(_(\"broken link from %7s %s\"),\n+\t\t\t  printable_type(parent), describe_object(parent));\n+\t\tprintf_ln(_(\"broken link from %7s %s\"),\n+\t\t\t  (type == OBJ_ANY ? _(\"unknown\") : type_name(type)),\n+\t\t\t  _(\"unknown\"));\n \t\terrors_found |= ERROR_REACHABLE;\n \t\treturn 1;\n \t}\n \n \tif (type != OBJ_ANY && obj->type != type)\n \t\t/* ... and the reference to parent is safe here */\n-\t\tobjerror(parent, \"wrong object type in link\");\n+\t\tobjerror(parent, _(\"wrong object type in link\"));\n \n \tif (obj->flags & REACHABLE)\n \t\treturn 0;\n@@ -174,8 +178,8 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt\n \n \tif (!(obj->flags & HAS_OBJ)) {\n \t\tif (parent && !has_object_file(&obj->oid)) {\n-\t\t\tprintf_ln(\"broken link from %7s %s\\n\"\n-\t\t\t\t  \"              to %7s %s\",\n+\t\t\tprintf_ln(_(\"broken link from %7s %s\\n\"\n+\t\t\t\t    \"              to %7s %s\"),\n \t\t\t\t  printable_type(parent),\n \t\t\t\t  describe_object(parent),\n \t\t\t\t  printable_type(obj),\n@@ -243,8 +247,8 @@ static void check_reachable_object(struct object *obj)\n \t\t\treturn;\n \t\tif (has_object_pack(&obj->oid))\n \t\t\treturn; /* it is in pack - forget about it */\n-\t\tprintf(\"missing %s %s\\n\", printable_type(obj),\n-\t\t\tdescribe_object(obj));\n+\t\tprintf_ln(_(\"missing %s %s\"), printable_type(obj),\n+\t\t\t  describe_object(obj));\n \t\terrors_found |= ERROR_REACHABLE;\n \t\treturn;\n \t}\n@@ -269,8 +273,8 @@ static void check_unreachable_object(struct object *obj)\n \t * since this is something that is prunable.\n \t */\n \tif (show_unreachable) {\n-\t\tprintf(\"unreachable %s %s\\n\", printable_type(obj),\n-\t\t\tdescribe_object(obj));\n+\t\tprintf_ln(_(\"unreachable %s %s\"), printable_type(obj),\n+\t\t\t  describe_object(obj));\n \t\treturn;\n \t}\n \n@@ -288,8 +292,8 @@ static void check_unreachable_object(struct object *obj)\n \t */\n \tif (!(obj->flags & USED)) {\n \t\tif (show_dangling)\n-\t\t\tprintf(\"dangling %s %s\\n\", printable_type(obj),\n-\t\t\t       describe_object(obj));\n+\t\t\tprintf_ln(_(\"dangling %s %s\"), printable_type(obj),\n+\t\t\t\t  describe_object(obj));\n \t\tif (write_lost_and_found) {\n \t\t\tchar *filename = git_pathdup(\"lost-found/%s/%s\",\n \t\t\t\tobj->type == OBJ_COMMIT ? \"commit\" : \"other\",\n@@ -297,18 +301,18 @@ static void check_unreachable_object(struct object *obj)\n \t\t\tFILE *f;\n \n \t\t\tif (safe_create_leading_directories_const(filename)) {\n-\t\t\t\terror(\"Could not create lost-found\");\n+\t\t\t\terror(_(\"could not create lost-found\"));\n \t\t\t\tfree(filename);\n \t\t\t\treturn;\n \t\t\t}\n \t\t\tf = xfopen(filename, \"w\");\n \t\t\tif (obj->type == OBJ_BLOB) {\n \t\t\t\tif (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1))\n-\t\t\t\t\tdie_errno(\"Could not write '%s'\", filename);\n+\t\t\t\t\tdie_errno(_(\"could not write '%s'\"), filename);\n \t\t\t} else\n \t\t\t\tfprintf(f, \"%s\\n\", describe_object(obj));\n \t\t\tif (fclose(f))\n-\t\t\t\tdie_errno(\"Could not finish '%s'\",\n+\t\t\t\tdie_errno(_(\"could not finish '%s'\"),\n \t\t\t\t\t  filename);\n \t\t\tfree(filename);\n \t\t}\n@@ -325,7 +329,7 @@ static void check_unreachable_object(struct object *obj)\n static void check_object(struct object *obj)\n {\n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking %s\\n\", describe_object(obj));\n+\t\tfprintf_ln(stderr, _(\"Checking %s\"), describe_object(obj));\n \n \tif (obj->flags & REACHABLE)\n \t\tcheck_reachable_object(obj);\n@@ -343,7 +347,7 @@ static void check_connectivity(void)\n \t/* Look up all the requirements, warn about missing objects.. */\n \tmax = get_max_object_index();\n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking connectivity (%d objects)\\n\", max);\n+\t\tfprintf_ln(stderr, _(\"Checking connectivity (%d objects)\"), max);\n \n \tfor (i = 0; i < max; i++) {\n \t\tstruct object *obj = get_indexed_object(i);\n@@ -362,11 +366,11 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)\n \tobj->flags |= SEEN;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking %s %s\\n\",\n-\t\t\tprintable_type(obj), describe_object(obj));\n+\t\tfprintf_ln(stderr, _(\"Checking %s %s\"),\n+\t\t\t   printable_type(obj), describe_object(obj));\n \n \tif (fsck_walk(obj, NULL, &fsck_obj_options))\n-\t\tobjerror(obj, \"broken links\");\n+\t\tobjerror(obj, _(\"broken links\"));\n \terr = fsck_object(obj, buffer, size, &fsck_obj_options);\n \tif (err)\n \t\tgoto out;\n@@ -375,14 +379,15 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)\n \t\tstruct commit *commit = (struct commit *) obj;\n \n \t\tif (!commit->parents && show_root)\n-\t\t\tprintf(\"root %s\\n\", describe_object(&commit->object));\n+\t\t\tprintf_ln(_(\"root %s\"),\n+\t\t\t\t  describe_object(&commit->object));\n \t}\n \n \tif (obj->type == OBJ_TAG) {\n \t\tstruct tag *tag = (struct tag *) obj;\n \n \t\tif (show_tags && tag->tagged) {\n-\t\t\tprintf_ln(\"tagged %s %s (%s) in %s\",\n+\t\t\tprintf_ln(_(\"tagged %s %s (%s) in %s\"),\n \t\t\t\t  printable_type(tag->tagged),\n \t\t\t\t  describe_object(tag->tagged),\n \t\t\t\t  tag->tag,\n@@ -410,7 +415,8 @@ static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,\n \t\t\t\t  eaten);\n \tif (!obj) {\n \t\terrors_found |= ERROR_OBJECT;\n-\t\treturn error(\"%s: object corrupt or missing\", oid_to_hex(oid));\n+\t\treturn error(_(\"%s: object corrupt or missing\"),\n+\t\t\t     oid_to_hex(oid));\n \t}\n \tobj->flags &= ~(REACHABLE | SEEN);\n \tobj->flags |= HAS_OBJ;\n@@ -434,7 +440,8 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,\n \t\t\tobj->flags |= USED;\n \t\t\tmark_object_reachable(obj);\n \t\t} else if (!is_promisor_object(oid)) {\n-\t\t\terror(\"%s: invalid reflog entry %s\", refname, oid_to_hex(oid));\n+\t\t\terror(_(\"%s: invalid reflog entry %s\"),\n+\t\t\t      refname, oid_to_hex(oid));\n \t\t\terrors_found |= ERROR_REACHABLE;\n \t\t}\n \t}\n@@ -447,8 +454,8 @@ static int fsck_handle_reflog_ent(struct object_id *ooid, struct object_id *noid\n \tconst char *refname = cb_data;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking reflog %s->%s\\n\",\n-\t\t\toid_to_hex(ooid), oid_to_hex(noid));\n+\t\tfprintf_ln(stderr, _(\"Checking reflog %s->%s\"),\n+\t\t\t   oid_to_hex(ooid), oid_to_hex(noid));\n \n \tfsck_handle_reflog_oid(refname, ooid, 0);\n \tfsck_handle_reflog_oid(refname, noid, timestamp);\n@@ -477,13 +484,14 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid,\n \t\t\t default_refs++;\n \t\t\t return 0;\n \t\t}\n-\t\terror(\"%s: invalid sha1 pointer %s\", refname, oid_to_hex(oid));\n+\t\terror(_(\"%s: invalid sha1 pointer %s\"),\n+\t\t      refname, oid_to_hex(oid));\n \t\terrors_found |= ERROR_REACHABLE;\n \t\t/* We'll continue with the rest despite the error.. */\n \t\treturn 0;\n \t}\n \tif (obj->type != OBJ_COMMIT && is_branch(refname)) {\n-\t\terror(\"%s: not a commit\", refname);\n+\t\terror(_(\"%s: not a commit\"), refname);\n \t\terrors_found |= ERROR_REFS;\n \t}\n \tdefault_refs++;\n@@ -517,7 +525,7 @@ static void get_default_heads(void)\n \t * \"show_unreachable\" flag.\n \t */\n \tif (!default_refs) {\n-\t\tfprintf(stderr, \"notice: No default references\\n\");\n+\t\tfprintf_ln(stderr, _(\"notice: No default references\"));\n \t\tshow_unreachable = 0;\n \t}\n }\n@@ -532,7 +540,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n \n \tif (read_loose_object(path, oid, &type, &size, &contents) < 0) {\n \t\terrors_found |= ERROR_OBJECT;\n-\t\terror(\"%s: object corrupt or missing: %s\",\n+\t\terror(_(\"%s: object corrupt or missing: %s\"),\n \t\t      oid_to_hex(oid), path);\n \t\treturn 0; /* keep checking other objects */\n \t}\n@@ -545,7 +553,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n \n \tif (!obj) {\n \t\terrors_found |= ERROR_OBJECT;\n-\t\terror(\"%s: object could not be parsed: %s\",\n+\t\terror(_(\"%s: object could not be parsed: %s\"),\n \t\t      oid_to_hex(oid), path);\n \t\tif (!eaten)\n \t\t\tfree(contents);\n@@ -565,7 +573,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n static int fsck_cruft(const char *basename, const char *path, void *data)\n {\n \tif (!starts_with(basename, \"tmp_obj_\"))\n-\t\tfprintf(stderr, \"bad sha1 file: %s\\n\", path);\n+\t\tfprintf_ln(stderr, _(\"bad sha1 file: %s\"), path);\n \treturn 0;\n }\n \n@@ -580,7 +588,7 @@ static void fsck_object_dir(const char *path)\n \tstruct progress *progress = NULL;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking object directory\\n\");\n+\t\tfprintf_ln(stderr, _(\"Checking object directory\"));\n \n \tif (show_progress)\n \t\tprogress = start_progress(_(\"Checking object directories\"), 256);\n@@ -596,28 +604,28 @@ static int fsck_head_link(void)\n \tint null_is_error = 0;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking HEAD link\\n\");\n+\t\tfprintf_ln(stderr, _(\"Checking HEAD link\"));\n \n \thead_points_at = resolve_ref_unsafe(\"HEAD\", 0, &head_oid, NULL);\n \tif (!head_points_at) {\n \t\terrors_found |= ERROR_REFS;\n-\t\treturn error(\"Invalid HEAD\");\n+\t\treturn error(_(\"invalid HEAD\"));\n \t}\n \tif (!strcmp(head_points_at, \"HEAD\"))\n \t\t/* detached HEAD */\n \t\tnull_is_error = 1;\n \telse if (!starts_with(head_points_at, \"refs/heads/\")) {\n \t\terrors_found |= ERROR_REFS;\n-\t\treturn error(\"HEAD points to something strange (%s)\",\n+\t\treturn error(_(\"HEAD points to something strange (%s)\"),\n \t\t\t     head_points_at);\n \t}\n \tif (is_null_oid(&head_oid)) {\n \t\tif (null_is_error) {\n \t\t\terrors_found |= ERROR_REFS;\n-\t\t\treturn error(\"HEAD: detached HEAD points at nothing\");\n+\t\t\treturn error(_(\"HEAD: detached HEAD points at nothing\"));\n \t\t}\n-\t\tfprintf(stderr, \"notice: HEAD points to an unborn branch (%s)\\n\",\n-\t\t\thead_points_at + 11);\n+\t\tfprintf_ln(stderr, _(\"notice: HEAD points to an unborn branch (%s)\"),\n+\t\t\t   head_points_at + 11);\n \t}\n \treturn 0;\n }\n@@ -628,12 +636,12 @@ static int fsck_cache_tree(struct cache_tree *it)\n \tint err = 0;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking cache tree\\n\");\n+\t\tfprintf_ln(stderr, _(\"Checking cache tree\"));\n \n \tif (0 <= it->entry_count) {\n \t\tstruct object *obj = parse_object(the_repository, &it->oid);\n \t\tif (!obj) {\n-\t\t\terror(\"%s: invalid sha1 pointer in cache-tree\",\n+\t\t\terror(_(\"%s: invalid sha1 pointer in cache-tree\"),\n \t\t\t      oid_to_hex(&it->oid));\n \t\t\terrors_found |= ERROR_REFS;\n \t\t\treturn 1;\n@@ -644,7 +652,7 @@ static int fsck_cache_tree(struct cache_tree *it)\n \t\t\t\tobj, xstrdup(\":\"));\n \t\tmark_object_reachable(obj);\n \t\tif (obj->type != OBJ_TREE)\n-\t\t\terr |= objerror(obj, \"non-tree in cache-tree\");\n+\t\t\terr |= objerror(obj, _(\"non-tree in cache-tree\"));\n \t}\n \tfor (i = 0; i < it->subtree_nr; i++)\n \t\terr |= fsck_cache_tree(it->down[i]->cache_tree);\n@@ -786,7 +794,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \t\t\tif (!obj || !(obj->flags & HAS_OBJ)) {\n \t\t\t\tif (is_promisor_object(&oid))\n \t\t\t\t\tcontinue;\n-\t\t\t\terror(\"%s: object missing\", oid_to_hex(&oid));\n+\t\t\t\terror(_(\"%s: object missing\"), oid_to_hex(&oid));\n \t\t\t\terrors_found |= ERROR_OBJECT;\n \t\t\t\tcontinue;\n \t\t\t}\n@@ -798,7 +806,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \t\t\tmark_object_reachable(obj);\n \t\t\tcontinue;\n \t\t}\n-\t\terror(\"invalid parameter: expected sha1, got '%s'\", arg);\n+\t\terror(_(\"invalid parameter: expected sha1, got '%s'\"), arg);\n \t\terrors_found |= ERROR_OBJECT;\n \t}\n \ndiff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh\nindex 388b0611d8..353bdfd415 100755\n--- a/t/t1410-reflog.sh\n+++ b/t/t1410-reflog.sh\n@@ -20,12 +20,12 @@ check_have () {\n }\n \n check_fsck () {\n-\toutput=$(git fsck --full)\n+\tgit fsck --full >fsck.output\n \tcase \"$1\" in\n \t'')\n-\t\ttest -z \"$output\" ;;\n+\t\ttest_must_be_empty fsck.output ;;\n \t*)\n-\t\techo \"$output\" | grep \"$1\" ;;\n+\t\ttest_i18ngrep \"$1\" fsck.output ;;\n \tesac\n }\n \ndiff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh\nindex 90c765df3a..15ca98b2a9 100755\n--- a/t/t1450-fsck.sh\n+++ b/t/t1450-fsck.sh\n@@ -70,7 +70,7 @@ test_expect_success 'object with bad sha1' '\n \n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"$sha.*corrupt\" out\n+\ttest_i18ngrep \"$sha.*corrupt\" out\n '\n \n test_expect_success 'branch pointing to non-commit' '\n@@ -78,7 +78,7 @@ test_expect_success 'branch pointing to non-commit' '\n \ttest_when_finished \"git update-ref -d refs/heads/invalid\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"not a commit\" out\n+\ttest_i18ngrep \"not a commit\" out\n '\n \n test_expect_success 'HEAD link pointing at a funny object' '\n@@ -88,7 +88,7 @@ test_expect_success 'HEAD link pointing at a funny object' '\n \t# avoid corrupt/broken HEAD from interfering with repo discovery\n \ttest_must_fail env GIT_DIR=.git git fsck 2>out &&\n \tcat out &&\n-\tgrep \"detached HEAD points\" out\n+\ttest_i18ngrep \"detached HEAD points\" out\n '\n \n test_expect_success 'HEAD link pointing at a funny place' '\n@@ -98,7 +98,7 @@ test_expect_success 'HEAD link pointing at a funny place' '\n \t# avoid corrupt/broken HEAD from interfering with repo discovery\n \ttest_must_fail env GIT_DIR=.git git fsck 2>out &&\n \tcat out &&\n-\tgrep \"HEAD points to something strange\" out\n+\ttest_i18ngrep \"HEAD points to something strange\" out\n '\n \n test_expect_success 'email without @ is okay' '\n@@ -122,7 +122,7 @@ test_expect_success 'email with embedded > is not okay' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new\" out\n+\ttest_i18ngrep \"error in commit $new\" out\n '\n \n test_expect_success 'missing < email delimiter is reported nicely' '\n@@ -134,7 +134,7 @@ test_expect_success 'missing < email delimiter is reported nicely' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.* - bad name\" out\n+\ttest_i18ngrep \"error in commit $new.* - bad name\" out\n '\n \n test_expect_success 'missing email is reported nicely' '\n@@ -146,7 +146,7 @@ test_expect_success 'missing email is reported nicely' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.* - missing email\" out\n+\ttest_i18ngrep \"error in commit $new.* - missing email\" out\n '\n \n test_expect_success '> in name is reported' '\n@@ -158,7 +158,7 @@ test_expect_success '> in name is reported' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new\" out\n+\ttest_i18ngrep \"error in commit $new\" out\n '\n \n # date is 2^64 + 1\n@@ -172,7 +172,7 @@ test_expect_success 'integer overflow in timestamps is reported' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.*integer overflow\" out\n+\ttest_i18ngrep \"error in commit $new.*integer overflow\" out\n '\n \n test_expect_success 'commit with NUL in header' '\n@@ -184,7 +184,7 @@ test_expect_success 'commit with NUL in header' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.*unterminated header: NUL at offset\" out\n+\ttest_i18ngrep \"error in commit $new.*unterminated header: NUL at offset\" out\n '\n \n test_expect_success 'tree object with duplicate entries' '\n@@ -205,7 +205,7 @@ test_expect_success 'tree object with duplicate entries' '\n \t\tgit hash-object -w -t tree --stdin\n \t) &&\n \ttest_must_fail git fsck 2>out &&\n-\tgrep \"error in tree .*contains duplicate file entries\" out\n+\ttest_i18ngrep \"error in tree .*contains duplicate file entries\" out\n '\n \n test_expect_success 'unparseable tree object' '\n@@ -259,7 +259,7 @@ test_expect_success 'tag pointing to nonexistent' '\n \ttest_when_finished \"git update-ref -d refs/tags/invalid\" &&\n \ttest_must_fail git fsck --tags >out &&\n \tcat out &&\n-\tgrep \"broken link\" out\n+\ttest_i18ngrep \"broken link\" out\n '\n \n test_expect_success 'tag pointing to something else than its type' '\n@@ -301,7 +301,7 @@ test_expect_success 'tag with incorrect tag name & missing tagger' '\n \twarning in tag $tag: badTagName: invalid '\\''tag'\\'' name: wrong name format\n \twarning in tag $tag: missingTaggerEntry: invalid format - expected '\\''tagger'\\'' line\n \tEOF\n-\ttest_cmp expect out\n+\ttest_i18ncmp expect out\n '\n \n test_expect_success 'tag with bad tagger' '\n@@ -320,7 +320,7 @@ test_expect_success 'tag with bad tagger' '\n \techo $tag >.git/refs/tags/wrong &&\n \ttest_when_finished \"git update-ref -d refs/tags/wrong\" &&\n \ttest_must_fail git fsck --tags 2>out &&\n-\tgrep \"error in tag .*: invalid author/committer\" out\n+\ttest_i18ngrep \"error in tag .*: invalid author/committer\" out\n '\n \n test_expect_success 'tag with NUL in header' '\n@@ -340,7 +340,7 @@ test_expect_success 'tag with NUL in header' '\n \ttest_when_finished \"git update-ref -d refs/tags/wrong\" &&\n \ttest_must_fail git fsck --tags 2>out &&\n \tcat out &&\n-\tgrep \"error in tag $tag.*unterminated header: NUL at offset\" out\n+\ttest_i18ngrep \"error in tag $tag.*unterminated header: NUL at offset\" out\n '\n \n test_expect_success 'cleaned up' '\n@@ -396,7 +396,7 @@ test_expect_success 'fsck notices blob entry pointing to null sha1' '\n \t       git hash-object -w --stdin -t tree) &&\n \t  git fsck 2>out &&\n \t  cat out &&\n-\t  grep \"warning.*null sha1\" out\n+\t  test_i18ngrep \"warning.*null sha1\" out\n \t)\n '\n \n@@ -407,7 +407,7 @@ test_expect_success 'fsck notices submodule entry pointing to null sha1' '\n \t       git hash-object -w --stdin -t tree) &&\n \t  git fsck 2>out &&\n \t  cat out &&\n-\t  grep \"warning.*null sha1\" out\n+\t  test_i18ngrep \"warning.*null sha1\" out\n \t)\n '\n \n@@ -428,7 +428,7 @@ while read name path pretty; do\n \t\t\tbad_tree=$(git mktree <bad) &&\n \t\t\tgit fsck 2>out &&\n \t\t\tcat out &&\n-\t\t\tgrep \"warning.*tree $bad_tree\" out\n+\t\t\ttest_i18ngrep \"warning.*tree $bad_tree\" out\n \t\t)'\n \tdone <<-\\EOF\n \t100644 blob\n@@ -474,9 +474,9 @@ test_expect_success 'NUL in commit' '\n \t\tgit branch bad $(cat name) &&\n \n \t\ttest_must_fail git -c fsck.nulInCommit=error fsck 2>warn.1 &&\n-\t\tgrep nulInCommit warn.1 &&\n+\t\ttest_i18ngrep nulInCommit warn.1 &&\n \t\tgit fsck 2>warn.2 &&\n-\t\tgrep nulInCommit warn.2\n+\t\ttest_i18ngrep nulInCommit warn.2\n \t)\n '\n \n@@ -594,7 +594,7 @@ test_expect_success 'fsck --name-objects' '\n \t\tremove_object $(git rev-parse julius:caesar.t) &&\n \t\ttest_must_fail git fsck --name-objects >out &&\n \t\ttree=$(git rev-parse --verify julius:) &&\n-\t\tegrep \"$tree \\((refs/heads/master|HEAD)@\\{[0-9]*\\}:\" out\n+\t\ttest_i18ngrep -E \"$tree \\((refs/heads/master|HEAD)@\\{[0-9]*\\}:\" out\n \t)\n '\n \n@@ -605,7 +605,7 @@ test_expect_success 'alternate objects are correctly blamed' '\n \tmkdir alt.git/objects/12 &&\n \t>alt.git/objects/12/34567890123456789012345678901234567890 &&\n \ttest_must_fail git fsck >out 2>&1 &&\n-\tgrep alt.git out\n+\ttest_i18ngrep alt.git out\n '\n \n test_expect_success 'fsck errors in packed objects' '\n@@ -624,8 +624,8 @@ test_expect_success 'fsck errors in packed objects' '\n \tremove_object $one &&\n \tremove_object $two &&\n \ttest_must_fail git fsck 2>out &&\n-\tgrep \"error in commit $one.* - bad name\" out &&\n-\tgrep \"error in commit $two.* - bad name\" out &&\n+\ttest_i18ngrep \"error in commit $one.* - bad name\" out &&\n+\ttest_i18ngrep \"error in commit $two.* - bad name\" out &&\n \t! grep corrupt out\n '\n \n@@ -706,7 +706,7 @@ test_expect_success 'fsck notices dangling objects' '\n \t\tgit fsck >actual &&\n \t\t# the output order is non-deterministic, as it comes from a hash\n \t\tsort <actual >actual.sorted &&\n-\t\ttest_cmp expect actual.sorted\n+\t\ttest_i18ncmp expect actual.sorted\n \t)\n '\n \ndiff --git a/t/t6050-replace.sh b/t/t6050-replace.sh\nindex 86374a9c52..7700a8e793 100755\n--- a/t/t6050-replace.sh\n+++ b/t/t6050-replace.sh\n@@ -133,8 +133,8 @@ test_expect_success 'tag replaced commit' '\n \n test_expect_success '\"git fsck\" works' '\n      git fsck master >fsck_master.out &&\n-     grep \"dangling commit $R\" fsck_master.out &&\n-     grep \"dangling tag $(cat .git/refs/tags/mytag)\" fsck_master.out &&\n+     test_i18ngrep \"dangling commit $R\" fsck_master.out &&\n+     test_i18ngrep \"dangling tag $(cat .git/refs/tags/mytag)\" fsck_master.out &&\n      test -z \"$(git fsck)\"\n '\n \ndiff --git a/t/t7415-submodule-names.sh b/t/t7415-submodule-names.sh\nindex 293e2e1963..49a37efe9c 100755\n--- a/t/t7415-submodule-names.sh\n+++ b/t/t7415-submodule-names.sh\n@@ -154,7 +154,7 @@ test_expect_success 'fsck detects symlinked .gitmodules file' '\n \t\t# symlink detector; this grep string comes from the config\n \t\t# variable name and will not be translated.\n \t\ttest_must_fail git fsck 2>output &&\n-\t\tgrep gitmodulesSymlink output\n+\t\ttest_i18ngrep gitmodulesSymlink output\n \t)\n '\n \n@@ -172,7 +172,7 @@ test_expect_success 'fsck detects non-blob .gitmodules' '\n \t\tgit ls-tree HEAD | sed s/subdir/.gitmodules/ | git mktree &&\n \n \t\ttest_must_fail git fsck 2>output &&\n-\t\tgrep gitmodulesBlob output\n+\t\ttest_i18ngrep gitmodulesBlob output\n \t)\n '\n \n@@ -186,7 +186,7 @@ test_expect_success 'fsck detects corrupt .gitmodules' '\n \t\tgit commit -m \"broken gitmodules\" &&\n \n \t\tgit fsck 2>output &&\n-\t\tgrep gitmodulesParse output &&\n+\t\ttest_i18ngrep gitmodulesParse output &&\n \t\ttest_i18ngrep ! \"bad config\" output\n \t)\n '\n-- \n2.19.1.1005.gac84295441\n\n"},{"id":"362544","messageId":"xmqqftwfgdzs.fsf@gitster-ct.c.googlers.com","threadId":"49702","inReplyTo":"20181105192059.20303-2-pclouds@gmail.com","subject":"Re: [PATCH v2 01/16] git.c: mark more strings for translation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-11-06T02:02:15Z","receivedAt":"2018-11-06T02:02:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> One string is slightly updated to keep consistency with the rest:\n> die() should with lowercase.\n\ns/should/& begin/, I think, in which case I could locally touch up.\n\n\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  git.c | 30 +++++++++++++++---------------\n>  1 file changed, 15 insertions(+), 15 deletions(-)\n>\n> diff --git a/git.c b/git.c\n> index adac132956..5fd30da093 100644\n> --- a/git.c\n> +++ b/git.c\n> @@ -338,27 +338,27 @@ static int handle_alias(int *argcp, const char ***argv)\n>  \t\t\tif (ret >= 0)   /* normal exit */\n>  \t\t\t\texit(ret);\n>  \n> -\t\t\tdie_errno(\"while expanding alias '%s': '%s'\",\n> -\t\t\t    alias_command, alias_string + 1);\n> +\t\t\tdie_errno(_(\"while expanding alias '%s': '%s'\"),\n> +\t\t\t\t  alias_command, alias_string + 1);\n>  \t\t}\n>  \t\tcount = split_cmdline(alias_string, &new_argv);\n>  \t\tif (count < 0)\n> -\t\t\tdie(\"Bad alias.%s string: %s\", alias_command,\n> +\t\t\tdie(_(\"bad alias.%s string: %s\"), alias_command,\n>  \t\t\t    split_cmdline_strerror(count));\n>  \t\toption_count = handle_options(&new_argv, &count, &envchanged);\n>  \t\tif (envchanged)\n> -\t\t\tdie(\"alias '%s' changes environment variables.\\n\"\n> -\t\t\t\t \"You can use '!git' in the alias to do this\",\n> -\t\t\t\t alias_command);\n> +\t\t\tdie(_(\"alias '%s' changes environment variables.\\n\"\n> +\t\t\t      \"You can use '!git' in the alias to do this\"),\n> +\t\t\t    alias_command);\n>  \t\tmemmove(new_argv - option_count, new_argv,\n>  \t\t\t\tcount * sizeof(char *));\n>  \t\tnew_argv -= option_count;\n>  \n>  \t\tif (count < 1)\n> -\t\t\tdie(\"empty alias for %s\", alias_command);\n> +\t\t\tdie(_(\"empty alias for %s\"), alias_command);\n>  \n>  \t\tif (!strcmp(alias_command, new_argv[0]))\n> -\t\t\tdie(\"recursive alias: %s\", alias_command);\n> +\t\t\tdie(_(\"recursive alias: %s\"), alias_command);\n>  \n>  \t\ttrace_argv_printf(new_argv,\n>  \t\t\t\t  \"trace: alias expansion: %s =>\",\n> @@ -409,7 +409,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n>  \n>  \tif (!help && get_super_prefix()) {\n>  \t\tif (!(p->option & SUPPORT_SUPER_PREFIX))\n> -\t\t\tdie(\"%s doesn't support --super-prefix\", p->cmd);\n> +\t\t\tdie(_(\"%s doesn't support --super-prefix\"), p->cmd);\n>  \t}\n>  \n>  \tif (!help && p->option & NEED_WORK_TREE)\n> @@ -433,11 +433,11 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n>  \n>  \t/* Check for ENOSPC and EIO errors.. */\n>  \tif (fflush(stdout))\n> -\t\tdie_errno(\"write failure on standard output\");\n> +\t\tdie_errno(_(\"write failure on standard output\"));\n>  \tif (ferror(stdout))\n> -\t\tdie(\"unknown write failure on standard output\");\n> +\t\tdie(_(\"unknown write failure on standard output\"));\n>  \tif (fclose(stdout))\n> -\t\tdie_errno(\"close failed on standard output\");\n> +\t\tdie_errno(_(\"close failed on standard output\"));\n>  \treturn 0;\n>  }\n>  \n> @@ -648,7 +648,7 @@ static void execv_dashed_external(const char **argv)\n>  \tint status;\n>  \n>  \tif (get_super_prefix())\n> -\t\tdie(\"%s doesn't support --super-prefix\", argv[0]);\n> +\t\tdie(_(\"%s doesn't support --super-prefix\"), argv[0]);\n>  \n>  \tif (use_pager == -1 && !is_builtin(argv[0]))\n>  \t\tuse_pager = check_pager_config(argv[0]);\n> @@ -760,7 +760,7 @@ int cmd_main(int argc, const char **argv)\n>  \tif (skip_prefix(cmd, \"git-\", &cmd)) {\n>  \t\targv[0] = cmd;\n>  \t\thandle_builtin(argc, argv);\n> -\t\tdie(\"cannot handle %s as a builtin\", cmd);\n> +\t\tdie(_(\"cannot handle %s as a builtin\"), cmd);\n>  \t}\n>  \n>  \t/* Look for flags.. */\n> @@ -773,7 +773,7 @@ int cmd_main(int argc, const char **argv)\n>  \t} else {\n>  \t\t/* The user didn't specify a command; give them help */\n>  \t\tcommit_pager_choice();\n> -\t\tprintf(\"usage: %s\\n\\n\", git_usage_string);\n> +\t\tprintf(_(\"usage: %s\\n\\n\"), git_usage_string);\n>  \t\tlist_common_cmds_help();\n>  \t\tprintf(\"\\n%s\\n\", _(git_more_info_string));\n>  \t\texit(1);\n"},{"id":"362545","messageId":"xmqqbm73gdog.fsf@gitster-ct.c.googlers.com","threadId":"49702","inReplyTo":"20181105192059.20303-4-pclouds@gmail.com","subject":"Re: [PATCH v2 03/16] archive.c: mark more strings for translation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-11-06T02:09:03Z","receivedAt":"2018-11-06T02:09:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> Two messages also print extra information to be more useful\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  archive.c | 8 ++++----\n>  1 file changed, 4 insertions(+), 4 deletions(-)\n>\n> diff --git a/archive.c b/archive.c\n> index 9d16b7fadf..d8f6e1ce30 100644\n> --- a/archive.c\n> +++ b/archive.c\n> @@ -385,12 +385,12 @@ static void parse_treeish_arg(const char **argv,\n>  \t\tint refnamelen = colon - name;\n>  \n>  \t\tif (!dwim_ref(name, refnamelen, &oid, &ref))\n> -\t\t\tdie(\"no such ref: %.*s\", refnamelen, name);\n> +\t\t\tdie(_(\"no such ref: %.*s\"), refnamelen, name);\n>  \t\tfree(ref);\n>  \t}\n>  \n>  \tif (get_oid(name, &oid))\n> -\t\tdie(\"Not a valid object name\");\n> +\t\tdie(_(\"not a valid object name: %s\"), name);\n\nMuch better than the previous one that gave the name upfront.\n\n>  \n>  \tcommit = lookup_commit_reference_gently(ar_args->repo, &oid, 1);\n>  \tif (commit) {\n> @@ -403,7 +403,7 @@ static void parse_treeish_arg(const char **argv,\n>  \n>  \ttree = parse_tree_indirect(&oid);\n>  \tif (tree == NULL)\n> -\t\tdie(\"not a tree object\");\n> +\t\tdie(_(\"not a tree object: %s\"), oid_to_hex(&oid));\n\nLikewise; as oid_to_hex() would be quite long compared to the rest\nof the message, this is a vast improvement from the previous round.\n\n>  \tif (prefix) {\n>  \t\tstruct object_id tree_oid;\n> @@ -413,7 +413,7 @@ static void parse_treeish_arg(const char **argv,\n>  \t\terr = get_tree_entry(&tree->object.oid, prefix, &tree_oid,\n>  \t\t\t\t     &mode);\n>  \t\tif (err || !S_ISDIR(mode))\n> -\t\t\tdie(\"current working directory is untracked\");\n> +\t\t\tdie(_(\"current working directory is untracked\"));\n>  \n>  \t\ttree = parse_tree_indirect(&tree_oid);\n>  \t}\n"},{"id":"362546","messageId":"xmqq7ehrgdm3.fsf@gitster-ct.c.googlers.com","threadId":"49702","inReplyTo":"20181105192059.20303-6-pclouds@gmail.com","subject":"Re: [PATCH v2 05/16] read-cache.c: turn die(\"internal error\") to BUG()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-11-06T02:10:28Z","receivedAt":"2018-11-06T02:10:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  read-cache.c | 6 +++---\n>  1 file changed, 3 insertions(+), 3 deletions(-)\n\nMakes sense; thanks.\n\n>\n> diff --git a/read-cache.c b/read-cache.c\n> index d57958233e..0c37f4885e 100644\n> --- a/read-cache.c\n> +++ b/read-cache.c\n> @@ -316,7 +316,7 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)\n>  \t\t\tchanged |= DATA_CHANGED;\n>  \t\treturn changed;\n>  \tdefault:\n> -\t\tdie(\"internal error: ce_mode is %o\", ce->ce_mode);\n> +\t\tBUG(\"unsupported ce_mode: %o\", ce->ce_mode);\n>  \t}\n>  \n>  \tchanged |= match_stat_data(&ce->ce_stat_data, st);\n> @@ -2356,14 +2356,14 @@ void validate_cache_entries(const struct index_state *istate)\n>  \n>  \tfor (i = 0; i < istate->cache_nr; i++) {\n>  \t\tif (!istate) {\n> -\t\t\tdie(\"internal error: cache entry is not allocated from expected memory pool\");\n> +\t\t\tBUG(\"cache entry is not allocated from expected memory pool\");\n>  \t\t} else if (!istate->ce_mem_pool ||\n>  \t\t\t!mem_pool_contains(istate->ce_mem_pool, istate->cache[i])) {\n>  \t\t\tif (!istate->split_index ||\n>  \t\t\t\t!istate->split_index->base ||\n>  \t\t\t\t!istate->split_index->base->ce_mem_pool ||\n>  \t\t\t\t!mem_pool_contains(istate->split_index->base->ce_mem_pool, istate->cache[i])) {\n> -\t\t\t\tdie(\"internal error: cache entry is not allocated from expected memory pool\");\n> +\t\t\t\tBUG(\"cache entry is not allocated from expected memory pool\");\n>  \t\t\t}\n>  \t\t}\n>  \t}\n"},{"id":"362547","messageId":"xmqq36sfgdjj.fsf@gitster-ct.c.googlers.com","threadId":"49702","inReplyTo":"20181105192059.20303-8-pclouds@gmail.com","subject":"Re: [PATCH v2 07/16] read-cache.c: add missing colon separators","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-11-06T02:12:00Z","receivedAt":"2018-11-06T02:12:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> typechange_fmt and added_fmt should have a colon before \"needs\n> update\". Align the statements to make it easier to read and see. Also\n> drop the unnecessary ().\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  read-cache.c | 10 +++++-----\n>  1 file changed, 5 insertions(+), 5 deletions(-)\n\nSensible.  Thanks.\n\n> diff --git a/read-cache.c b/read-cache.c\n> index 858befe738..8d99ae376c 100644\n> --- a/read-cache.c\n> +++ b/read-cache.c\n> @@ -1492,11 +1492,11 @@ int refresh_index(struct index_state *istate, unsigned int flags,\n>  \t\t\t\t\t\t  istate->cache_nr);\n>  \n>  \ttrace_performance_enter();\n> -\tmodified_fmt = (in_porcelain ? \"M\\t%s\\n\" : \"%s: needs update\\n\");\n> -\tdeleted_fmt = (in_porcelain ? \"D\\t%s\\n\" : \"%s: needs update\\n\");\n> -\ttypechange_fmt = (in_porcelain ? \"T\\t%s\\n\" : \"%s needs update\\n\");\n> -\tadded_fmt = (in_porcelain ? \"A\\t%s\\n\" : \"%s needs update\\n\");\n> -\tunmerged_fmt = (in_porcelain ? \"U\\t%s\\n\" : \"%s: needs merge\\n\");\n> +\tmodified_fmt   = in_porcelain ? \"M\\t%s\\n\" : \"%s: needs update\\n\";\n> +\tdeleted_fmt    = in_porcelain ? \"D\\t%s\\n\" : \"%s: needs update\\n\";\n> +\ttypechange_fmt = in_porcelain ? \"T\\t%s\\n\" : \"%s: needs update\\n\";\n> +\tadded_fmt      = in_porcelain ? \"A\\t%s\\n\" : \"%s: needs update\\n\";\n> +\tunmerged_fmt   = in_porcelain ? \"U\\t%s\\n\" : \"%s: needs merge\\n\";\n>  \tfor (i = 0; i < istate->cache_nr; i++) {\n>  \t\tstruct cache_entry *ce, *new_entry;\n>  \t\tint cache_errno = 0;\n"},{"id":"362548","messageId":"xmqqy3a7eywd.fsf@gitster-ct.c.googlers.com","threadId":"49702","inReplyTo":"20181105192059.20303-9-pclouds@gmail.com","subject":"Re: [PATCH v2 08/16] reflog: mark strings for translation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-11-06T02:13:38Z","receivedAt":"2018-11-06T02:13:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n>  \tif (argc - i < 1)\n> -\t\treturn error(\"Nothing to delete?\");\n> +\t\treturn error(_(\"no reflog specified to delete\"));\n\nBetter.  Thanks.\n\n"},{"id":"362549","messageId":"xmqqtvkveyiv.fsf@gitster-ct.c.googlers.com","threadId":"49702","inReplyTo":"20181105192059.20303-10-pclouds@gmail.com","subject":"Re: [PATCH v2 09/16] remote.c: turn some error() or die() to BUG()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-11-06T02:21:44Z","receivedAt":"2018-11-06T02:21:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> The first error, \"internal error\", is clearly a BUG(). The second two\n> are meant to catch calls with invalid parameters and should never\n> happen outside the test suite.\n\nSounds as if it would happen inside test suites.\n\nI guess by \"inside the test suite\" you mean a test that links broken\ncallers to this code as if it is a piece of library function, but\n\"should never happen, even with invalid or malformed end-user\nrequest\" would convey the point better, as the normal part of\ntesting that is done by driing \"git we just built from the command\nline should not hit these.\n\nThe changes all look sensible.  Thanks.\n\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  remote.c | 6 +++---\n>  1 file changed, 3 insertions(+), 3 deletions(-)\n>\n> diff --git a/remote.c b/remote.c\n> index 81f4f01b00..257630ff21 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -620,7 +620,7 @@ static void handle_duplicate(struct ref *ref1, struct ref *ref2)\n>  \t\t\t * FETCH_HEAD_IGNORE entries always appear at\n>  \t\t\t * the end of the list.\n>  \t\t\t */\n> -\t\t\tdie(_(\"Internal error\"));\n> +\t\t\tBUG(\"Internal error\");\n>  \t\t}\n>  \t}\n>  \tfree(ref2->peer_ref);\n> @@ -707,7 +707,7 @@ static void query_refspecs_multiple(struct refspec *rs,\n>  \tint find_src = !query->src;\n>  \n>  \tif (find_src && !query->dst)\n> -\t\terror(\"query_refspecs_multiple: need either src or dst\");\n> +\t\tBUG(\"query_refspecs_multiple: need either src or dst\");\n>  \n>  \tfor (i = 0; i < rs->nr; i++) {\n>  \t\tstruct refspec_item *refspec = &rs->items[i];\n> @@ -735,7 +735,7 @@ int query_refspecs(struct refspec *rs, struct refspec_item *query)\n>  \tchar **result = find_src ? &query->src : &query->dst;\n>  \n>  \tif (find_src && !query->dst)\n> -\t\treturn error(\"query_refspecs: need either src or dst\");\n> +\t\tBUG(\"query_refspecs: need either src or dst\");\n>  \n>  \tfor (i = 0; i < rs->nr; i++) {\n>  \t\tstruct refspec_item *refspec = &rs->items[i];\n"},{"id":"362551","messageId":"xmqqpnvjexzf.fsf@gitster-ct.c.googlers.com","threadId":"49702","inReplyTo":"20181105192059.20303-13-pclouds@gmail.com","subject":"Re: [PATCH v2 12/16] parse-options: replace opterror() with optname()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-11-06T02:33:24Z","receivedAt":"2018-11-06T02:33:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> There are a few issues with opterror()\n>\n> - it tries to assemble an English sentence from pieces. This is not\n>   great for translators because we give them pieces instead of a full\n>   sentence.\n>\n> - It's a wrapper around error() and needs some hack to let the\n>   compiler know it always returns -1.\n>\n> - Since it takes a string instead of printf format, one call site has\n>   to assemble the string manually before passing to it.\n>\n> Kill it and produce the option name with optname(). The user will use\n> error() directly. This solves the second and third problems.\n\nThe proposed log message is not very friendly to reviewers, as there\nis no hint what optname() does nor where it came from; it turns out\nthat this patch introduces it.\n\n    Introduce optname() that does the early half of original\n    opterror() to come up with the name of the option reported back\n    to the user, and use it to kill opterror().  The callers of\n    opterror() now directly call error() using the string returned\n    by opterror() instead.\n\nor something like that perhaps.\n\nTheoretically not very friendly to topics in flight, but I do not\nexpect there would be any right now that wants to add new callers of\nopterror().\n\nI do agree with the reasoning behind this change.  Thanks for\nworking on it.\n\n>\n> It kind helps the first problem as well because \"%s does foo\" does\n> give a translator a full sentence in a sense and let them reorder if\n> needed. But it has limitations, if the subject part has to change\n> based on the rest of the sentence, that language is screwed. This is\n> also why I try to avoid calling optname() when 'flags' is known in\n> advance.\n>\n> Mark of these strings for translation as well while at there.\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  builtin/merge.c     |  2 +-\n>  builtin/revert.c    |  3 ++-\n>  parse-options-cb.c  |  7 ++++---\n>  parse-options.c     | 46 +++++++++++++++++++++++++--------------------\n>  parse-options.h     |  5 +----\n>  ref-filter.c        |  8 +++++---\n>  t/t4211-line-log.sh |  2 +-\n>  7 files changed, 40 insertions(+), 33 deletions(-)\n>\n> diff --git a/builtin/merge.c b/builtin/merge.c\n> index 92ba7e1c6d..82248d43c3 100644\n> --- a/builtin/merge.c\n> +++ b/builtin/merge.c\n> @@ -128,7 +128,7 @@ static int option_read_message(struct parse_opt_ctx_t *ctx,\n>  \t\tctx->argc--;\n>  \t\targ = *++ctx->argv;\n>  \t} else\n> -\t\treturn opterror(opt, \"requires a value\", 0);\n> +\t\treturn error(_(\"option `%s' requires a value\"), opt->long_name);\n>  \n>  \tif (buf->len)\n>  \t\tstrbuf_addch(buf, '\\n');\n> diff --git a/builtin/revert.c b/builtin/revert.c\n> index c93393c89b..11190d2ab4 100644\n> --- a/builtin/revert.c\n> +++ b/builtin/revert.c\n> @@ -69,7 +69,8 @@ static int option_parse_m(const struct option *opt,\n>  \n>  \treplay->mainline = strtol(arg, &end, 10);\n>  \tif (*end || replay->mainline <= 0)\n> -\t\treturn opterror(opt, \"expects a number greater than zero\", 0);\n> +\t\treturn error(_(\"option `%s' expects a number greater than zero\"),\n> +\t\t\t     opt->long_name);\n>  \n>  \treturn 0;\n>  }\n> diff --git a/parse-options-cb.c b/parse-options-cb.c\n> index e8236534ac..813eb6301b 100644\n> --- a/parse-options-cb.c\n> +++ b/parse-options-cb.c\n> @@ -18,7 +18,8 @@ int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)\n>  \t} else {\n>  \t\tv = strtol(arg, (char **)&arg, 10);\n>  \t\tif (*arg)\n> -\t\t\treturn opterror(opt, \"expects a numerical value\", 0);\n> +\t\t\treturn error(_(\"option `%s' expects a numerical value\"),\n> +\t\t\t\t     opt->long_name);\n>  \t\tif (v && v < MINIMUM_ABBREV)\n>  \t\t\tv = MINIMUM_ABBREV;\n>  \t\telse if (v > 40)\n> @@ -54,8 +55,8 @@ int parse_opt_color_flag_cb(const struct option *opt, const char *arg,\n>  \t\targ = unset ? \"never\" : (const char *)opt->defval;\n>  \tvalue = git_config_colorbool(NULL, arg);\n>  \tif (value < 0)\n> -\t\treturn opterror(opt,\n> -\t\t\t\"expects \\\"always\\\", \\\"auto\\\", or \\\"never\\\"\", 0);\n> +\t\treturn error(_(\"option `%s' expects \\\"always\\\", \\\"auto\\\", or \\\"never\\\"\"),\n> +\t\t\t     opt->long_name);\n>  \t*(int *)opt->value = value;\n>  \treturn 0;\n>  }\n> diff --git a/parse-options.c b/parse-options.c\n> index 3b874a83a0..0bf817193d 100644\n> --- a/parse-options.c\n> +++ b/parse-options.c\n> @@ -32,7 +32,7 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,\n>  \t\tp->argc--;\n>  \t\t*arg = *++p->argv;\n>  \t} else\n> -\t\treturn opterror(opt, \"requires a value\", flags);\n> +\t\treturn error(_(\"%s requires a value\"), optname(opt, flags));\n>  \treturn 0;\n>  }\n>  \n> @@ -49,7 +49,6 @@ static int opt_command_mode_error(const struct option *opt,\n>  \t\t\t\t  int flags)\n>  {\n>  \tconst struct option *that;\n> -\tstruct strbuf message = STRBUF_INIT;\n>  \tstruct strbuf that_name = STRBUF_INIT;\n>  \n>  \t/*\n> @@ -67,13 +66,13 @@ static int opt_command_mode_error(const struct option *opt,\n>  \t\t\tstrbuf_addf(&that_name, \"--%s\", that->long_name);\n>  \t\telse\n>  \t\t\tstrbuf_addf(&that_name, \"-%c\", that->short_name);\n> -\t\tstrbuf_addf(&message, \": incompatible with %s\", that_name.buf);\n> +\t\terror(_(\"%s is incompatible with %s\"),\n> +\t\t      optname(opt, flags), that_name.buf);\n>  \t\tstrbuf_release(&that_name);\n> -\t\topterror(opt, message.buf, flags);\n> -\t\tstrbuf_release(&message);\n>  \t\treturn -1;\n>  \t}\n> -\treturn opterror(opt, \": incompatible with something else\", flags);\n> +\treturn error(_(\"%s : incompatible with something else\"),\n> +\t\t     optname(opt, flags));\n>  }\n>  \n>  static int get_value(struct parse_opt_ctx_t *p,\n> @@ -86,11 +85,11 @@ static int get_value(struct parse_opt_ctx_t *p,\n>  \tint err;\n>  \n>  \tif (unset && p->opt)\n> -\t\treturn opterror(opt, \"takes no value\", flags);\n> +\t\treturn error(_(\"%s takes no value\"), optname(opt, flags));\n>  \tif (unset && (opt->flags & PARSE_OPT_NONEG))\n> -\t\treturn opterror(opt, \"isn't available\", flags);\n> +\t\treturn error(_(\"%s isn't available\"), optname(opt, flags));\n>  \tif (!(flags & OPT_SHORT) && p->opt && (opt->flags & PARSE_OPT_NOARG))\n> -\t\treturn opterror(opt, \"takes no value\", flags);\n> +\t\treturn error(_(\"%s takes no value\"), optname(opt, flags));\n>  \n>  \tswitch (opt->type) {\n>  \tcase OPTION_LOWLEVEL_CALLBACK:\n> @@ -176,7 +175,8 @@ static int get_value(struct parse_opt_ctx_t *p,\n>  \t\t\treturn -1;\n>  \t\t*(int *)opt->value = strtol(arg, (char **)&s, 10);\n>  \t\tif (*s)\n> -\t\t\treturn opterror(opt, \"expects a numerical value\", flags);\n> +\t\t\treturn error(_(\"%s expects a numerical value\"),\n> +\t\t\t\t     optname(opt, flags));\n>  \t\treturn 0;\n>  \n>  \tcase OPTION_MAGNITUDE:\n> @@ -191,9 +191,9 @@ static int get_value(struct parse_opt_ctx_t *p,\n>  \t\tif (get_arg(p, opt, flags, &arg))\n>  \t\t\treturn -1;\n>  \t\tif (!git_parse_ulong(arg, opt->value))\n> -\t\t\treturn opterror(opt,\n> -\t\t\t\t\"expects a non-negative integer value with an optional k/m/g suffix\",\n> -\t\t\t\tflags);\n> +\t\t\treturn error(_(\"%s expects a non-negative integer value\"\n> +\t\t\t\t       \" with an optional k/m/g suffix\"),\n> +\t\t\t\t     optname(opt, flags));\n>  \t\treturn 0;\n>  \n>  \tdefault:\n> @@ -257,7 +257,8 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,\n>  \t\t\tif (!rest)\n>  \t\t\t\tcontinue;\n>  \t\t\tif (*rest == '=')\n> -\t\t\t\treturn opterror(options, \"takes no value\", flags);\n> +\t\t\t\treturn error(_(\"%s takes no value\"),\n> +\t\t\t\t\t     optname(options, flags));\n>  \t\t\tif (*rest)\n>  \t\t\t\tcontinue;\n>  \t\t\tp->out[p->cpidx++] = arg - 2;\n> @@ -773,12 +774,17 @@ void NORETURN usage_msg_opt(const char *msg,\n>  \tusage_with_options(usagestr, options);\n>  }\n>  \n> -#undef opterror\n> -int opterror(const struct option *opt, const char *reason, int flags)\n> +const char *optname(const struct option *opt, int flags)\n>  {\n> +\tstatic struct strbuf sb = STRBUF_INIT;\n> +\n> +\tstrbuf_reset(&sb);\n>  \tif (flags & OPT_SHORT)\n> -\t\treturn error(\"switch `%c' %s\", opt->short_name, reason);\n> -\tif (flags & OPT_UNSET)\n> -\t\treturn error(\"option `no-%s' %s\", opt->long_name, reason);\n> -\treturn error(\"option `%s' %s\", opt->long_name, reason);\n> +\t\tstrbuf_addf(&sb, \"switch `%c'\", opt->short_name);\n> +\telse if (flags & OPT_UNSET)\n> +\t\tstrbuf_addf(&sb, \"option `no-%s'\", opt->long_name);\n> +\telse\n> +\t\tstrbuf_addf(&sb, \"option `%s'\", opt->long_name);\n> +\n> +\treturn sb.buf;\n>  }\n> diff --git a/parse-options.h b/parse-options.h\n> index dd14911a29..2e146aa6fa 100644\n> --- a/parse-options.h\n> +++ b/parse-options.h\n> @@ -189,10 +189,7 @@ extern NORETURN void usage_msg_opt(const char *msg,\n>  \t\t\t\t   const struct option *options);\n>  \n>  extern int optbug(const struct option *opt, const char *reason);\n> -extern int opterror(const struct option *opt, const char *reason, int flags);\n> -#if defined(__GNUC__)\n> -#define opterror(o,r,f) (opterror((o),(r),(f)), const_error())\n> -#endif\n> +const char *optname(const struct option *opt, int flags);\n>  \n>  /*----- incremental advanced APIs -----*/\n>  \n> diff --git a/ref-filter.c b/ref-filter.c\n> index 2a05619211..0681359100 100644\n> --- a/ref-filter.c\n> +++ b/ref-filter.c\n> @@ -2302,9 +2302,11 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n>  \n>  \tif (rf->merge) {\n>  \t\tif (no_merged) {\n> -\t\t\treturn opterror(opt, \"is incompatible with --merged\", 0);\n> +\t\t\treturn error(_(\"option `%s' is incompatible with --merged\"),\n> +\t\t\t\t     opt->long_name);\n>  \t\t} else {\n> -\t\t\treturn opterror(opt, \"is incompatible with --no-merged\", 0);\n> +\t\t\treturn error(_(\"option `%s' is incompatible with --no-merged\"),\n> +\t\t\t\t     opt->long_name);\n>  \t\t}\n>  \t}\n>  \n> @@ -2318,7 +2320,7 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n>  \trf->merge_commit = lookup_commit_reference_gently(the_repository,\n>  \t\t\t\t\t\t\t  &oid, 0);\n>  \tif (!rf->merge_commit)\n> -\t\treturn opterror(opt, \"must point to a commit\", 0);\n> +\t\treturn error(_(\"option `%s' must point to a commit\"), opt->long_name);\n>  \n>  \treturn 0;\n>  }\n> diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh\n> index ef1322148e..bd5fe4d148 100755\n> --- a/t/t4211-line-log.sh\n> +++ b/t/t4211-line-log.sh\n> @@ -25,7 +25,7 @@ canned_test_failure () {\n>  test_bad_opts () {\n>  \ttest_expect_success \"invalid args: $1\" \"\n>  \t\ttest_must_fail git log $1 2>errors &&\n> -\t\tgrep '$2' errors\n> +\t\ttest_i18ngrep '$2' errors\n>  \t\"\n>  }\n"},{"id":"362552","messageId":"xmqqh8guga1x.fsf@gitster-ct.c.googlers.com","threadId":"49702","inReplyTo":"20181105192059.20303-14-pclouds@gmail.com","subject":"Re: [PATCH v2 13/16] parse-options.c: turn some die() to BUG()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-11-06T03:27:22Z","receivedAt":"2018-11-06T03:27:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> diff --git a/parse-options.c b/parse-options.c\n> index 0bf817193d..3f5f985c1e 100644\n> --- a/parse-options.c\n> +++ b/parse-options.c\n> @@ -197,7 +197,7 @@ static int get_value(struct parse_opt_ctx_t *p,\n>  \t\treturn 0;\n>  \n>  \tdefault:\n> -\t\tdie(\"should not happen, someone must be hit on the forehead\");\n> +\t\tBUG(\"opt->type %d should not happen\", opt->type);\n>  \t}\n>  }\n\nOK, this should not happen.\n\n> @@ -424,7 +424,7 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,\n>  \tctx->flags = flags;\n>  \tif ((flags & PARSE_OPT_KEEP_UNKNOWN) &&\n>  \t    (flags & PARSE_OPT_STOP_AT_NON_OPTION))\n> -\t\tdie(\"STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together\");\n> +\t\tBUG(\"STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together\");\n\nThe correctness of this conversion was not immediately obvious, as\n\"git rev-parse --parse-options\" could allow end-users to specify\nflags, and when these two flags came together from that codepath, it\nis an end-user error that should be diagnosed with die(), not BUG().\n\nIt turns out that stop-at-non-option can be passed, but keep-unknown\nis not (yet) available to the codepath, so this conversion to BUG()\nis correct---an end user futzing with Git correctly compiled from a\nbug-free source should not be able to trigger this.\n"},{"id":"362553","messageId":"xmqqbm72g9ee.fsf@gitster-ct.c.googlers.com","threadId":"49702","inReplyTo":"20181105192059.20303-16-pclouds@gmail.com","subject":"Re: [PATCH v2 15/16] fsck: reduce word legos to help i18n","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-11-06T03:41:29Z","receivedAt":"2018-11-06T03:41:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n>  static const char *describe_object(struct object *obj)\n>  {\n> -\tstatic struct strbuf buf = STRBUF_INIT;\n> -\tchar *name = name_objects ?\n> -\t\tlookup_decoration(fsck_walk_options.object_names, obj) : NULL;\n> +\tstatic struct strbuf bufs[4] = {\n> +\t\tSTRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT\n> +\t};\n\nIf you need to repeat _INIT anyway, perhaps you want to actively\nomit the 4 from above, no?  If you typed 6 by mistake instead, you'd\nbe in trouble when using the last two elements.\n\n>  static int objerror(struct object *obj, const char *err)\n>  {\n>  \terrors_found |= ERROR_OBJECT;\n> -\tobjreport(obj, \"error\", err);\n> +\tfprintf_ln(stderr, \"error in %s %s: %s\",\n> +\t\t   printable_type(obj), describe_object(obj), err);\n>  \treturn -1;\n>  }\n\nMakes sense.\n\n>  static int fsck_error_func(struct fsck_options *o,\n>  \tstruct object *obj, int type, const char *message)\n>  {\n> -\tobjreport(obj, (type == FSCK_WARN) ? \"warning\" : \"error\", message);\n> -\treturn (type == FSCK_WARN) ? 0 : 1;\n> +\tif (type == FSCK_WARN) {\n> +\t\tfprintf_ln(stderr, \"warning in %s %s: %s\",\n> +\t\t\t   printable_type(obj), describe_object(obj), message);\n> +\t\treturn 0;\n> +\t}\n> +\n> +\tfprintf_ln(stderr, \"error in %s %s: %s\",\n> +\t\t   printable_type(obj), describe_object(obj), message);\n> +\treturn 1;\n\nMake it look more symmetrical like the original, perhaps by\n\n\tif (type == FSCK_WARN) {\n\t\t...\n\t\treturn 0;\n\t} else { /* FSCK_ERROR */\n\t\t...\n\t\treturn 1;\n\t}\n\nActually, wouldn't it be clearer to see what is going on, if we did\nit like this instead?\n\n\tconst char *fmt = (type == FSCK_WARN) \n\t\t? N_(\"warning in %s %s: %s\")\n\t\t: N_(\"error in %s %s: %s\");\n\tfprintf_ln(stderr, _(fmt),\n\t\t   printable_type(obj), describe_object(obj), message);\n\treturn (type == FSCK_WARN) ? 0 : 1;\n\nIt would show that in either case we show these three things in the\nmessage.  I dunno.\n"},{"id":"362574","messageId":"d29c4fcc-0591-fc45-5a5d-65d2874d98a7@ramsayjones.plus.com","threadId":"49702","inReplyTo":"xmqqpnvjexzf.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v2 12/16] parse-options: replace opterror() with optname()","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2018-11-06T14:02:42Z","receivedAt":"2018-11-06T14:02:47Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 06/11/2018 02:33, Junio C Hamano wrote:\n> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n> \n>> There are a few issues with opterror()\n>>\n>> - it tries to assemble an English sentence from pieces. This is not\n>>   great for translators because we give them pieces instead of a full\n>>   sentence.\n>>\n>> - It's a wrapper around error() and needs some hack to let the\n>>   compiler know it always returns -1.\n>>\n>> - Since it takes a string instead of printf format, one call site has\n>>   to assemble the string manually before passing to it.\n>>\n>> Kill it and produce the option name with optname(). The user will use\n>> error() directly. This solves the second and third problems.\n> \n> The proposed log message is not very friendly to reviewers, as there\n> is no hint what optname() does nor where it came from; it turns out\n> that this patch introduces it.\n> \n>     Introduce optname() that does the early half of original\n>     opterror() to come up with the name of the option reported back\n>     to the user, and use it to kill opterror().  The callers of\n>     opterror() now directly call error() using the string returned\n>     by opterror() instead.\n> \n> or something like that perhaps.\n> \n> Theoretically not very friendly to topics in flight, but I do not\n> expect there would be any right now that wants to add new callers of\n> opterror().\n> \n> I do agree with the reasoning behind this change.  Thanks for\n> working on it.\n> \n\nAlso, this patch does not replace opterror() calls outside of\nthe 'parse-options.c' file with optname(). This tickles my\nstatic-check.pl script, since optname() is an external function\nwhich is only called from 'parse-options.c'.\n\nSo, at present, optname() could be marked as a local 'static'\nsymbol. However, I could also imagine it being used by new callers\noutside of 'parse-options.c' in the future. (maybe) Your call. ;-)\n\nATB,\nRamsay Jones\n\n"},{"id":"362599","messageId":"20181106190852.GA7499@sigill.intra.peff.net","threadId":"49702","inReplyTo":"d29c4fcc-0591-fc45-5a5d-65d2874d98a7@ramsayjones.plus.com","subject":"Re: [PATCH v2 12/16] parse-options: replace opterror() with optname()","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2018-11-06T19:08:52Z","receivedAt":"2018-11-06T19:08:56Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Nov 06, 2018 at 02:02:42PM +0000, Ramsay Jones wrote:\n\n> Also, this patch does not replace opterror() calls outside of\n> the 'parse-options.c' file with optname(). This tickles my\n> static-check.pl script, since optname() is an external function\n> which is only called from 'parse-options.c'.\n> \n> So, at present, optname() could be marked as a local 'static'\n> symbol. However, I could also imagine it being used by new callers\n> outside of 'parse-options.c' in the future. (maybe) Your call. ;-)\n\nOne potential caller is the BUG() cases I added in:\n\n  https://public-inbox.org/git/20181105064542.GM25864@sigill.intra.peff.net/\n\nI actually thought about factoring out an optname() there, but saw that\nit involved memory ownership issues and punted (since those messages are\njust BUG()s anyway, and unlikely to be triggered). But if we have it, we\ncould use it.\n\n-Peff\n"},{"id":"362843","messageId":"20181110051615.8641-17-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 16/16] fsck: mark strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:15Z","receivedAt":"2018-11-10T05:38:21Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Two die() are updated to start with lowercase to be consistent with\nthe rest.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/fsck.c             | 106 ++++++++++++++++++++-----------------\n t/t1410-reflog.sh          |   6 +--\n t/t1450-fsck.sh            |  50 ++++++++---------\n t/t6050-replace.sh         |   4 +-\n t/t7415-submodule-names.sh |   6 +--\n 5 files changed, 90 insertions(+), 82 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex 1feb6142f4..dcf72859a6 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -85,7 +85,7 @@ static const char *printable_type(struct object *obj)\n \n \tret = type_name(obj->type);\n \tif (!ret)\n-\t\tret = \"unknown\";\n+\t\tret = _(\"unknown\");\n \n \treturn ret;\n }\n@@ -116,7 +116,8 @@ static int fsck_config(const char *var, const char *value, void *cb)\n static int objerror(struct object *obj, const char *err)\n {\n \terrors_found |= ERROR_OBJECT;\n-\tfprintf_ln(stderr, \"error in %s %s: %s\",\n+\t/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */\n+\tfprintf_ln(stderr, _(\"error in %s %s: %s\"),\n \t\t   printable_type(obj), describe_object(obj), err);\n \treturn -1;\n }\n@@ -126,11 +127,13 @@ static int fsck_error_func(struct fsck_options *o,\n {\n \tswitch (type) {\n \tcase FSCK_WARN:\n-\t\tfprintf_ln(stderr, \"warning in %s %s: %s\",\n+\t\t/* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */\n+\t\tfprintf_ln(stderr, _(\"warning in %s %s: %s\"),\n \t\t\t   printable_type(obj), describe_object(obj), message);\n \t\treturn 0;\n \tcase FSCK_ERROR:\n-\t\tfprintf_ln(stderr, \"error in %s %s: %s\",\n+\t\t/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */\n+\t\tfprintf_ln(stderr, _(\"error in %s %s: %s\"),\n \t\t\t   printable_type(obj), describe_object(obj), message);\n \t\treturn 1;\n \tdefault:\n@@ -151,17 +154,18 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt\n \t */\n \tif (!obj) {\n \t\t/* ... these references to parent->fld are safe here */\n-\t\tprintf(\"broken link from %7s %s\\n\",\n-\t\t\t   printable_type(parent), describe_object(parent));\n-\t\tprintf(\"broken link from %7s %s\\n\",\n-\t\t\t   (type == OBJ_ANY ? \"unknown\" : type_name(type)), \"unknown\");\n+\t\tprintf_ln(_(\"broken link from %7s %s\"),\n+\t\t\t  printable_type(parent), describe_object(parent));\n+\t\tprintf_ln(_(\"broken link from %7s %s\"),\n+\t\t\t  (type == OBJ_ANY ? _(\"unknown\") : type_name(type)),\n+\t\t\t  _(\"unknown\"));\n \t\terrors_found |= ERROR_REACHABLE;\n \t\treturn 1;\n \t}\n \n \tif (type != OBJ_ANY && obj->type != type)\n \t\t/* ... and the reference to parent is safe here */\n-\t\tobjerror(parent, \"wrong object type in link\");\n+\t\tobjerror(parent, _(\"wrong object type in link\"));\n \n \tif (obj->flags & REACHABLE)\n \t\treturn 0;\n@@ -177,8 +181,8 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt\n \n \tif (!(obj->flags & HAS_OBJ)) {\n \t\tif (parent && !has_object_file(&obj->oid)) {\n-\t\t\tprintf_ln(\"broken link from %7s %s\\n\"\n-\t\t\t\t  \"              to %7s %s\",\n+\t\t\tprintf_ln(_(\"broken link from %7s %s\\n\"\n+\t\t\t\t    \"              to %7s %s\"),\n \t\t\t\t  printable_type(parent),\n \t\t\t\t  describe_object(parent),\n \t\t\t\t  printable_type(obj),\n@@ -246,8 +250,8 @@ static void check_reachable_object(struct object *obj)\n \t\t\treturn;\n \t\tif (has_object_pack(&obj->oid))\n \t\t\treturn; /* it is in pack - forget about it */\n-\t\tprintf(\"missing %s %s\\n\", printable_type(obj),\n-\t\t\tdescribe_object(obj));\n+\t\tprintf_ln(_(\"missing %s %s\"), printable_type(obj),\n+\t\t\t  describe_object(obj));\n \t\terrors_found |= ERROR_REACHABLE;\n \t\treturn;\n \t}\n@@ -272,8 +276,8 @@ static void check_unreachable_object(struct object *obj)\n \t * since this is something that is prunable.\n \t */\n \tif (show_unreachable) {\n-\t\tprintf(\"unreachable %s %s\\n\", printable_type(obj),\n-\t\t\tdescribe_object(obj));\n+\t\tprintf_ln(_(\"unreachable %s %s\"), printable_type(obj),\n+\t\t\t  describe_object(obj));\n \t\treturn;\n \t}\n \n@@ -291,8 +295,8 @@ static void check_unreachable_object(struct object *obj)\n \t */\n \tif (!(obj->flags & USED)) {\n \t\tif (show_dangling)\n-\t\t\tprintf(\"dangling %s %s\\n\", printable_type(obj),\n-\t\t\t       describe_object(obj));\n+\t\t\tprintf_ln(_(\"dangling %s %s\"), printable_type(obj),\n+\t\t\t\t  describe_object(obj));\n \t\tif (write_lost_and_found) {\n \t\t\tchar *filename = git_pathdup(\"lost-found/%s/%s\",\n \t\t\t\tobj->type == OBJ_COMMIT ? \"commit\" : \"other\",\n@@ -300,18 +304,18 @@ static void check_unreachable_object(struct object *obj)\n \t\t\tFILE *f;\n \n \t\t\tif (safe_create_leading_directories_const(filename)) {\n-\t\t\t\terror(\"Could not create lost-found\");\n+\t\t\t\terror(_(\"could not create lost-found\"));\n \t\t\t\tfree(filename);\n \t\t\t\treturn;\n \t\t\t}\n \t\t\tf = xfopen(filename, \"w\");\n \t\t\tif (obj->type == OBJ_BLOB) {\n \t\t\t\tif (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1))\n-\t\t\t\t\tdie_errno(\"Could not write '%s'\", filename);\n+\t\t\t\t\tdie_errno(_(\"could not write '%s'\"), filename);\n \t\t\t} else\n \t\t\t\tfprintf(f, \"%s\\n\", describe_object(obj));\n \t\t\tif (fclose(f))\n-\t\t\t\tdie_errno(\"Could not finish '%s'\",\n+\t\t\t\tdie_errno(_(\"could not finish '%s'\"),\n \t\t\t\t\t  filename);\n \t\t\tfree(filename);\n \t\t}\n@@ -328,7 +332,7 @@ static void check_unreachable_object(struct object *obj)\n static void check_object(struct object *obj)\n {\n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking %s\\n\", describe_object(obj));\n+\t\tfprintf_ln(stderr, _(\"Checking %s\"), describe_object(obj));\n \n \tif (obj->flags & REACHABLE)\n \t\tcheck_reachable_object(obj);\n@@ -346,7 +350,7 @@ static void check_connectivity(void)\n \t/* Look up all the requirements, warn about missing objects.. */\n \tmax = get_max_object_index();\n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking connectivity (%d objects)\\n\", max);\n+\t\tfprintf_ln(stderr, _(\"Checking connectivity (%d objects)\"), max);\n \n \tfor (i = 0; i < max; i++) {\n \t\tstruct object *obj = get_indexed_object(i);\n@@ -365,11 +369,11 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)\n \tobj->flags |= SEEN;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking %s %s\\n\",\n-\t\t\tprintable_type(obj), describe_object(obj));\n+\t\tfprintf_ln(stderr, _(\"Checking %s %s\"),\n+\t\t\t   printable_type(obj), describe_object(obj));\n \n \tif (fsck_walk(obj, NULL, &fsck_obj_options))\n-\t\tobjerror(obj, \"broken links\");\n+\t\tobjerror(obj, _(\"broken links\"));\n \terr = fsck_object(obj, buffer, size, &fsck_obj_options);\n \tif (err)\n \t\tgoto out;\n@@ -378,14 +382,15 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)\n \t\tstruct commit *commit = (struct commit *) obj;\n \n \t\tif (!commit->parents && show_root)\n-\t\t\tprintf(\"root %s\\n\", describe_object(&commit->object));\n+\t\t\tprintf_ln(_(\"root %s\"),\n+\t\t\t\t  describe_object(&commit->object));\n \t}\n \n \tif (obj->type == OBJ_TAG) {\n \t\tstruct tag *tag = (struct tag *) obj;\n \n \t\tif (show_tags && tag->tagged) {\n-\t\t\tprintf_ln(\"tagged %s %s (%s) in %s\",\n+\t\t\tprintf_ln(_(\"tagged %s %s (%s) in %s\"),\n \t\t\t\t  printable_type(tag->tagged),\n \t\t\t\t  describe_object(tag->tagged),\n \t\t\t\t  tag->tag,\n@@ -413,7 +418,8 @@ static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,\n \t\t\t\t  eaten);\n \tif (!obj) {\n \t\terrors_found |= ERROR_OBJECT;\n-\t\treturn error(\"%s: object corrupt or missing\", oid_to_hex(oid));\n+\t\treturn error(_(\"%s: object corrupt or missing\"),\n+\t\t\t     oid_to_hex(oid));\n \t}\n \tobj->flags &= ~(REACHABLE | SEEN);\n \tobj->flags |= HAS_OBJ;\n@@ -437,7 +443,8 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,\n \t\t\tobj->flags |= USED;\n \t\t\tmark_object_reachable(obj);\n \t\t} else if (!is_promisor_object(oid)) {\n-\t\t\terror(\"%s: invalid reflog entry %s\", refname, oid_to_hex(oid));\n+\t\t\terror(_(\"%s: invalid reflog entry %s\"),\n+\t\t\t      refname, oid_to_hex(oid));\n \t\t\terrors_found |= ERROR_REACHABLE;\n \t\t}\n \t}\n@@ -450,8 +457,8 @@ static int fsck_handle_reflog_ent(struct object_id *ooid, struct object_id *noid\n \tconst char *refname = cb_data;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking reflog %s->%s\\n\",\n-\t\t\toid_to_hex(ooid), oid_to_hex(noid));\n+\t\tfprintf_ln(stderr, _(\"Checking reflog %s->%s\"),\n+\t\t\t   oid_to_hex(ooid), oid_to_hex(noid));\n \n \tfsck_handle_reflog_oid(refname, ooid, 0);\n \tfsck_handle_reflog_oid(refname, noid, timestamp);\n@@ -480,13 +487,14 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid,\n \t\t\t default_refs++;\n \t\t\t return 0;\n \t\t}\n-\t\terror(\"%s: invalid sha1 pointer %s\", refname, oid_to_hex(oid));\n+\t\terror(_(\"%s: invalid sha1 pointer %s\"),\n+\t\t      refname, oid_to_hex(oid));\n \t\terrors_found |= ERROR_REACHABLE;\n \t\t/* We'll continue with the rest despite the error.. */\n \t\treturn 0;\n \t}\n \tif (obj->type != OBJ_COMMIT && is_branch(refname)) {\n-\t\terror(\"%s: not a commit\", refname);\n+\t\terror(_(\"%s: not a commit\"), refname);\n \t\terrors_found |= ERROR_REFS;\n \t}\n \tdefault_refs++;\n@@ -520,7 +528,7 @@ static void get_default_heads(void)\n \t * \"show_unreachable\" flag.\n \t */\n \tif (!default_refs) {\n-\t\tfprintf(stderr, \"notice: No default references\\n\");\n+\t\tfprintf_ln(stderr, _(\"notice: No default references\"));\n \t\tshow_unreachable = 0;\n \t}\n }\n@@ -535,7 +543,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n \n \tif (read_loose_object(path, oid, &type, &size, &contents) < 0) {\n \t\terrors_found |= ERROR_OBJECT;\n-\t\terror(\"%s: object corrupt or missing: %s\",\n+\t\terror(_(\"%s: object corrupt or missing: %s\"),\n \t\t      oid_to_hex(oid), path);\n \t\treturn 0; /* keep checking other objects */\n \t}\n@@ -548,7 +556,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n \n \tif (!obj) {\n \t\terrors_found |= ERROR_OBJECT;\n-\t\terror(\"%s: object could not be parsed: %s\",\n+\t\terror(_(\"%s: object could not be parsed: %s\"),\n \t\t      oid_to_hex(oid), path);\n \t\tif (!eaten)\n \t\t\tfree(contents);\n@@ -568,7 +576,7 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)\n static int fsck_cruft(const char *basename, const char *path, void *data)\n {\n \tif (!starts_with(basename, \"tmp_obj_\"))\n-\t\tfprintf(stderr, \"bad sha1 file: %s\\n\", path);\n+\t\tfprintf_ln(stderr, _(\"bad sha1 file: %s\"), path);\n \treturn 0;\n }\n \n@@ -583,7 +591,7 @@ static void fsck_object_dir(const char *path)\n \tstruct progress *progress = NULL;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking object directory\\n\");\n+\t\tfprintf_ln(stderr, _(\"Checking object directory\"));\n \n \tif (show_progress)\n \t\tprogress = start_progress(_(\"Checking object directories\"), 256);\n@@ -599,28 +607,28 @@ static int fsck_head_link(void)\n \tint null_is_error = 0;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking HEAD link\\n\");\n+\t\tfprintf_ln(stderr, _(\"Checking HEAD link\"));\n \n \thead_points_at = resolve_ref_unsafe(\"HEAD\", 0, &head_oid, NULL);\n \tif (!head_points_at) {\n \t\terrors_found |= ERROR_REFS;\n-\t\treturn error(\"Invalid HEAD\");\n+\t\treturn error(_(\"invalid HEAD\"));\n \t}\n \tif (!strcmp(head_points_at, \"HEAD\"))\n \t\t/* detached HEAD */\n \t\tnull_is_error = 1;\n \telse if (!starts_with(head_points_at, \"refs/heads/\")) {\n \t\terrors_found |= ERROR_REFS;\n-\t\treturn error(\"HEAD points to something strange (%s)\",\n+\t\treturn error(_(\"HEAD points to something strange (%s)\"),\n \t\t\t     head_points_at);\n \t}\n \tif (is_null_oid(&head_oid)) {\n \t\tif (null_is_error) {\n \t\t\terrors_found |= ERROR_REFS;\n-\t\t\treturn error(\"HEAD: detached HEAD points at nothing\");\n+\t\t\treturn error(_(\"HEAD: detached HEAD points at nothing\"));\n \t\t}\n-\t\tfprintf(stderr, \"notice: HEAD points to an unborn branch (%s)\\n\",\n-\t\t\thead_points_at + 11);\n+\t\tfprintf_ln(stderr, _(\"notice: HEAD points to an unborn branch (%s)\"),\n+\t\t\t   head_points_at + 11);\n \t}\n \treturn 0;\n }\n@@ -631,12 +639,12 @@ static int fsck_cache_tree(struct cache_tree *it)\n \tint err = 0;\n \n \tif (verbose)\n-\t\tfprintf(stderr, \"Checking cache tree\\n\");\n+\t\tfprintf_ln(stderr, _(\"Checking cache tree\"));\n \n \tif (0 <= it->entry_count) {\n \t\tstruct object *obj = parse_object(the_repository, &it->oid);\n \t\tif (!obj) {\n-\t\t\terror(\"%s: invalid sha1 pointer in cache-tree\",\n+\t\t\terror(_(\"%s: invalid sha1 pointer in cache-tree\"),\n \t\t\t      oid_to_hex(&it->oid));\n \t\t\terrors_found |= ERROR_REFS;\n \t\t\treturn 1;\n@@ -647,7 +655,7 @@ static int fsck_cache_tree(struct cache_tree *it)\n \t\t\t\tobj, xstrdup(\":\"));\n \t\tmark_object_reachable(obj);\n \t\tif (obj->type != OBJ_TREE)\n-\t\t\terr |= objerror(obj, \"non-tree in cache-tree\");\n+\t\t\terr |= objerror(obj, _(\"non-tree in cache-tree\"));\n \t}\n \tfor (i = 0; i < it->subtree_nr; i++)\n \t\terr |= fsck_cache_tree(it->down[i]->cache_tree);\n@@ -789,7 +797,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \t\t\tif (!obj || !(obj->flags & HAS_OBJ)) {\n \t\t\t\tif (is_promisor_object(&oid))\n \t\t\t\t\tcontinue;\n-\t\t\t\terror(\"%s: object missing\", oid_to_hex(&oid));\n+\t\t\t\terror(_(\"%s: object missing\"), oid_to_hex(&oid));\n \t\t\t\terrors_found |= ERROR_OBJECT;\n \t\t\t\tcontinue;\n \t\t\t}\n@@ -801,7 +809,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)\n \t\t\tmark_object_reachable(obj);\n \t\t\tcontinue;\n \t\t}\n-\t\terror(\"invalid parameter: expected sha1, got '%s'\", arg);\n+\t\terror(_(\"invalid parameter: expected sha1, got '%s'\"), arg);\n \t\terrors_found |= ERROR_OBJECT;\n \t}\n \ndiff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh\nindex 388b0611d8..353bdfd415 100755\n--- a/t/t1410-reflog.sh\n+++ b/t/t1410-reflog.sh\n@@ -20,12 +20,12 @@ check_have () {\n }\n \n check_fsck () {\n-\toutput=$(git fsck --full)\n+\tgit fsck --full >fsck.output\n \tcase \"$1\" in\n \t'')\n-\t\ttest -z \"$output\" ;;\n+\t\ttest_must_be_empty fsck.output ;;\n \t*)\n-\t\techo \"$output\" | grep \"$1\" ;;\n+\t\ttest_i18ngrep \"$1\" fsck.output ;;\n \tesac\n }\n \ndiff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh\nindex 90c765df3a..15ca98b2a9 100755\n--- a/t/t1450-fsck.sh\n+++ b/t/t1450-fsck.sh\n@@ -70,7 +70,7 @@ test_expect_success 'object with bad sha1' '\n \n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"$sha.*corrupt\" out\n+\ttest_i18ngrep \"$sha.*corrupt\" out\n '\n \n test_expect_success 'branch pointing to non-commit' '\n@@ -78,7 +78,7 @@ test_expect_success 'branch pointing to non-commit' '\n \ttest_when_finished \"git update-ref -d refs/heads/invalid\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"not a commit\" out\n+\ttest_i18ngrep \"not a commit\" out\n '\n \n test_expect_success 'HEAD link pointing at a funny object' '\n@@ -88,7 +88,7 @@ test_expect_success 'HEAD link pointing at a funny object' '\n \t# avoid corrupt/broken HEAD from interfering with repo discovery\n \ttest_must_fail env GIT_DIR=.git git fsck 2>out &&\n \tcat out &&\n-\tgrep \"detached HEAD points\" out\n+\ttest_i18ngrep \"detached HEAD points\" out\n '\n \n test_expect_success 'HEAD link pointing at a funny place' '\n@@ -98,7 +98,7 @@ test_expect_success 'HEAD link pointing at a funny place' '\n \t# avoid corrupt/broken HEAD from interfering with repo discovery\n \ttest_must_fail env GIT_DIR=.git git fsck 2>out &&\n \tcat out &&\n-\tgrep \"HEAD points to something strange\" out\n+\ttest_i18ngrep \"HEAD points to something strange\" out\n '\n \n test_expect_success 'email without @ is okay' '\n@@ -122,7 +122,7 @@ test_expect_success 'email with embedded > is not okay' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new\" out\n+\ttest_i18ngrep \"error in commit $new\" out\n '\n \n test_expect_success 'missing < email delimiter is reported nicely' '\n@@ -134,7 +134,7 @@ test_expect_success 'missing < email delimiter is reported nicely' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.* - bad name\" out\n+\ttest_i18ngrep \"error in commit $new.* - bad name\" out\n '\n \n test_expect_success 'missing email is reported nicely' '\n@@ -146,7 +146,7 @@ test_expect_success 'missing email is reported nicely' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.* - missing email\" out\n+\ttest_i18ngrep \"error in commit $new.* - missing email\" out\n '\n \n test_expect_success '> in name is reported' '\n@@ -158,7 +158,7 @@ test_expect_success '> in name is reported' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new\" out\n+\ttest_i18ngrep \"error in commit $new\" out\n '\n \n # date is 2^64 + 1\n@@ -172,7 +172,7 @@ test_expect_success 'integer overflow in timestamps is reported' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.*integer overflow\" out\n+\ttest_i18ngrep \"error in commit $new.*integer overflow\" out\n '\n \n test_expect_success 'commit with NUL in header' '\n@@ -184,7 +184,7 @@ test_expect_success 'commit with NUL in header' '\n \ttest_when_finished \"git update-ref -d refs/heads/bogus\" &&\n \ttest_must_fail git fsck 2>out &&\n \tcat out &&\n-\tgrep \"error in commit $new.*unterminated header: NUL at offset\" out\n+\ttest_i18ngrep \"error in commit $new.*unterminated header: NUL at offset\" out\n '\n \n test_expect_success 'tree object with duplicate entries' '\n@@ -205,7 +205,7 @@ test_expect_success 'tree object with duplicate entries' '\n \t\tgit hash-object -w -t tree --stdin\n \t) &&\n \ttest_must_fail git fsck 2>out &&\n-\tgrep \"error in tree .*contains duplicate file entries\" out\n+\ttest_i18ngrep \"error in tree .*contains duplicate file entries\" out\n '\n \n test_expect_success 'unparseable tree object' '\n@@ -259,7 +259,7 @@ test_expect_success 'tag pointing to nonexistent' '\n \ttest_when_finished \"git update-ref -d refs/tags/invalid\" &&\n \ttest_must_fail git fsck --tags >out &&\n \tcat out &&\n-\tgrep \"broken link\" out\n+\ttest_i18ngrep \"broken link\" out\n '\n \n test_expect_success 'tag pointing to something else than its type' '\n@@ -301,7 +301,7 @@ test_expect_success 'tag with incorrect tag name & missing tagger' '\n \twarning in tag $tag: badTagName: invalid '\\''tag'\\'' name: wrong name format\n \twarning in tag $tag: missingTaggerEntry: invalid format - expected '\\''tagger'\\'' line\n \tEOF\n-\ttest_cmp expect out\n+\ttest_i18ncmp expect out\n '\n \n test_expect_success 'tag with bad tagger' '\n@@ -320,7 +320,7 @@ test_expect_success 'tag with bad tagger' '\n \techo $tag >.git/refs/tags/wrong &&\n \ttest_when_finished \"git update-ref -d refs/tags/wrong\" &&\n \ttest_must_fail git fsck --tags 2>out &&\n-\tgrep \"error in tag .*: invalid author/committer\" out\n+\ttest_i18ngrep \"error in tag .*: invalid author/committer\" out\n '\n \n test_expect_success 'tag with NUL in header' '\n@@ -340,7 +340,7 @@ test_expect_success 'tag with NUL in header' '\n \ttest_when_finished \"git update-ref -d refs/tags/wrong\" &&\n \ttest_must_fail git fsck --tags 2>out &&\n \tcat out &&\n-\tgrep \"error in tag $tag.*unterminated header: NUL at offset\" out\n+\ttest_i18ngrep \"error in tag $tag.*unterminated header: NUL at offset\" out\n '\n \n test_expect_success 'cleaned up' '\n@@ -396,7 +396,7 @@ test_expect_success 'fsck notices blob entry pointing to null sha1' '\n \t       git hash-object -w --stdin -t tree) &&\n \t  git fsck 2>out &&\n \t  cat out &&\n-\t  grep \"warning.*null sha1\" out\n+\t  test_i18ngrep \"warning.*null sha1\" out\n \t)\n '\n \n@@ -407,7 +407,7 @@ test_expect_success 'fsck notices submodule entry pointing to null sha1' '\n \t       git hash-object -w --stdin -t tree) &&\n \t  git fsck 2>out &&\n \t  cat out &&\n-\t  grep \"warning.*null sha1\" out\n+\t  test_i18ngrep \"warning.*null sha1\" out\n \t)\n '\n \n@@ -428,7 +428,7 @@ while read name path pretty; do\n \t\t\tbad_tree=$(git mktree <bad) &&\n \t\t\tgit fsck 2>out &&\n \t\t\tcat out &&\n-\t\t\tgrep \"warning.*tree $bad_tree\" out\n+\t\t\ttest_i18ngrep \"warning.*tree $bad_tree\" out\n \t\t)'\n \tdone <<-\\EOF\n \t100644 blob\n@@ -474,9 +474,9 @@ test_expect_success 'NUL in commit' '\n \t\tgit branch bad $(cat name) &&\n \n \t\ttest_must_fail git -c fsck.nulInCommit=error fsck 2>warn.1 &&\n-\t\tgrep nulInCommit warn.1 &&\n+\t\ttest_i18ngrep nulInCommit warn.1 &&\n \t\tgit fsck 2>warn.2 &&\n-\t\tgrep nulInCommit warn.2\n+\t\ttest_i18ngrep nulInCommit warn.2\n \t)\n '\n \n@@ -594,7 +594,7 @@ test_expect_success 'fsck --name-objects' '\n \t\tremove_object $(git rev-parse julius:caesar.t) &&\n \t\ttest_must_fail git fsck --name-objects >out &&\n \t\ttree=$(git rev-parse --verify julius:) &&\n-\t\tegrep \"$tree \\((refs/heads/master|HEAD)@\\{[0-9]*\\}:\" out\n+\t\ttest_i18ngrep -E \"$tree \\((refs/heads/master|HEAD)@\\{[0-9]*\\}:\" out\n \t)\n '\n \n@@ -605,7 +605,7 @@ test_expect_success 'alternate objects are correctly blamed' '\n \tmkdir alt.git/objects/12 &&\n \t>alt.git/objects/12/34567890123456789012345678901234567890 &&\n \ttest_must_fail git fsck >out 2>&1 &&\n-\tgrep alt.git out\n+\ttest_i18ngrep alt.git out\n '\n \n test_expect_success 'fsck errors in packed objects' '\n@@ -624,8 +624,8 @@ test_expect_success 'fsck errors in packed objects' '\n \tremove_object $one &&\n \tremove_object $two &&\n \ttest_must_fail git fsck 2>out &&\n-\tgrep \"error in commit $one.* - bad name\" out &&\n-\tgrep \"error in commit $two.* - bad name\" out &&\n+\ttest_i18ngrep \"error in commit $one.* - bad name\" out &&\n+\ttest_i18ngrep \"error in commit $two.* - bad name\" out &&\n \t! grep corrupt out\n '\n \n@@ -706,7 +706,7 @@ test_expect_success 'fsck notices dangling objects' '\n \t\tgit fsck >actual &&\n \t\t# the output order is non-deterministic, as it comes from a hash\n \t\tsort <actual >actual.sorted &&\n-\t\ttest_cmp expect actual.sorted\n+\t\ttest_i18ncmp expect actual.sorted\n \t)\n '\n \ndiff --git a/t/t6050-replace.sh b/t/t6050-replace.sh\nindex 86374a9c52..7700a8e793 100755\n--- a/t/t6050-replace.sh\n+++ b/t/t6050-replace.sh\n@@ -133,8 +133,8 @@ test_expect_success 'tag replaced commit' '\n \n test_expect_success '\"git fsck\" works' '\n      git fsck master >fsck_master.out &&\n-     grep \"dangling commit $R\" fsck_master.out &&\n-     grep \"dangling tag $(cat .git/refs/tags/mytag)\" fsck_master.out &&\n+     test_i18ngrep \"dangling commit $R\" fsck_master.out &&\n+     test_i18ngrep \"dangling tag $(cat .git/refs/tags/mytag)\" fsck_master.out &&\n      test -z \"$(git fsck)\"\n '\n \ndiff --git a/t/t7415-submodule-names.sh b/t/t7415-submodule-names.sh\nindex 293e2e1963..49a37efe9c 100755\n--- a/t/t7415-submodule-names.sh\n+++ b/t/t7415-submodule-names.sh\n@@ -154,7 +154,7 @@ test_expect_success 'fsck detects symlinked .gitmodules file' '\n \t\t# symlink detector; this grep string comes from the config\n \t\t# variable name and will not be translated.\n \t\ttest_must_fail git fsck 2>output &&\n-\t\tgrep gitmodulesSymlink output\n+\t\ttest_i18ngrep gitmodulesSymlink output\n \t)\n '\n \n@@ -172,7 +172,7 @@ test_expect_success 'fsck detects non-blob .gitmodules' '\n \t\tgit ls-tree HEAD | sed s/subdir/.gitmodules/ | git mktree &&\n \n \t\ttest_must_fail git fsck 2>output &&\n-\t\tgrep gitmodulesBlob output\n+\t\ttest_i18ngrep gitmodulesBlob output\n \t)\n '\n \n@@ -186,7 +186,7 @@ test_expect_success 'fsck detects corrupt .gitmodules' '\n \t\tgit commit -m \"broken gitmodules\" &&\n \n \t\tgit fsck 2>output &&\n-\t\tgrep gitmodulesParse output &&\n+\t\ttest_i18ngrep gitmodulesParse output &&\n \t\ttest_i18ngrep ! \"bad config\" output\n \t)\n '\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362844","messageId":"20181110051615.8641-1-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181105192059.20303-1-pclouds@gmail.com","subject":"[PATCH v3 00/16] Mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:15:59Z","receivedAt":"2018-11-10T05:39:36Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"v3 is just small touchups here and there after the review comments\nfrom v2.\n\nRange-diff against v2:\n 1:  e77c203313 !  1:  936f84d4b3 git.c: mark more strings for translation\n    @@ -3,7 +3,7 @@\n         git.c: mark more strings for translation\n     \n         One string is slightly updated to keep consistency with the rest:\n    -    die() should with lowercase.\n    +    die() should begin with lowercase.\n     \n      diff --git a/git.c b/git.c\n      --- a/git.c\n 2:  12c9468696 =  2:  8ff2de14bf alias.c: mark split_cmdline_strerror() strings for translation\n 3:  bf662dc105 =  3:  8e147f6bff archive.c: mark more strings for translation\n 4:  1d032b0fdf =  4:  5d574460eb attr.c: mark more string for translation\n 5:  2c3ad8c262 =  5:  8e37efb756 read-cache.c: turn die(\"internal error\") to BUG()\n 6:  df25ac78b1 =  6:  83b7b6d029 read-cache.c: mark more strings for translation\n 7:  241e5a7450 =  7:  4bd085682d read-cache.c: add missing colon separators\n 8:  8f60728b0f =  8:  fb72be3a1e reflog: mark strings for translation\n 9:  24d2ed6682 =  9:  711812d70b remote.c: turn some error() or die() to BUG()\n10:  26e8cee291 = 10:  0213c1f5eb remote.c: mark messages for translation\n11:  2409f76902 = 11:  85459c65ca repack: mark more strings for translation\n12:  afafe6771c ! 12:  21916a8fb4 parse-options: replace opterror() with optname()\n    @@ -2,6 +2,11 @@\n     \n         parse-options: replace opterror() with optname()\n     \n    +    Introduce optname() that does the early half of original opterror() to\n    +    come up with the name of the option reported back to the user, and use\n    +    it to kill opterror().  The callers of opterror() now directly call\n    +    error() using the string returned by opterror() instead.\n    +\n         There are a few issues with opterror()\n     \n         - it tries to assemble an English sentence from pieces. This is not\n    @@ -14,8 +19,7 @@\n         - Since it takes a string instead of printf format, one call site has\n           to assemble the string manually before passing to it.\n     \n    -    Kill it and produce the option name with optname(). The user will use\n    -    error() directly. This solves the second and third problems.\n    +    Using error() directly solves the second and third problems.\n     \n         It kind helps the first problem as well because \"%s does foo\" does\n         give a translator a full sentence in a sense and let them reorder if\n13:  e8b4af8fac = 13:  8c9d2985b5 parse-options.c: turn some die() to BUG()\n14:  c3530e162e = 14:  b81cdeda46 parse-options.c: mark more strings for translation\n15:  644c56780c ! 15:  dd872fc39b fsck: reduce word legos to help i18n\n    @@ -19,7 +19,7 @@\n     -\tstatic struct strbuf buf = STRBUF_INIT;\n     -\tchar *name = name_objects ?\n     -\t\tlookup_decoration(fsck_walk_options.object_names, obj) : NULL;\n    -+\tstatic struct strbuf bufs[4] = {\n    ++\tstatic struct strbuf bufs[] = {\n     +\t\tSTRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT\n     +\t};\n     +\tstatic int b = 0;\n    @@ -69,15 +69,18 @@\n      {\n     -\tobjreport(obj, (type == FSCK_WARN) ? \"warning\" : \"error\", message);\n     -\treturn (type == FSCK_WARN) ? 0 : 1;\n    -+\tif (type == FSCK_WARN) {\n    ++\tswitch (type) {\n    ++\tcase FSCK_WARN:\n     +\t\tfprintf_ln(stderr, \"warning in %s %s: %s\",\n     +\t\t\t   printable_type(obj), describe_object(obj), message);\n     +\t\treturn 0;\n    ++\tcase FSCK_ERROR:\n    ++\t\tfprintf_ln(stderr, \"error in %s %s: %s\",\n    ++\t\t\t   printable_type(obj), describe_object(obj), message);\n    ++\t\treturn 1;\n    ++\tdefault:\n    ++\t\tBUG(\"%d (FSCK_IGNORE?) should never trigger this callback\", type);\n     +\t}\n    -+\n    -+\tfprintf_ln(stderr, \"error in %s %s: %s\",\n    -+\t\t   printable_type(obj), describe_object(obj), message);\n    -+\treturn 1;\n      }\n      \n      static struct object_array pending;\n16:  61af36567b ! 16:  8f1bbd1c65 fsck: mark strings for translation\n    @@ -28,22 +28,21 @@\n      \treturn -1;\n      }\n     @@\n    - \tstruct object *obj, int type, const char *message)\n      {\n    - \tif (type == FSCK_WARN) {\n    + \tswitch (type) {\n    + \tcase FSCK_WARN:\n     -\t\tfprintf_ln(stderr, \"warning in %s %s: %s\",\n     +\t\t/* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */\n     +\t\tfprintf_ln(stderr, _(\"warning in %s %s: %s\"),\n      \t\t\t   printable_type(obj), describe_object(obj), message);\n      \t\treturn 0;\n    - \t}\n    - \n    --\tfprintf_ln(stderr, \"error in %s %s: %s\",\n    -+\t/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */\n    -+\tfprintf_ln(stderr, _(\"error in %s %s: %s\"),\n    - \t\t   printable_type(obj), describe_object(obj), message);\n    - \treturn 1;\n    - }\n    + \tcase FSCK_ERROR:\n    +-\t\tfprintf_ln(stderr, \"error in %s %s: %s\",\n    ++\t\t/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */\n    ++\t\tfprintf_ln(stderr, _(\"error in %s %s: %s\"),\n    + \t\t\t   printable_type(obj), describe_object(obj), message);\n    + \t\treturn 1;\n    + \tdefault:\n     @@\n      \t */\n      \tif (!obj) {\n\nNguyễn Thái Ngọc Duy (16):\n  git.c: mark more strings for translation\n  alias.c: mark split_cmdline_strerror() strings for translation\n  archive.c: mark more strings for translation\n  attr.c: mark more string for translation\n  read-cache.c: turn die(\"internal error\") to BUG()\n  read-cache.c: mark more strings for translation\n  read-cache.c: add missing colon separators\n  reflog: mark strings for translation\n  remote.c: turn some error() or die() to BUG()\n  remote.c: mark messages for translation\n  repack: mark more strings for translation\n  parse-options: replace opterror() with optname()\n  parse-options.c: turn some die() to BUG()\n  parse-options.c: mark more strings for translation\n  fsck: reduce word legos to help i18n\n  fsck: mark strings for translation\n\n alias.c                    |   4 +-\n archive.c                  |   8 +-\n attr.c                     |   4 +-\n builtin/fsck.c             | 159 +++++++++++++++++++++----------------\n builtin/merge.c            |   4 +-\n builtin/reflog.c           |  34 ++++----\n builtin/repack.c           |  26 +++---\n builtin/revert.c           |   3 +-\n git.c                      |  32 ++++----\n parse-options-cb.c         |   7 +-\n parse-options.c            |  64 ++++++++-------\n parse-options.h            |   5 +-\n read-cache.c               |  73 ++++++++---------\n ref-filter.c               |   8 +-\n remote.c                   |  49 ++++++------\n t/t0040-parse-options.sh   |   4 +-\n t/t1410-reflog.sh          |   6 +-\n t/t1450-fsck.sh            |  52 ++++++------\n t/t4211-line-log.sh        |   2 +-\n t/t6050-replace.sh         |   4 +-\n t/t7415-submodule-names.sh |   6 +-\n 21 files changed, 295 insertions(+), 259 deletions(-)\n\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362845","messageId":"20181110051615.8641-4-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 03/16] archive.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:02Z","receivedAt":"2018-11-10T05:39:49Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Two messages also print extra information to be more useful\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n archive.c | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 9d16b7fadf..d8f6e1ce30 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -385,12 +385,12 @@ static void parse_treeish_arg(const char **argv,\n \t\tint refnamelen = colon - name;\n \n \t\tif (!dwim_ref(name, refnamelen, &oid, &ref))\n-\t\t\tdie(\"no such ref: %.*s\", refnamelen, name);\n+\t\t\tdie(_(\"no such ref: %.*s\"), refnamelen, name);\n \t\tfree(ref);\n \t}\n \n \tif (get_oid(name, &oid))\n-\t\tdie(\"Not a valid object name\");\n+\t\tdie(_(\"not a valid object name: %s\"), name);\n \n \tcommit = lookup_commit_reference_gently(ar_args->repo, &oid, 1);\n \tif (commit) {\n@@ -403,7 +403,7 @@ static void parse_treeish_arg(const char **argv,\n \n \ttree = parse_tree_indirect(&oid);\n \tif (tree == NULL)\n-\t\tdie(\"not a tree object\");\n+\t\tdie(_(\"not a tree object: %s\"), oid_to_hex(&oid));\n \n \tif (prefix) {\n \t\tstruct object_id tree_oid;\n@@ -413,7 +413,7 @@ static void parse_treeish_arg(const char **argv,\n \t\terr = get_tree_entry(&tree->object.oid, prefix, &tree_oid,\n \t\t\t\t     &mode);\n \t\tif (err || !S_ISDIR(mode))\n-\t\t\tdie(\"current working directory is untracked\");\n+\t\t\tdie(_(\"current working directory is untracked\"));\n \n \t\ttree = parse_tree_indirect(&tree_oid);\n \t}\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362846","messageId":"20181110051615.8641-3-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 02/16] alias.c: mark split_cmdline_strerror() strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:01Z","receivedAt":"2018-11-10T05:40:48Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This function can be part of translated messages. To make sure we\ndon't have a sentence with mixed languages, mark the strings for\ntranslation, but only use translated strings in places we know we will\noutput translated strings.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n alias.c         | 4 ++--\n builtin/merge.c | 2 +-\n git.c           | 2 +-\n 3 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/alias.c b/alias.c\nindex a7e4e57130..c471538020 100644\n--- a/alias.c\n+++ b/alias.c\n@@ -47,8 +47,8 @@ void list_aliases(struct string_list *list)\n #define SPLIT_CMDLINE_BAD_ENDING 1\n #define SPLIT_CMDLINE_UNCLOSED_QUOTE 2\n static const char *split_cmdline_errors[] = {\n-\t\"cmdline ends with \\\\\",\n-\t\"unclosed quote\"\n+\tN_(\"cmdline ends with \\\\\"),\n+\tN_(\"unclosed quote\")\n };\n \n int split_cmdline(char *cmdline, const char ***argv)\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 4aa6071598..92ba7e1c6d 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -577,7 +577,7 @@ static void parse_branch_merge_options(char *bmo)\n \targc = split_cmdline(bmo, &argv);\n \tif (argc < 0)\n \t\tdie(_(\"Bad branch.%s.mergeoptions string: %s\"), branch,\n-\t\t    split_cmdline_strerror(argc));\n+\t\t    _(split_cmdline_strerror(argc)));\n \tREALLOC_ARRAY(argv, argc + 2);\n \tMOVE_ARRAY(argv + 1, argv, argc + 1);\n \targc++;\ndiff --git a/git.c b/git.c\nindex 5fd30da093..c7e122cfc1 100644\n--- a/git.c\n+++ b/git.c\n@@ -344,7 +344,7 @@ static int handle_alias(int *argcp, const char ***argv)\n \t\tcount = split_cmdline(alias_string, &new_argv);\n \t\tif (count < 0)\n \t\t\tdie(_(\"bad alias.%s string: %s\"), alias_command,\n-\t\t\t    split_cmdline_strerror(count));\n+\t\t\t    _(split_cmdline_strerror(count)));\n \t\toption_count = handle_options(&new_argv, &count, &envchanged);\n \t\tif (envchanged)\n \t\t\tdie(_(\"alias '%s' changes environment variables.\\n\"\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362847","messageId":"20181110051615.8641-5-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 04/16] attr.c: mark more string for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:03Z","receivedAt":"2018-11-10T05:41:01Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n attr.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 60d284796d..3770bc1a11 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -372,8 +372,8 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,\n \tif (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen &&\n \t    starts_with(name, ATTRIBUTE_MACRO_PREFIX)) {\n \t\tif (!macro_ok) {\n-\t\t\tfprintf(stderr, \"%s not allowed: %s:%d\\n\",\n-\t\t\t\tname, src, lineno);\n+\t\t\tfprintf_ln(stderr, _(\"%s not allowed: %s:%d\"),\n+\t\t\t\t   name, src, lineno);\n \t\t\tgoto fail_return;\n \t\t}\n \t\tis_macro = 1;\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362848","messageId":"20181110051615.8641-7-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 06/16] read-cache.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:05Z","receivedAt":"2018-11-10T05:41:10Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"There are a couple other improvements on these strings as well:\n\n - add missing colon (as separator)\n - quote paths\n - provide more information on error messages\n - keep first word in lowercase\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n read-cache.c    | 57 +++++++++++++++++++++++++------------------------\n t/t1450-fsck.sh |  2 +-\n 2 files changed, 30 insertions(+), 29 deletions(-)\n\ndiff --git a/read-cache.c b/read-cache.c\nindex 0c37f4885e..858befe738 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -672,7 +672,8 @@ static struct cache_entry *create_alias_ce(struct index_state *istate,\n \tstruct cache_entry *new_entry;\n \n \tif (alias->ce_flags & CE_ADDED)\n-\t\tdie(\"Will not add file alias '%s' ('%s' already exists in index)\", ce->name, alias->name);\n+\t\tdie(_(\"will not add file alias '%s' ('%s' already exists in index)\"),\n+\t\t    ce->name, alias->name);\n \n \t/* Ok, create the new entry using the name of the existing alias */\n \tlen = ce_namelen(alias);\n@@ -687,7 +688,7 @@ void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)\n {\n \tstruct object_id oid;\n \tif (write_object_file(\"\", 0, blob_type, &oid))\n-\t\tdie(\"cannot create an empty blob in the object database\");\n+\t\tdie(_(\"cannot create an empty blob in the object database\"));\n \toidcpy(&ce->oid, &oid);\n }\n \n@@ -708,7 +709,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \t\tnewflags |= HASH_RENORMALIZE;\n \n \tif (!S_ISREG(st_mode) && !S_ISLNK(st_mode) && !S_ISDIR(st_mode))\n-\t\treturn error(\"%s: can only add regular files, symbolic links or git-directories\", path);\n+\t\treturn error(_(\"%s: can only add regular files, symbolic links or git-directories\"), path);\n \n \tnamelen = strlen(path);\n \tif (S_ISDIR(st_mode)) {\n@@ -763,7 +764,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \tif (!intent_only) {\n \t\tif (index_path(istate, &ce->oid, path, st, newflags)) {\n \t\t\tdiscard_cache_entry(ce);\n-\t\t\treturn error(\"unable to index file %s\", path);\n+\t\t\treturn error(_(\"unable to index file '%s'\"), path);\n \t\t}\n \t} else\n \t\tset_object_name_for_intent_to_add_entry(ce);\n@@ -782,7 +783,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,\n \t\tdiscard_cache_entry(ce);\n \telse if (add_index_entry(istate, ce, add_option)) {\n \t\tdiscard_cache_entry(ce);\n-\t\treturn error(\"unable to add %s to index\", path);\n+\t\treturn error(_(\"unable to add '%s' to index\"), path);\n \t}\n \tif (verbose && !was_same)\n \t\tprintf(\"add '%s'\\n\", path);\n@@ -793,7 +794,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int flags)\n {\n \tstruct stat st;\n \tif (lstat(path, &st))\n-\t\tdie_errno(\"unable to stat '%s'\", path);\n+\t\tdie_errno(_(\"unable to stat '%s'\"), path);\n \treturn add_to_index(istate, path, &st, flags);\n }\n \n@@ -818,7 +819,7 @@ struct cache_entry *make_cache_entry(struct index_state *istate,\n \tint len;\n \n \tif (!verify_path(path, mode)) {\n-\t\terror(\"Invalid path '%s'\", path);\n+\t\terror(_(\"invalid path '%s'\"), path);\n \t\treturn NULL;\n \t}\n \n@@ -844,7 +845,7 @@ struct cache_entry *make_transient_cache_entry(unsigned int mode, const struct o\n \tint len;\n \n \tif (!verify_path(path, mode)) {\n-\t\terror(\"Invalid path '%s'\", path);\n+\t\terror(_(\"invalid path '%s'\"), path);\n \t\treturn NULL;\n \t}\n \n@@ -1297,12 +1298,12 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e\n \tif (!ok_to_add)\n \t\treturn -1;\n \tif (!verify_path(ce->name, ce->ce_mode))\n-\t\treturn error(\"Invalid path '%s'\", ce->name);\n+\t\treturn error(_(\"invalid path '%s'\"), ce->name);\n \n \tif (!skip_df_check &&\n \t    check_file_directory_conflict(istate, ce, pos, ok_to_replace)) {\n \t\tif (!ok_to_replace)\n-\t\t\treturn error(\"'%s' appears as both a file and as a directory\",\n+\t\t\treturn error(_(\"'%s' appears as both a file and as a directory\"),\n \t\t\t\t     ce->name);\n \t\tpos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce));\n \t\tpos = -pos-1;\n@@ -1676,10 +1677,10 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)\n \tint hdr_version;\n \n \tif (hdr->hdr_signature != htonl(CACHE_SIGNATURE))\n-\t\treturn error(\"bad signature\");\n+\t\treturn error(_(\"bad signature 0x%08x\"), hdr->hdr_signature);\n \thdr_version = ntohl(hdr->hdr_version);\n \tif (hdr_version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < hdr_version)\n-\t\treturn error(\"bad index version %d\", hdr_version);\n+\t\treturn error(_(\"bad index version %d\"), hdr_version);\n \n \tif (!verify_index_checksum)\n \t\treturn 0;\n@@ -1688,7 +1689,7 @@ static int verify_hdr(const struct cache_header *hdr, unsigned long size)\n \tthe_hash_algo->update_fn(&c, hdr, size - the_hash_algo->rawsz);\n \tthe_hash_algo->final_fn(hash, &c);\n \tif (!hasheq(hash, (unsigned char *)hdr + size - the_hash_algo->rawsz))\n-\t\treturn error(\"bad index file sha1 signature\");\n+\t\treturn error(_(\"bad index file sha1 signature\"));\n \treturn 0;\n }\n \n@@ -1718,9 +1719,9 @@ static int read_index_extension(struct index_state *istate,\n \t\tbreak;\n \tdefault:\n \t\tif (*ext < 'A' || 'Z' < *ext)\n-\t\t\treturn error(\"index uses %.4s extension, which we do not understand\",\n+\t\t\treturn error(_(\"index uses %.4s extension, which we do not understand\"),\n \t\t\t\t     ext);\n-\t\tfprintf(stderr, \"ignoring %.4s extension\\n\", ext);\n+\t\tfprintf_ln(stderr, _(\"ignoring %.4s extension\"), ext);\n \t\tbreak;\n \t}\n \treturn 0;\n@@ -1767,7 +1768,7 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,\n \t\textended_flags = get_be16(&ondisk2->flags2) << 16;\n \t\t/* We do not yet understand any bit out of CE_EXTENDED_FLAGS */\n \t\tif (extended_flags & ~CE_EXTENDED_FLAGS)\n-\t\t\tdie(\"Unknown index entry format %08x\", extended_flags);\n+\t\t\tdie(_(\"unknown index entry format 0x%08x\"), extended_flags);\n \t\tflags |= extended_flags;\n \t\tname = ondisk2->name;\n \t}\n@@ -1840,13 +1841,13 @@ static void check_ce_order(struct index_state *istate)\n \t\tint name_compare = strcmp(ce->name, next_ce->name);\n \n \t\tif (0 < name_compare)\n-\t\t\tdie(\"unordered stage entries in index\");\n+\t\t\tdie(_(\"unordered stage entries in index\"));\n \t\tif (!name_compare) {\n \t\t\tif (!ce_stage(ce))\n-\t\t\t\tdie(\"multiple stage entries for merged file '%s'\",\n+\t\t\t\tdie(_(\"multiple stage entries for merged file '%s'\"),\n \t\t\t\t    ce->name);\n \t\t\tif (ce_stage(ce) > ce_stage(next_ce))\n-\t\t\t\tdie(\"unordered stage entries for '%s'\",\n+\t\t\t\tdie(_(\"unordered stage entries for '%s'\"),\n \t\t\t\t    ce->name);\n \t\t}\n \t}\n@@ -2149,19 +2150,19 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n \tif (fd < 0) {\n \t\tif (!must_exist && errno == ENOENT)\n \t\t\treturn 0;\n-\t\tdie_errno(\"%s: index file open failed\", path);\n+\t\tdie_errno(_(\"%s: index file open failed\"), path);\n \t}\n \n \tif (fstat(fd, &st))\n-\t\tdie_errno(\"cannot stat the open index\");\n+\t\tdie_errno(_(\"%s: cannot stat the open index\"), path);\n \n \tmmap_size = xsize_t(st.st_size);\n \tif (mmap_size < sizeof(struct cache_header) + the_hash_algo->rawsz)\n-\t\tdie(\"index file smaller than expected\");\n+\t\tdie(_(\"%s: index file smaller than expected\"), path);\n \n \tmmap = xmmap(NULL, mmap_size, PROT_READ, MAP_PRIVATE, fd, 0);\n \tif (mmap == MAP_FAILED)\n-\t\tdie_errno(\"unable to map index file\");\n+\t\tdie_errno(_(\"%s: unable to map index file\"), path);\n \tclose(fd);\n \n \thdr = (const struct cache_header *)mmap;\n@@ -2243,7 +2244,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n \n unmap:\n \tmunmap((void *)mmap, mmap_size);\n-\tdie(\"index file corrupt\");\n+\tdie(_(\"index file corrupt\"));\n }\n \n /*\n@@ -2255,7 +2256,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)\n static void freshen_shared_index(const char *shared_index, int warn)\n {\n \tif (!check_and_freshen_file(shared_index, 1) && warn)\n-\t\twarning(\"could not freshen shared index '%s'\", shared_index);\n+\t\twarning(_(\"could not freshen shared index '%s'\"), shared_index);\n }\n \n int read_index_from(struct index_state *istate, const char *path,\n@@ -2290,7 +2291,7 @@ int read_index_from(struct index_state *istate, const char *path,\n \tbase_path = xstrfmt(\"%s/sharedindex.%s\", gitdir, base_oid_hex);\n \tret = do_read_index(split_index->base, base_path, 1);\n \tif (!oideq(&split_index->base_oid, &split_index->base->oid))\n-\t\tdie(\"broken index, expect %s in %s, got %s\",\n+\t\tdie(_(\"broken index, expect %s in %s, got %s\"),\n \t\t    base_oid_hex, base_path,\n \t\t    oid_to_hex(&split_index->base->oid));\n \n@@ -3076,7 +3077,7 @@ static int write_shared_index(struct index_state *istate,\n \t\treturn ret;\n \tret = adjust_shared_perm(get_tempfile_path(*temp));\n \tif (ret) {\n-\t\terror(\"cannot fix permission bits on %s\", get_tempfile_path(*temp));\n+\t\terror(_(\"cannot fix permission bits on '%s'\"), get_tempfile_path(*temp));\n \t\treturn ret;\n \t}\n \tret = rename_tempfile(temp,\n@@ -3222,7 +3223,7 @@ int read_index_unmerged(struct index_state *istate)\n \t\tnew_ce->ce_namelen = len;\n \t\tnew_ce->ce_mode = ce->ce_mode;\n \t\tif (add_index_entry(istate, new_ce, ADD_CACHE_SKIP_DFCHECK))\n-\t\t\treturn error(\"%s: cannot drop to stage #0\",\n+\t\t\treturn error(_(\"%s: cannot drop to stage #0\"),\n \t\t\t\t     new_ce->name);\n \t}\n \treturn unmerged;\ndiff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh\nindex 0f2dd26f74..90c765df3a 100755\n--- a/t/t1450-fsck.sh\n+++ b/t/t1450-fsck.sh\n@@ -754,7 +754,7 @@ test_expect_success 'detect corrupt index file in fsck' '\n \ttest_when_finished \"mv .git/index.backup .git/index\" &&\n \tcorrupt_index_checksum &&\n \ttest_must_fail git fsck --cache 2>errors &&\n-\tgrep \"bad index file\" errors\n+\ttest_i18ngrep \"bad index file\" errors\n '\n \n test_done\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362849","messageId":"20181110051615.8641-8-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 07/16] read-cache.c: add missing colon separators","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:06Z","receivedAt":"2018-11-10T05:41:43Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"typechange_fmt and added_fmt should have a colon before \"needs\nupdate\". Align the statements to make it easier to read and see. Also\ndrop the unnecessary ().\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n read-cache.c | 10 +++++-----\n 1 file changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/read-cache.c b/read-cache.c\nindex 858befe738..8d99ae376c 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -1492,11 +1492,11 @@ int refresh_index(struct index_state *istate, unsigned int flags,\n \t\t\t\t\t\t  istate->cache_nr);\n \n \ttrace_performance_enter();\n-\tmodified_fmt = (in_porcelain ? \"M\\t%s\\n\" : \"%s: needs update\\n\");\n-\tdeleted_fmt = (in_porcelain ? \"D\\t%s\\n\" : \"%s: needs update\\n\");\n-\ttypechange_fmt = (in_porcelain ? \"T\\t%s\\n\" : \"%s needs update\\n\");\n-\tadded_fmt = (in_porcelain ? \"A\\t%s\\n\" : \"%s needs update\\n\");\n-\tunmerged_fmt = (in_porcelain ? \"U\\t%s\\n\" : \"%s: needs merge\\n\");\n+\tmodified_fmt   = in_porcelain ? \"M\\t%s\\n\" : \"%s: needs update\\n\";\n+\tdeleted_fmt    = in_porcelain ? \"D\\t%s\\n\" : \"%s: needs update\\n\";\n+\ttypechange_fmt = in_porcelain ? \"T\\t%s\\n\" : \"%s: needs update\\n\";\n+\tadded_fmt      = in_porcelain ? \"A\\t%s\\n\" : \"%s: needs update\\n\";\n+\tunmerged_fmt   = in_porcelain ? \"U\\t%s\\n\" : \"%s: needs merge\\n\";\n \tfor (i = 0; i < istate->cache_nr; i++) {\n \t\tstruct cache_entry *ce, *new_entry;\n \t\tint cache_errno = 0;\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362850","messageId":"20181110051615.8641-15-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 14/16] parse-options.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:13Z","receivedAt":"2018-11-10T05:41:51Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"One error is updated to start with lowercase to be consistent with the\nrest.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n parse-options.c          | 14 +++++++-------\n t/t0040-parse-options.sh |  4 ++--\n 2 files changed, 9 insertions(+), 9 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex 3f5f985c1e..86aad2e185 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -319,8 +319,8 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,\n \t}\n \n \tif (ambiguous_option) {\n-\t\terror(\"Ambiguous option: %s \"\n-\t\t\t\"(could be --%s%s or --%s%s)\",\n+\t\terror(_(\"ambiguous option: %s \"\n+\t\t\t\"(could be --%s%s or --%s%s)\"),\n \t\t\targ,\n \t\t\t(ambiguous_flags & OPT_UNSET) ?  \"no-\" : \"\",\n \t\t\tambiguous_option->long_name,\n@@ -353,7 +353,7 @@ static void check_typos(const char *arg, const struct option *options)\n \t\treturn;\n \n \tif (starts_with(arg, \"no-\")) {\n-\t\terror (\"did you mean `--%s` (with two dashes ?)\", arg);\n+\t\terror(_(\"did you mean `--%s` (with two dashes ?)\"), arg);\n \t\texit(129);\n \t}\n \n@@ -361,7 +361,7 @@ static void check_typos(const char *arg, const struct option *options)\n \t\tif (!options->long_name)\n \t\t\tcontinue;\n \t\tif (starts_with(options->long_name, arg)) {\n-\t\t\terror (\"did you mean `--%s` (with two dashes ?)\", arg);\n+\t\t\terror(_(\"did you mean `--%s` (with two dashes ?)\"), arg);\n \t\t\texit(129);\n \t\t}\n \t}\n@@ -644,11 +644,11 @@ int parse_options(int argc, const char **argv, const char *prefix,\n \t\tbreak;\n \tdefault: /* PARSE_OPT_UNKNOWN */\n \t\tif (ctx.argv[0][1] == '-') {\n-\t\t\terror(\"unknown option `%s'\", ctx.argv[0] + 2);\n+\t\t\terror(_(\"unknown option `%s'\"), ctx.argv[0] + 2);\n \t\t} else if (isascii(*ctx.opt)) {\n-\t\t\terror(\"unknown switch `%c'\", *ctx.opt);\n+\t\t\terror(_(\"unknown switch `%c'\"), *ctx.opt);\n \t\t} else {\n-\t\t\terror(\"unknown non-ascii option in string: `%s'\",\n+\t\t\terror(_(\"unknown non-ascii option in string: `%s'\"),\n \t\t\t      ctx.argv[0]);\n \t\t}\n \t\tusage_with_options(usagestr, options);\ndiff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh\nindex 17d0c18feb..e46b1e02f0 100755\n--- a/t/t0040-parse-options.sh\n+++ b/t/t0040-parse-options.sh\n@@ -228,7 +228,7 @@ EOF\n test_expect_success 'detect possible typos' '\n \ttest_must_fail test-tool parse-options -boolean >output 2>output.err &&\n \ttest_must_be_empty output &&\n-\ttest_cmp typo.err output.err\n+\ttest_i18ncmp typo.err output.err\n '\n \n cat >typo.err <<\\EOF\n@@ -238,7 +238,7 @@ EOF\n test_expect_success 'detect possible typos' '\n \ttest_must_fail test-tool parse-options -ambiguous >output 2>output.err &&\n \ttest_must_be_empty output &&\n-\ttest_cmp typo.err output.err\n+\ttest_i18ncmp typo.err output.err\n '\n \n test_expect_success 'keep some options as arguments' '\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362851","messageId":"20181110051615.8641-2-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 01/16] git.c: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:00Z","receivedAt":"2018-11-10T05:43:07Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"One string is slightly updated to keep consistency with the rest:\ndie() should begin with lowercase.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n git.c | 30 +++++++++++++++---------------\n 1 file changed, 15 insertions(+), 15 deletions(-)\n\ndiff --git a/git.c b/git.c\nindex adac132956..5fd30da093 100644\n--- a/git.c\n+++ b/git.c\n@@ -338,27 +338,27 @@ static int handle_alias(int *argcp, const char ***argv)\n \t\t\tif (ret >= 0)   /* normal exit */\n \t\t\t\texit(ret);\n \n-\t\t\tdie_errno(\"while expanding alias '%s': '%s'\",\n-\t\t\t    alias_command, alias_string + 1);\n+\t\t\tdie_errno(_(\"while expanding alias '%s': '%s'\"),\n+\t\t\t\t  alias_command, alias_string + 1);\n \t\t}\n \t\tcount = split_cmdline(alias_string, &new_argv);\n \t\tif (count < 0)\n-\t\t\tdie(\"Bad alias.%s string: %s\", alias_command,\n+\t\t\tdie(_(\"bad alias.%s string: %s\"), alias_command,\n \t\t\t    split_cmdline_strerror(count));\n \t\toption_count = handle_options(&new_argv, &count, &envchanged);\n \t\tif (envchanged)\n-\t\t\tdie(\"alias '%s' changes environment variables.\\n\"\n-\t\t\t\t \"You can use '!git' in the alias to do this\",\n-\t\t\t\t alias_command);\n+\t\t\tdie(_(\"alias '%s' changes environment variables.\\n\"\n+\t\t\t      \"You can use '!git' in the alias to do this\"),\n+\t\t\t    alias_command);\n \t\tmemmove(new_argv - option_count, new_argv,\n \t\t\t\tcount * sizeof(char *));\n \t\tnew_argv -= option_count;\n \n \t\tif (count < 1)\n-\t\t\tdie(\"empty alias for %s\", alias_command);\n+\t\t\tdie(_(\"empty alias for %s\"), alias_command);\n \n \t\tif (!strcmp(alias_command, new_argv[0]))\n-\t\t\tdie(\"recursive alias: %s\", alias_command);\n+\t\t\tdie(_(\"recursive alias: %s\"), alias_command);\n \n \t\ttrace_argv_printf(new_argv,\n \t\t\t\t  \"trace: alias expansion: %s =>\",\n@@ -409,7 +409,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n \n \tif (!help && get_super_prefix()) {\n \t\tif (!(p->option & SUPPORT_SUPER_PREFIX))\n-\t\t\tdie(\"%s doesn't support --super-prefix\", p->cmd);\n+\t\t\tdie(_(\"%s doesn't support --super-prefix\"), p->cmd);\n \t}\n \n \tif (!help && p->option & NEED_WORK_TREE)\n@@ -433,11 +433,11 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n \n \t/* Check for ENOSPC and EIO errors.. */\n \tif (fflush(stdout))\n-\t\tdie_errno(\"write failure on standard output\");\n+\t\tdie_errno(_(\"write failure on standard output\"));\n \tif (ferror(stdout))\n-\t\tdie(\"unknown write failure on standard output\");\n+\t\tdie(_(\"unknown write failure on standard output\"));\n \tif (fclose(stdout))\n-\t\tdie_errno(\"close failed on standard output\");\n+\t\tdie_errno(_(\"close failed on standard output\"));\n \treturn 0;\n }\n \n@@ -648,7 +648,7 @@ static void execv_dashed_external(const char **argv)\n \tint status;\n \n \tif (get_super_prefix())\n-\t\tdie(\"%s doesn't support --super-prefix\", argv[0]);\n+\t\tdie(_(\"%s doesn't support --super-prefix\"), argv[0]);\n \n \tif (use_pager == -1 && !is_builtin(argv[0]))\n \t\tuse_pager = check_pager_config(argv[0]);\n@@ -760,7 +760,7 @@ int cmd_main(int argc, const char **argv)\n \tif (skip_prefix(cmd, \"git-\", &cmd)) {\n \t\targv[0] = cmd;\n \t\thandle_builtin(argc, argv);\n-\t\tdie(\"cannot handle %s as a builtin\", cmd);\n+\t\tdie(_(\"cannot handle %s as a builtin\"), cmd);\n \t}\n \n \t/* Look for flags.. */\n@@ -773,7 +773,7 @@ int cmd_main(int argc, const char **argv)\n \t} else {\n \t\t/* The user didn't specify a command; give them help */\n \t\tcommit_pager_choice();\n-\t\tprintf(\"usage: %s\\n\\n\", git_usage_string);\n+\t\tprintf(_(\"usage: %s\\n\\n\"), git_usage_string);\n \t\tlist_common_cmds_help();\n \t\tprintf(\"\\n%s\\n\", _(git_more_info_string));\n \t\texit(1);\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362852","messageId":"20181110051615.8641-10-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 09/16] remote.c: turn some error() or die() to BUG()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:08Z","receivedAt":"2018-11-10T05:43:19Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The first error, \"internal error\", is clearly a BUG(). The second two\nare meant to catch calls with invalid parameters and should never\nhappen outside the test suite.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n remote.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex 81f4f01b00..257630ff21 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -620,7 +620,7 @@ static void handle_duplicate(struct ref *ref1, struct ref *ref2)\n \t\t\t * FETCH_HEAD_IGNORE entries always appear at\n \t\t\t * the end of the list.\n \t\t\t */\n-\t\t\tdie(_(\"Internal error\"));\n+\t\t\tBUG(\"Internal error\");\n \t\t}\n \t}\n \tfree(ref2->peer_ref);\n@@ -707,7 +707,7 @@ static void query_refspecs_multiple(struct refspec *rs,\n \tint find_src = !query->src;\n \n \tif (find_src && !query->dst)\n-\t\terror(\"query_refspecs_multiple: need either src or dst\");\n+\t\tBUG(\"query_refspecs_multiple: need either src or dst\");\n \n \tfor (i = 0; i < rs->nr; i++) {\n \t\tstruct refspec_item *refspec = &rs->items[i];\n@@ -735,7 +735,7 @@ int query_refspecs(struct refspec *rs, struct refspec_item *query)\n \tchar **result = find_src ? &query->src : &query->dst;\n \n \tif (find_src && !query->dst)\n-\t\treturn error(\"query_refspecs: need either src or dst\");\n+\t\tBUG(\"query_refspecs: need either src or dst\");\n \n \tfor (i = 0; i < rs->nr; i++) {\n \t\tstruct refspec_item *refspec = &rs->items[i];\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362853","messageId":"20181110051615.8641-6-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 05/16] read-cache.c: turn die(\"internal error\") to BUG()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:04Z","receivedAt":"2018-11-10T05:43:24Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n read-cache.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/read-cache.c b/read-cache.c\nindex d57958233e..0c37f4885e 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -316,7 +316,7 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)\n \t\t\tchanged |= DATA_CHANGED;\n \t\treturn changed;\n \tdefault:\n-\t\tdie(\"internal error: ce_mode is %o\", ce->ce_mode);\n+\t\tBUG(\"unsupported ce_mode: %o\", ce->ce_mode);\n \t}\n \n \tchanged |= match_stat_data(&ce->ce_stat_data, st);\n@@ -2356,14 +2356,14 @@ void validate_cache_entries(const struct index_state *istate)\n \n \tfor (i = 0; i < istate->cache_nr; i++) {\n \t\tif (!istate) {\n-\t\t\tdie(\"internal error: cache entry is not allocated from expected memory pool\");\n+\t\t\tBUG(\"cache entry is not allocated from expected memory pool\");\n \t\t} else if (!istate->ce_mem_pool ||\n \t\t\t!mem_pool_contains(istate->ce_mem_pool, istate->cache[i])) {\n \t\t\tif (!istate->split_index ||\n \t\t\t\t!istate->split_index->base ||\n \t\t\t\t!istate->split_index->base->ce_mem_pool ||\n \t\t\t\t!mem_pool_contains(istate->split_index->base->ce_mem_pool, istate->cache[i])) {\n-\t\t\t\tdie(\"internal error: cache entry is not allocated from expected memory pool\");\n+\t\t\t\tBUG(\"cache entry is not allocated from expected memory pool\");\n \t\t\t}\n \t\t}\n \t}\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362854","messageId":"20181110051615.8641-13-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 12/16] parse-options: replace opterror() with optname()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:11Z","receivedAt":"2018-11-10T05:43:25Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Introduce optname() that does the early half of original opterror() to\ncome up with the name of the option reported back to the user, and use\nit to kill opterror().  The callers of opterror() now directly call\nerror() using the string returned by opterror() instead.\n\nThere are a few issues with opterror()\n\n- it tries to assemble an English sentence from pieces. This is not\n  great for translators because we give them pieces instead of a full\n  sentence.\n\n- It's a wrapper around error() and needs some hack to let the\n  compiler know it always returns -1.\n\n- Since it takes a string instead of printf format, one call site has\n  to assemble the string manually before passing to it.\n\nUsing error() directly solves the second and third problems.\n\nIt kind helps the first problem as well because \"%s does foo\" does\ngive a translator a full sentence in a sense and let them reorder if\nneeded. But it has limitations, if the subject part has to change\nbased on the rest of the sentence, that language is screwed. This is\nalso why I try to avoid calling optname() when 'flags' is known in\nadvance.\n\nMark of these strings for translation as well while at there.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/merge.c     |  2 +-\n builtin/revert.c    |  3 ++-\n parse-options-cb.c  |  7 ++++---\n parse-options.c     | 46 +++++++++++++++++++++++++--------------------\n parse-options.h     |  5 +----\n ref-filter.c        |  8 +++++---\n t/t4211-line-log.sh |  2 +-\n 7 files changed, 40 insertions(+), 33 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 92ba7e1c6d..82248d43c3 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -128,7 +128,7 @@ static int option_read_message(struct parse_opt_ctx_t *ctx,\n \t\tctx->argc--;\n \t\targ = *++ctx->argv;\n \t} else\n-\t\treturn opterror(opt, \"requires a value\", 0);\n+\t\treturn error(_(\"option `%s' requires a value\"), opt->long_name);\n \n \tif (buf->len)\n \t\tstrbuf_addch(buf, '\\n');\ndiff --git a/builtin/revert.c b/builtin/revert.c\nindex c93393c89b..11190d2ab4 100644\n--- a/builtin/revert.c\n+++ b/builtin/revert.c\n@@ -69,7 +69,8 @@ static int option_parse_m(const struct option *opt,\n \n \treplay->mainline = strtol(arg, &end, 10);\n \tif (*end || replay->mainline <= 0)\n-\t\treturn opterror(opt, \"expects a number greater than zero\", 0);\n+\t\treturn error(_(\"option `%s' expects a number greater than zero\"),\n+\t\t\t     opt->long_name);\n \n \treturn 0;\n }\ndiff --git a/parse-options-cb.c b/parse-options-cb.c\nindex e8236534ac..813eb6301b 100644\n--- a/parse-options-cb.c\n+++ b/parse-options-cb.c\n@@ -18,7 +18,8 @@ int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)\n \t} else {\n \t\tv = strtol(arg, (char **)&arg, 10);\n \t\tif (*arg)\n-\t\t\treturn opterror(opt, \"expects a numerical value\", 0);\n+\t\t\treturn error(_(\"option `%s' expects a numerical value\"),\n+\t\t\t\t     opt->long_name);\n \t\tif (v && v < MINIMUM_ABBREV)\n \t\t\tv = MINIMUM_ABBREV;\n \t\telse if (v > 40)\n@@ -54,8 +55,8 @@ int parse_opt_color_flag_cb(const struct option *opt, const char *arg,\n \t\targ = unset ? \"never\" : (const char *)opt->defval;\n \tvalue = git_config_colorbool(NULL, arg);\n \tif (value < 0)\n-\t\treturn opterror(opt,\n-\t\t\t\"expects \\\"always\\\", \\\"auto\\\", or \\\"never\\\"\", 0);\n+\t\treturn error(_(\"option `%s' expects \\\"always\\\", \\\"auto\\\", or \\\"never\\\"\"),\n+\t\t\t     opt->long_name);\n \t*(int *)opt->value = value;\n \treturn 0;\n }\ndiff --git a/parse-options.c b/parse-options.c\nindex 3b874a83a0..0bf817193d 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -32,7 +32,7 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,\n \t\tp->argc--;\n \t\t*arg = *++p->argv;\n \t} else\n-\t\treturn opterror(opt, \"requires a value\", flags);\n+\t\treturn error(_(\"%s requires a value\"), optname(opt, flags));\n \treturn 0;\n }\n \n@@ -49,7 +49,6 @@ static int opt_command_mode_error(const struct option *opt,\n \t\t\t\t  int flags)\n {\n \tconst struct option *that;\n-\tstruct strbuf message = STRBUF_INIT;\n \tstruct strbuf that_name = STRBUF_INIT;\n \n \t/*\n@@ -67,13 +66,13 @@ static int opt_command_mode_error(const struct option *opt,\n \t\t\tstrbuf_addf(&that_name, \"--%s\", that->long_name);\n \t\telse\n \t\t\tstrbuf_addf(&that_name, \"-%c\", that->short_name);\n-\t\tstrbuf_addf(&message, \": incompatible with %s\", that_name.buf);\n+\t\terror(_(\"%s is incompatible with %s\"),\n+\t\t      optname(opt, flags), that_name.buf);\n \t\tstrbuf_release(&that_name);\n-\t\topterror(opt, message.buf, flags);\n-\t\tstrbuf_release(&message);\n \t\treturn -1;\n \t}\n-\treturn opterror(opt, \": incompatible with something else\", flags);\n+\treturn error(_(\"%s : incompatible with something else\"),\n+\t\t     optname(opt, flags));\n }\n \n static int get_value(struct parse_opt_ctx_t *p,\n@@ -86,11 +85,11 @@ static int get_value(struct parse_opt_ctx_t *p,\n \tint err;\n \n \tif (unset && p->opt)\n-\t\treturn opterror(opt, \"takes no value\", flags);\n+\t\treturn error(_(\"%s takes no value\"), optname(opt, flags));\n \tif (unset && (opt->flags & PARSE_OPT_NONEG))\n-\t\treturn opterror(opt, \"isn't available\", flags);\n+\t\treturn error(_(\"%s isn't available\"), optname(opt, flags));\n \tif (!(flags & OPT_SHORT) && p->opt && (opt->flags & PARSE_OPT_NOARG))\n-\t\treturn opterror(opt, \"takes no value\", flags);\n+\t\treturn error(_(\"%s takes no value\"), optname(opt, flags));\n \n \tswitch (opt->type) {\n \tcase OPTION_LOWLEVEL_CALLBACK:\n@@ -176,7 +175,8 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\t\treturn -1;\n \t\t*(int *)opt->value = strtol(arg, (char **)&s, 10);\n \t\tif (*s)\n-\t\t\treturn opterror(opt, \"expects a numerical value\", flags);\n+\t\t\treturn error(_(\"%s expects a numerical value\"),\n+\t\t\t\t     optname(opt, flags));\n \t\treturn 0;\n \n \tcase OPTION_MAGNITUDE:\n@@ -191,9 +191,9 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\tif (get_arg(p, opt, flags, &arg))\n \t\t\treturn -1;\n \t\tif (!git_parse_ulong(arg, opt->value))\n-\t\t\treturn opterror(opt,\n-\t\t\t\t\"expects a non-negative integer value with an optional k/m/g suffix\",\n-\t\t\t\tflags);\n+\t\t\treturn error(_(\"%s expects a non-negative integer value\"\n+\t\t\t\t       \" with an optional k/m/g suffix\"),\n+\t\t\t\t     optname(opt, flags));\n \t\treturn 0;\n \n \tdefault:\n@@ -257,7 +257,8 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,\n \t\t\tif (!rest)\n \t\t\t\tcontinue;\n \t\t\tif (*rest == '=')\n-\t\t\t\treturn opterror(options, \"takes no value\", flags);\n+\t\t\t\treturn error(_(\"%s takes no value\"),\n+\t\t\t\t\t     optname(options, flags));\n \t\t\tif (*rest)\n \t\t\t\tcontinue;\n \t\t\tp->out[p->cpidx++] = arg - 2;\n@@ -773,12 +774,17 @@ void NORETURN usage_msg_opt(const char *msg,\n \tusage_with_options(usagestr, options);\n }\n \n-#undef opterror\n-int opterror(const struct option *opt, const char *reason, int flags)\n+const char *optname(const struct option *opt, int flags)\n {\n+\tstatic struct strbuf sb = STRBUF_INIT;\n+\n+\tstrbuf_reset(&sb);\n \tif (flags & OPT_SHORT)\n-\t\treturn error(\"switch `%c' %s\", opt->short_name, reason);\n-\tif (flags & OPT_UNSET)\n-\t\treturn error(\"option `no-%s' %s\", opt->long_name, reason);\n-\treturn error(\"option `%s' %s\", opt->long_name, reason);\n+\t\tstrbuf_addf(&sb, \"switch `%c'\", opt->short_name);\n+\telse if (flags & OPT_UNSET)\n+\t\tstrbuf_addf(&sb, \"option `no-%s'\", opt->long_name);\n+\telse\n+\t\tstrbuf_addf(&sb, \"option `%s'\", opt->long_name);\n+\n+\treturn sb.buf;\n }\ndiff --git a/parse-options.h b/parse-options.h\nindex dd14911a29..2e146aa6fa 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -189,10 +189,7 @@ extern NORETURN void usage_msg_opt(const char *msg,\n \t\t\t\t   const struct option *options);\n \n extern int optbug(const struct option *opt, const char *reason);\n-extern int opterror(const struct option *opt, const char *reason, int flags);\n-#if defined(__GNUC__)\n-#define opterror(o,r,f) (opterror((o),(r),(f)), const_error())\n-#endif\n+const char *optname(const struct option *opt, int flags);\n \n /*----- incremental advanced APIs -----*/\n \ndiff --git a/ref-filter.c b/ref-filter.c\nindex 2a05619211..0681359100 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -2302,9 +2302,11 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n \n \tif (rf->merge) {\n \t\tif (no_merged) {\n-\t\t\treturn opterror(opt, \"is incompatible with --merged\", 0);\n+\t\t\treturn error(_(\"option `%s' is incompatible with --merged\"),\n+\t\t\t\t     opt->long_name);\n \t\t} else {\n-\t\t\treturn opterror(opt, \"is incompatible with --no-merged\", 0);\n+\t\t\treturn error(_(\"option `%s' is incompatible with --no-merged\"),\n+\t\t\t\t     opt->long_name);\n \t\t}\n \t}\n \n@@ -2318,7 +2320,7 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)\n \trf->merge_commit = lookup_commit_reference_gently(the_repository,\n \t\t\t\t\t\t\t  &oid, 0);\n \tif (!rf->merge_commit)\n-\t\treturn opterror(opt, \"must point to a commit\", 0);\n+\t\treturn error(_(\"option `%s' must point to a commit\"), opt->long_name);\n \n \treturn 0;\n }\ndiff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh\nindex ef1322148e..bd5fe4d148 100755\n--- a/t/t4211-line-log.sh\n+++ b/t/t4211-line-log.sh\n@@ -25,7 +25,7 @@ canned_test_failure () {\n test_bad_opts () {\n \ttest_expect_success \"invalid args: $1\" \"\n \t\ttest_must_fail git log $1 2>errors &&\n-\t\tgrep '$2' errors\n+\t\ttest_i18ngrep '$2' errors\n \t\"\n }\n \n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362855","messageId":"20181110051615.8641-11-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 10/16] remote.c: mark messages for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:09Z","receivedAt":"2018-11-10T05:44:15Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The two strings are slightly modified to be consistent with the rest:\ndie() and error() start with a lowercase.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n remote.c | 43 ++++++++++++++++++++++---------------------\n 1 file changed, 22 insertions(+), 21 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex 257630ff21..11b33d1625 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -359,7 +359,7 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\treturn 0;\n \t/* Handle remote.<name>.* variables */\n \tif (*name == '/') {\n-\t\twarning(\"Config remote shorthand cannot begin with '/': %s\",\n+\t\twarning(_(\"config remote shorthand cannot begin with '/': %s\"),\n \t\t\tname);\n \t\treturn 0;\n \t}\n@@ -406,7 +406,7 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\tif (!remote->receivepack)\n \t\t\tremote->receivepack = v;\n \t\telse\n-\t\t\terror(\"more than one receivepack given, using the first\");\n+\t\t\terror(_(\"more than one receivepack given, using the first\"));\n \t} else if (!strcmp(subkey, \"uploadpack\")) {\n \t\tconst char *v;\n \t\tif (git_config_string(&v, key, value))\n@@ -414,7 +414,7 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\tif (!remote->uploadpack)\n \t\t\tremote->uploadpack = v;\n \t\telse\n-\t\t\terror(\"more than one uploadpack given, using the first\");\n+\t\t\terror(_(\"more than one uploadpack given, using the first\"));\n \t} else if (!strcmp(subkey, \"tagopt\")) {\n \t\tif (!strcmp(value, \"--no-tags\"))\n \t\t\tremote->fetch_tags = -1;\n@@ -680,7 +680,7 @@ static int match_name_with_pattern(const char *key, const char *name,\n \tsize_t namelen;\n \tint ret;\n \tif (!kstar)\n-\t\tdie(\"Key '%s' of pattern had no '*'\", key);\n+\t\tdie(_(\"key '%s' of pattern had no '*'\"), key);\n \tklen = kstar - key;\n \tksuffixlen = strlen(kstar + 1);\n \tnamelen = strlen(name);\n@@ -690,7 +690,7 @@ static int match_name_with_pattern(const char *key, const char *name,\n \t\tstruct strbuf sb = STRBUF_INIT;\n \t\tconst char *vstar = strchr(value, '*');\n \t\tif (!vstar)\n-\t\t\tdie(\"Value '%s' of pattern has no '*'\", value);\n+\t\t\tdie(_(\"value '%s' of pattern has no '*'\"), value);\n \t\tstrbuf_add(&sb, value, vstar - value);\n \t\tstrbuf_add(&sb, name + klen, namelen - klen - ksuffixlen);\n \t\tstrbuf_addstr(&sb, vstar + 1);\n@@ -995,12 +995,12 @@ static int match_explicit_lhs(struct ref *src,\n \t\t * way to delete 'other' ref at the remote end.\n \t\t */\n \t\tif (try_explicit_object_name(rs->src, match) < 0)\n-\t\t\treturn error(\"src refspec %s does not match any.\", rs->src);\n+\t\t\treturn error(_(\"src refspec %s does not match any\"), rs->src);\n \t\tif (allocated_match)\n \t\t\t*allocated_match = 1;\n \t\treturn 0;\n \tdefault:\n-\t\treturn error(\"src refspec %s matches more than one.\", rs->src);\n+\t\treturn error(_(\"src refspec %s matches more than one\"), rs->src);\n \t}\n }\n \n@@ -1030,7 +1030,7 @@ static int match_explicit(struct ref *src, struct ref *dst,\n \t\tif (!dst_value ||\n \t\t    ((flag & REF_ISSYMREF) &&\n \t\t     !starts_with(dst_value, \"refs/heads/\")))\n-\t\t\tdie(\"%s cannot be resolved to branch.\",\n+\t\t\tdie(_(\"%s cannot be resolved to branch\"),\n \t\t\t    matched_src->name);\n \t}\n \n@@ -1041,30 +1041,30 @@ static int match_explicit(struct ref *src, struct ref *dst,\n \t\tif (starts_with(dst_value, \"refs/\"))\n \t\t\tmatched_dst = make_linked_ref(dst_value, dst_tail);\n \t\telse if (is_null_oid(&matched_src->new_oid))\n-\t\t\terror(\"unable to delete '%s': remote ref does not exist\",\n+\t\t\terror(_(\"unable to delete '%s': remote ref does not exist\"),\n \t\t\t      dst_value);\n \t\telse if ((dst_guess = guess_ref(dst_value, matched_src))) {\n \t\t\tmatched_dst = make_linked_ref(dst_guess, dst_tail);\n \t\t\tfree(dst_guess);\n \t\t} else\n-\t\t\terror(\"unable to push to unqualified destination: %s\\n\"\n-\t\t\t      \"The destination refspec neither matches an \"\n-\t\t\t      \"existing ref on the remote nor\\n\"\n-\t\t\t      \"begins with refs/, and we are unable to \"\n-\t\t\t      \"guess a prefix based on the source ref.\",\n+\t\t\terror(_(\"unable to push to unqualified destination: %s\\n\"\n+\t\t\t\t\"The destination refspec neither matches an \"\n+\t\t\t\t\"existing ref on the remote nor\\n\"\n+\t\t\t\t\"begins with refs/, and we are unable to \"\n+\t\t\t\t\"guess a prefix based on the source ref.\"),\n \t\t\t      dst_value);\n \t\tbreak;\n \tdefault:\n \t\tmatched_dst = NULL;\n-\t\terror(\"dst refspec %s matches more than one.\",\n+\t\terror(_(\"dst refspec %s matches more than one\"),\n \t\t      dst_value);\n \t\tbreak;\n \t}\n \tif (!matched_dst)\n \t\treturn -1;\n \tif (matched_dst->peer_ref)\n-\t\treturn error(\"dst ref %s receives from more than one src.\",\n-\t\t      matched_dst->name);\n+\t\treturn error(_(\"dst ref %s receives from more than one src\"),\n+\t\t\t     matched_dst->name);\n \telse {\n \t\tmatched_dst->peer_ref = allocated_src ?\n \t\t\t\t\tmatched_src :\n@@ -1750,7 +1750,7 @@ int get_fetch_map(const struct ref *remote_refs,\n \t\t\tref_map = get_remote_ref(remote_refs, name);\n \t\t}\n \t\tif (!missing_ok && !ref_map)\n-\t\t\tdie(\"Couldn't find remote ref %s\", name);\n+\t\t\tdie(_(\"couldn't find remote ref %s\"), name);\n \t\tif (ref_map) {\n \t\t\tref_map->peer_ref = get_local_ref(refspec->dst);\n \t\t\tif (ref_map->peer_ref && refspec->force)\n@@ -1763,7 +1763,7 @@ int get_fetch_map(const struct ref *remote_refs,\n \t\t\tif (!starts_with((*rmp)->peer_ref->name, \"refs/\") ||\n \t\t\t    check_refname_format((*rmp)->peer_ref->name, 0)) {\n \t\t\t\tstruct ref *ignore = *rmp;\n-\t\t\t\terror(\"* Ignoring funny ref '%s' locally\",\n+\t\t\t\terror(_(\"* Ignoring funny ref '%s' locally\"),\n \t\t\t\t      (*rmp)->peer_ref->name);\n \t\t\t\t*rmp = (*rmp)->next;\n \t\t\t\tfree(ignore->peer_ref);\n@@ -1858,7 +1858,7 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,\n \trepo_init_revisions(the_repository, &revs, NULL);\n \tsetup_revisions(argv.argc, argv.argv, &revs, NULL);\n \tif (prepare_revision_walk(&revs))\n-\t\tdie(\"revision walk setup failed\");\n+\t\tdie(_(\"revision walk setup failed\"));\n \n \t/* ... and count the commits on each side. */\n \twhile (1) {\n@@ -2131,7 +2131,8 @@ static int parse_push_cas_option(struct push_cas_option *cas, const char *arg, i\n \telse if (!colon[1])\n \t\toidclr(&entry->expect);\n \telse if (get_oid(colon + 1, &entry->expect))\n-\t\treturn error(\"cannot parse expected object name '%s'\", colon + 1);\n+\t\treturn error(_(\"cannot parse expected object name '%s'\"),\n+\t\t\t     colon + 1);\n \treturn 0;\n }\n \n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362856","messageId":"20181110051615.8641-16-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 15/16] fsck: reduce word legos to help i18n","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:14Z","receivedAt":"2018-11-10T05:46:17Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"These messages will be marked for translation later. Reduce word legos\nand give translators almost full phrases. describe_object() is updated\nso that it can be called from printf() twice.\n\nWhile at there, remove \\n from the strings to reduce a bit of work\nfrom translators.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/fsck.c | 65 +++++++++++++++++++++++++++++++-------------------\n 1 file changed, 40 insertions(+), 25 deletions(-)\n\ndiff --git a/builtin/fsck.c b/builtin/fsck.c\nindex 06eb421720..1feb6142f4 100644\n--- a/builtin/fsck.c\n+++ b/builtin/fsck.c\n@@ -52,16 +52,24 @@ static int name_objects;\n \n static const char *describe_object(struct object *obj)\n {\n-\tstatic struct strbuf buf = STRBUF_INIT;\n-\tchar *name = name_objects ?\n-\t\tlookup_decoration(fsck_walk_options.object_names, obj) : NULL;\n+\tstatic struct strbuf bufs[] = {\n+\t\tSTRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT\n+\t};\n+\tstatic int b = 0;\n+\tstruct strbuf *buf;\n+\tchar *name = NULL;\n \n-\tstrbuf_reset(&buf);\n-\tstrbuf_addstr(&buf, oid_to_hex(&obj->oid));\n+\tif (name_objects)\n+\t\tname = lookup_decoration(fsck_walk_options.object_names, obj);\n+\n+\tbuf = bufs + b;\n+\tb = (b + 1) % ARRAY_SIZE(bufs);\n+\tstrbuf_reset(buf);\n+\tstrbuf_addstr(buf, oid_to_hex(&obj->oid));\n \tif (name)\n-\t\tstrbuf_addf(&buf, \" (%s)\", name);\n+\t\tstrbuf_addf(buf, \" (%s)\", name);\n \n-\treturn buf.buf;\n+\treturn buf->buf;\n }\n \n static const char *printable_type(struct object *obj)\n@@ -105,25 +113,29 @@ static int fsck_config(const char *var, const char *value, void *cb)\n \treturn git_default_config(var, value, cb);\n }\n \n-static void objreport(struct object *obj, const char *msg_type,\n-\t\t\tconst char *err)\n-{\n-\tfprintf(stderr, \"%s in %s %s: %s\\n\",\n-\t\tmsg_type, printable_type(obj), describe_object(obj), err);\n-}\n-\n static int objerror(struct object *obj, const char *err)\n {\n \terrors_found |= ERROR_OBJECT;\n-\tobjreport(obj, \"error\", err);\n+\tfprintf_ln(stderr, \"error in %s %s: %s\",\n+\t\t   printable_type(obj), describe_object(obj), err);\n \treturn -1;\n }\n \n static int fsck_error_func(struct fsck_options *o,\n \tstruct object *obj, int type, const char *message)\n {\n-\tobjreport(obj, (type == FSCK_WARN) ? \"warning\" : \"error\", message);\n-\treturn (type == FSCK_WARN) ? 0 : 1;\n+\tswitch (type) {\n+\tcase FSCK_WARN:\n+\t\tfprintf_ln(stderr, \"warning in %s %s: %s\",\n+\t\t\t   printable_type(obj), describe_object(obj), message);\n+\t\treturn 0;\n+\tcase FSCK_ERROR:\n+\t\tfprintf_ln(stderr, \"error in %s %s: %s\",\n+\t\t\t   printable_type(obj), describe_object(obj), message);\n+\t\treturn 1;\n+\tdefault:\n+\t\tBUG(\"%d (FSCK_IGNORE?) should never trigger this callback\", type);\n+\t}\n }\n \n static struct object_array pending;\n@@ -165,10 +177,12 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt\n \n \tif (!(obj->flags & HAS_OBJ)) {\n \t\tif (parent && !has_object_file(&obj->oid)) {\n-\t\t\tprintf(\"broken link from %7s %s\\n\",\n-\t\t\t\t printable_type(parent), describe_object(parent));\n-\t\t\tprintf(\"              to %7s %s\\n\",\n-\t\t\t\t printable_type(obj), describe_object(obj));\n+\t\t\tprintf_ln(\"broken link from %7s %s\\n\"\n+\t\t\t\t  \"              to %7s %s\",\n+\t\t\t\t  printable_type(parent),\n+\t\t\t\t  describe_object(parent),\n+\t\t\t\t  printable_type(obj),\n+\t\t\t\t  describe_object(obj));\n \t\t\terrors_found |= ERROR_REACHABLE;\n \t\t}\n \t\treturn 1;\n@@ -371,10 +385,11 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)\n \t\tstruct tag *tag = (struct tag *) obj;\n \n \t\tif (show_tags && tag->tagged) {\n-\t\t\tprintf(\"tagged %s %s\", printable_type(tag->tagged),\n-\t\t\t\tdescribe_object(tag->tagged));\n-\t\t\tprintf(\" (%s) in %s\\n\", tag->tag,\n-\t\t\t\tdescribe_object(&tag->object));\n+\t\t\tprintf_ln(\"tagged %s %s (%s) in %s\",\n+\t\t\t\t  printable_type(tag->tagged),\n+\t\t\t\t  describe_object(tag->tagged),\n+\t\t\t\t  tag->tag,\n+\t\t\t\t  describe_object(&tag->object));\n \t\t}\n \t}\n \n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362862","messageId":"20181110051615.8641-14-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 13/16] parse-options.c: turn some die() to BUG()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:12Z","receivedAt":"2018-11-10T05:47:06Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"These two strings are clearly not for the user to see. Reduce the\nviolence in one string while at there.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n parse-options.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex 0bf817193d..3f5f985c1e 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -197,7 +197,7 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\treturn 0;\n \n \tdefault:\n-\t\tdie(\"should not happen, someone must be hit on the forehead\");\n+\t\tBUG(\"opt->type %d should not happen\", opt->type);\n \t}\n }\n \n@@ -424,7 +424,7 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,\n \tctx->flags = flags;\n \tif ((flags & PARSE_OPT_KEEP_UNKNOWN) &&\n \t    (flags & PARSE_OPT_STOP_AT_NON_OPTION))\n-\t\tdie(\"STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together\");\n+\t\tBUG(\"STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together\");\n \tparse_options_check(options);\n }\n \n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362863","messageId":"20181110051615.8641-12-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 11/16] repack: mark more strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:10Z","receivedAt":"2018-11-10T05:47:28Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Two strings are slightly updated to be consistent with the rest: die()\nstarts with lowercase.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/repack.c | 26 +++++++++++++-------------\n 1 file changed, 13 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/repack.c b/builtin/repack.c\nindex c6a7943d5c..721f947218 100644\n--- a/builtin/repack.c\n+++ b/builtin/repack.c\n@@ -197,7 +197,7 @@ static int write_oid(const struct object_id *oid, struct packed_git *pack,\n \n \tif (cmd->in == -1) {\n \t\tif (start_command(cmd))\n-\t\t\tdie(\"Could not start pack-objects to repack promisor objects\");\n+\t\t\tdie(_(\"could not start pack-objects to repack promisor objects\"));\n \t}\n \n \txwrite(cmd->in, oid_to_hex(oid), GIT_SHA1_HEXSZ);\n@@ -236,7 +236,7 @@ static void repack_promisor_objects(const struct pack_objects_args *args,\n \t\tchar *promisor_name;\n \t\tint fd;\n \t\tif (line.len != 40)\n-\t\t\tdie(\"repack: Expecting 40 character sha1 lines only from pack-objects.\");\n+\t\t\tdie(_(\"repack: Expecting 40 character sha1 lines only from pack-objects.\"));\n \t\tstring_list_append(names, line.buf);\n \n \t\t/*\n@@ -247,13 +247,13 @@ static void repack_promisor_objects(const struct pack_objects_args *args,\n \t\t\t\t\t  line.buf);\n \t\tfd = open(promisor_name, O_CREAT|O_EXCL|O_WRONLY, 0600);\n \t\tif (fd < 0)\n-\t\t\tdie_errno(\"unable to create '%s'\", promisor_name);\n+\t\t\tdie_errno(_(\"unable to create '%s'\"), promisor_name);\n \t\tclose(fd);\n \t\tfree(promisor_name);\n \t}\n \tfclose(out);\n \tif (finish_command(&cmd))\n-\t\tdie(\"Could not finish pack-objects to repack promisor objects\");\n+\t\tdie(_(\"could not finish pack-objects to repack promisor objects\"));\n }\n \n #define ALL_INTO_ONE 1\n@@ -408,7 +408,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \tout = xfdopen(cmd.out, \"r\");\n \twhile (strbuf_getline_lf(&line, out) != EOF) {\n \t\tif (line.len != 40)\n-\t\t\tdie(\"repack: Expecting 40 character sha1 lines only from pack-objects.\");\n+\t\t\tdie(_(\"repack: Expecting 40 character sha1 lines only from pack-objects\"));\n \t\tstring_list_append(&names, line.buf);\n \t}\n \tfclose(out);\n@@ -417,7 +417,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\treturn ret;\n \n \tif (!names.nr && !po_args.quiet)\n-\t\tprintf(\"Nothing new to pack.\\n\");\n+\t\tprintf_ln(_(\"Nothing new to pack.\"));\n \n \t/*\n \t * Ok we have prepared all new packfiles.\n@@ -477,13 +477,13 @@ int cmd_repack(int argc, const char **argv, const char *prefix)\n \t\tif (rollback_failure.nr) {\n \t\t\tint i;\n \t\t\tfprintf(stderr,\n-\t\t\t\t\"WARNING: Some packs in use have been renamed by\\n\"\n-\t\t\t\t\"WARNING: prefixing old- to their name, in order to\\n\"\n-\t\t\t\t\"WARNING: replace them with the new version of the\\n\"\n-\t\t\t\t\"WARNING: file.  But the operation failed, and the\\n\"\n-\t\t\t\t\"WARNING: attempt to rename them back to their\\n\"\n-\t\t\t\t\"WARNING: original names also failed.\\n\"\n-\t\t\t\t\"WARNING: Please rename them in %s manually:\\n\", packdir);\n+\t\t\t\t_(\"WARNING: Some packs in use have been renamed by\\n\"\n+\t\t\t\t  \"WARNING: prefixing old- to their name, in order to\\n\"\n+\t\t\t\t  \"WARNING: replace them with the new version of the\\n\"\n+\t\t\t\t  \"WARNING: file.  But the operation failed, and the\\n\"\n+\t\t\t\t  \"WARNING: attempt to rename them back to their\\n\"\n+\t\t\t\t  \"WARNING: original names also failed.\\n\"\n+\t\t\t\t  \"WARNING: Please rename them in %s manually:\\n\"), packdir);\n \t\t\tfor (i = 0; i < rollback_failure.nr; i++)\n \t\t\t\tfprintf(stderr, \"WARNING:   old-%s -> %s\\n\",\n \t\t\t\t\trollback_failure.items[i].string,\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362864","messageId":"CACsJy8CM=0Cw1WCamJJe8aapA4-mdr+rMmbjVpYYQCj2++NQbA@mail.gmail.com","threadId":"49702","inReplyTo":"d29c4fcc-0591-fc45-5a5d-65d2874d98a7@ramsayjones.plus.com","subject":"Re: [PATCH v2 12/16] parse-options: replace opterror() with optname()","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T04:55:34Z","receivedAt":"2018-11-10T05:48:08Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Nov 6, 2018 at 3:07 PM Ramsay Jones <ramsay@ramsayjones.plus.com> wrote:\n> Also, this patch does not replace opterror() calls outside of\n> the 'parse-options.c' file with optname(). This tickles my\n> static-check.pl script, since optname() is an external function\n> which is only called from 'parse-options.c'.\n>\n> So, at present, optname() could be marked as a local 'static'\n> symbol. However, I could also imagine it being used by new callers\n> outside of 'parse-options.c' in the future. (maybe) Your call. ;-)\n\nI was making it static, but the compiler complained about undefined\nfunction and I would need to either move optname() up in\nparse-options.c or add a forward declaration (but I was going to\n_remove_ the declaration!)\n\nSince it could be potentially used by Jeff's series (and I think it\ndoes have potential in parse-options-cb.c), I'll just leave it\nexported and caress your static-check.pl script (how did it not catch\noptbug() not being used outside parse-options.c either)?\n-- \nDuy\n"},{"id":"362865","messageId":"20181110051615.8641-9-pclouds@gmail.com","threadId":"49702","inReplyTo":"20181110051615.8641-1-pclouds@gmail.com","subject":"[PATCH v3 08/16] reflog: mark strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T05:16:07Z","receivedAt":"2018-11-10T05:48:51Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"One string \"nothing to delete?\" is rephrased to be more helpful.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/reflog.c | 34 +++++++++++++++++++---------------\n 1 file changed, 19 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex b5941c1ff3..5a74ccf7ab 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -13,11 +13,15 @@\n \n /* NEEDSWORK: switch to using parse_options */\n static const char reflog_expire_usage[] =\n-\"git reflog expire [--expire=<time>] [--expire-unreachable=<time>] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] <refs>...\";\n+N_(\"git reflog expire [--expire=<time>] \"\n+   \"[--expire-unreachable=<time>] \"\n+   \"[--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] \"\n+   \"[--verbose] [--all] <refs>...\");\n static const char reflog_delete_usage[] =\n-\"git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] <refs>...\";\n+N_(\"git reflog delete [--rewrite] [--updateref] \"\n+   \"[--dry-run | -n] [--verbose] <refs>...\");\n static const char reflog_exists_usage[] =\n-\"git reflog exists <ref>\";\n+N_(\"git reflog exists <ref>\");\n \n static timestamp_t default_reflog_expire;\n static timestamp_t default_reflog_expire_unreachable;\n@@ -556,7 +560,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \t\t\tbreak;\n \t\t}\n \t\telse if (arg[0] == '-')\n-\t\t\tusage(reflog_expire_usage);\n+\t\t\tusage(_(reflog_expire_usage));\n \t\telse\n \t\t\tbreak;\n \t}\n@@ -569,7 +573,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \tif (cb.cmd.stalefix) {\n \t\trepo_init_revisions(the_repository, &cb.cmd.revs, prefix);\n \t\tif (flags & EXPIRE_REFLOGS_VERBOSE)\n-\t\t\tprintf(\"Marking reachable objects...\");\n+\t\t\tprintf(_(\"Marking reachable objects...\"));\n \t\tmark_reachable_objects(&cb.cmd.revs, 0, 0, NULL);\n \t\tif (flags & EXPIRE_REFLOGS_VERBOSE)\n \t\t\tputchar('\\n');\n@@ -598,7 +602,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \t\tchar *ref;\n \t\tstruct object_id oid;\n \t\tif (!dwim_log(argv[i], strlen(argv[i]), &oid, &ref)) {\n-\t\t\tstatus |= error(\"%s points nowhere!\", argv[i]);\n+\t\t\tstatus |= error(_(\"%s points nowhere!\"), argv[i]);\n \t\t\tcontinue;\n \t\t}\n \t\tset_reflog_expiry_param(&cb.cmd, explicit_expiry, ref);\n@@ -644,13 +648,13 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)\n \t\t\tbreak;\n \t\t}\n \t\telse if (arg[0] == '-')\n-\t\t\tusage(reflog_delete_usage);\n+\t\t\tusage(_(reflog_delete_usage));\n \t\telse\n \t\t\tbreak;\n \t}\n \n \tif (argc - i < 1)\n-\t\treturn error(\"Nothing to delete?\");\n+\t\treturn error(_(\"no reflog specified to delete\"));\n \n \tfor ( ; i < argc; i++) {\n \t\tconst char *spec = strstr(argv[i], \"@{\");\n@@ -659,12 +663,12 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)\n \t\tint recno;\n \n \t\tif (!spec) {\n-\t\t\tstatus |= error(\"Not a reflog: %s\", argv[i]);\n+\t\t\tstatus |= error(_(\"not a reflog: %s\"), argv[i]);\n \t\t\tcontinue;\n \t\t}\n \n \t\tif (!dwim_log(argv[i], spec - argv[i], &oid, &ref)) {\n-\t\t\tstatus |= error(\"no reflog for '%s'\", argv[i]);\n+\t\t\tstatus |= error(_(\"no reflog for '%s'\"), argv[i]);\n \t\t\tcontinue;\n \t\t}\n \n@@ -699,7 +703,7 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n \t\t\tbreak;\n \t\t}\n \t\telse if (arg[0] == '-')\n-\t\t\tusage(reflog_exists_usage);\n+\t\t\tusage(_(reflog_exists_usage));\n \t\telse\n \t\t\tbreak;\n \t}\n@@ -707,10 +711,10 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n \tstart = i;\n \n \tif (argc - start != 1)\n-\t\tusage(reflog_exists_usage);\n+\t\tusage(_(reflog_exists_usage));\n \n \tif (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL))\n-\t\tdie(\"invalid ref format: %s\", argv[start]);\n+\t\tdie(_(\"invalid ref format: %s\"), argv[start]);\n \treturn !reflog_exists(argv[start]);\n }\n \n@@ -719,12 +723,12 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)\n  */\n \n static const char reflog_usage[] =\n-\"git reflog [ show | expire | delete | exists ]\";\n+N_(\"git reflog [ show | expire | delete | exists ]\");\n \n int cmd_reflog(int argc, const char **argv, const char *prefix)\n {\n \tif (argc > 1 && !strcmp(argv[1], \"-h\"))\n-\t\tusage(reflog_usage);\n+\t\tusage(_(reflog_usage));\n \n \t/* With no command, we default to showing it. */\n \tif (argc < 2 || *argv[1] == '-')\n-- \n2.19.1.1231.g84aef82467\n\n"},{"id":"362889","messageId":"CACsJy8CT43QQRvkHefXnPtYHbAFQVB847bTYyj8Hxyt-csDkBA@mail.gmail.com","threadId":"49702","inReplyTo":"xmqqbm72g9ee.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v2 15/16] fsck: reduce word legos to help i18n","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-11-10T04:59:25Z","receivedAt":"2018-11-10T05:53:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Nov 6, 2018 at 4:41 AM Junio C Hamano <gitster@pobox.com> wrote:\n> >  static int fsck_error_func(struct fsck_options *o,\n> >       struct object *obj, int type, const char *message)\n> >  {\n> > -     objreport(obj, (type == FSCK_WARN) ? \"warning\" : \"error\", message);\n> > -     return (type == FSCK_WARN) ? 0 : 1;\n> > +     if (type == FSCK_WARN) {\n> > +             fprintf_ln(stderr, \"warning in %s %s: %s\",\n> > +                        printable_type(obj), describe_object(obj), message);\n> > +             return 0;\n> > +     }\n> > +\n> > +     fprintf_ln(stderr, \"error in %s %s: %s\",\n> > +                printable_type(obj), describe_object(obj), message);\n> > +     return 1;\n>\n> Make it look more symmetrical like the original, perhaps by\n>\n>         if (type == FSCK_WARN) {\n>                 ...\n>                 return 0;\n>         } else { /* FSCK_ERROR */\n>                 ...\n>                 return 1;\n>         }\n>\n> Actually, wouldn't it be clearer to see what is going on, if we did\n> it like this instead?\n>\n>         const char *fmt = (type == FSCK_WARN)\n>                 ? N_(\"warning in %s %s: %s\")\n>                 : N_(\"error in %s %s: %s\");\n>         fprintf_ln(stderr, _(fmt),\n>                    printable_type(obj), describe_object(obj), message);\n>         return (type == FSCK_WARN) ? 0 : 1;\n>\n> It would show that in either case we show these three things in the\n> message.  I dunno.\n\nSpecifying \"type == FSCK_WARN\" twice triggers me (what if we add a\nthird fsck type?) so I just turn this to a switch/case block instead\n(and get to know the third fsck type FSCK_IGNORE).\n-- \nDuy\n"},{"id":"362893","messageId":"2bbd6010-c4c5-df68-3583-51a354e3ab5a@ramsayjones.plus.com","threadId":"49702","inReplyTo":"CACsJy8CM=0Cw1WCamJJe8aapA4-mdr+rMmbjVpYYQCj2++NQbA@mail.gmail.com","subject":"Re: [PATCH v2 12/16] parse-options: replace opterror() with optname()","fromName":"Ramsay Jones","fromEmail":"ramsay@ramsayjones.plus.com","sentAt":"2018-11-10T14:59:05Z","receivedAt":"2018-11-10T14:59:11Z","isPatch":true,"sender":{"key":"ramsay@ramsayjones.plus.com","avatar":"https://avatars.githubusercontent.com/u/33702710?v=4"},"body":"\n\nOn 10/11/2018 04:55, Duy Nguyen wrote:\n> On Tue, Nov 6, 2018 at 3:07 PM Ramsay Jones <ramsay@ramsayjones.plus.com> wrote:\n>> Also, this patch does not replace opterror() calls outside of\n>> the 'parse-options.c' file with optname(). This tickles my\n>> static-check.pl script, since optname() is an external function\n>> which is only called from 'parse-options.c'.\n>>\n>> So, at present, optname() could be marked as a local 'static'\n>> symbol. However, I could also imagine it being used by new callers\n>> outside of 'parse-options.c' in the future. (maybe) Your call. ;-)\n> \n> I was making it static, but the compiler complained about undefined\n> function and I would need to either move optname() up in\n> parse-options.c or add a forward declaration (but I was going to\n> _remove_ the declaration!)\n> \n> Since it could be potentially used by Jeff's series (and I think it\n> does have potential in parse-options-cb.c), I'll just leave it\n> exported and caress your static-check.pl script\n\nFair enough.\n\n>                                                (how did it not catch\n> optbug() not being used outside parse-options.c either)?\n\nIt did, some time ago (presumably, I haven't checked). Which is to\nsay: the output from the master branch notes it:\n\n    $ grep parse-options sc\n    parse-options.o\t- optbug\n    $ \n\n... but if it gets to the master branch I tend to forget it. (I have\nbeen meaning to go through the 'sc' file and clean out some of the\n'easy' cases).\n\nSo, if optname() doesn't get any new callers, I will watch it go\nfrom 'pu' to 'next' and then to 'master' and ... ;-)\n\nATB,\nRamsay Jones\n"}]}