{"thread":{"id":"35462","subject":"[PATCH/RESEND] transport.c: mark push status strings for translation","startedAt":"2013-12-03T10:26:49Z","lastAt":"2013-12-03T20:08:57Z","messageCount":2,"participants":["Nguyễn Thái Ngọc Duy","Jonathan Nieder"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"231421","messageId":"1386066409-15262-1-git-send-email-pclouds@gmail.com","threadId":"35462","inReplyTo":null,"subject":"[PATCH/RESEND] transport.c: mark push status strings for translation","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-12-03T10:26:49Z","receivedAt":"2013-12-03T10:26:49Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Mark strings like \"[up to date]\" passed to print_ref_status() for\ntranslation with N_() instead of _() so they can remain untranslated\nin porcelain mode.\n\nWhile at there, mark some error strings in git push for translation\ntoo.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nReviewed-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n builtin/push.c |  8 +++---\n transport.c    | 81 ++++++++++++++++++++++++++++++++++------------------------\n 2 files changed, 52 insertions(+), 37 deletions(-)\n\ndiff --git a/builtin/push.c b/builtin/push.c\nindex 7b1b66c..22e2d4c 100644\n--- a/builtin/push.c\n+++ b/builtin/push.c\n@@ -319,7 +319,7 @@ static int push_with_options(struct transport *transport, int flags)\n \n \tif (!is_empty_cas(&cas)) {\n \t\tif (!transport->smart_options)\n-\t\t\tdie(\"underlying transport does not support --%s option\",\n+\t\t\tdie(_(\"underlying transport does not support --%s option\"),\n \t\t\t    CAS_OPT_NAME);\n \t\ttransport->smart_options->cas = &cas;\n \t}\n@@ -426,7 +426,7 @@ static int option_parse_recurse_submodules(const struct option *opt,\n \n \tif (*flags & (TRANSPORT_RECURSE_SUBMODULES_CHECK |\n \t\t      TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND))\n-\t\tdie(\"%s can only be used once.\", opt->long_name);\n+\t\tdie(_(\"%s can only be used once.\"), opt->long_name);\n \n \tif (arg) {\n \t\tif (!strcmp(arg, \"check\"))\n@@ -434,9 +434,9 @@ static int option_parse_recurse_submodules(const struct option *opt,\n \t\telse if (!strcmp(arg, \"on-demand\"))\n \t\t\t*flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND;\n \t\telse\n-\t\t\tdie(\"bad %s argument: %s\", opt->long_name, arg);\n+\t\t\tdie(_(\"bad %s argument: %s\"), opt->long_name, arg);\n \t} else\n-\t\tdie(\"option %s needs an argument (check|on-demand)\",\n+\t\tdie(_(\"option %s needs an argument (check|on-demand)\"),\n \t\t\t\topt->long_name);\n \n \treturn 0;\ndiff --git a/transport.c b/transport.c\nindex 7202b77..1fb92a1 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -14,6 +14,7 @@\n #include \"url.h\"\n #include \"submodule.h\"\n #include \"string-list.h\"\n+#include \"utf8.h\"\n \n /* rsync support */\n \n@@ -627,16 +628,23 @@ static void print_ref_status(char flag, const char *summary, struct ref *to, str\n \t\telse\n \t\t\tfprintf(stdout, \"%s\\n\", summary);\n \t} else {\n-\t\tfprintf(stderr, \" %c %-*s \", flag, TRANSPORT_SUMMARY_WIDTH, summary);\n+\t\tint width = TRANSPORT_SUMMARY_WIDTH;\n+\t\tconst char *localized_summary = _(summary);\n+\t\t/*\n+\t\t * Compensate for the invisible bytes in utf-8\n+\t\t * strings. The expression below is guaranteed always\n+\t\t * positive (or zero in case of ascii strings) because\n+\t\t * none of the doublewidth characters are ASCII\n+\t\t * characters.\n+\t\t */\n+\t\twidth += strlen(localized_summary) - utf8_strwidth(localized_summary);\n+\t\tfprintf(stderr, \" %c %-*s \", flag, width, localized_summary);\n \t\tif (from)\n \t\t\tfprintf(stderr, \"%s -> %s\", prettify_refname(from->name), prettify_refname(to->name));\n \t\telse\n \t\t\tfputs(prettify_refname(to->name), stderr);\n-\t\tif (msg) {\n-\t\t\tfputs(\" (\", stderr);\n-\t\t\tfputs(msg, stderr);\n-\t\t\tfputc(')', stderr);\n-\t\t}\n+\t\tif (msg)\n+\t\t\tfprintf(stderr, \" (%s)\", _(msg));\n \t\tfputc('\\n', stderr);\n \t}\n }\n@@ -649,11 +657,11 @@ static const char *status_abbrev(unsigned char sha1[20])\n static void print_ok_ref_status(struct ref *ref, int porcelain)\n {\n \tif (ref->deletion)\n-\t\tprint_ref_status('-', \"[deleted]\", ref, NULL, NULL, porcelain);\n+\t\tprint_ref_status('-', N_(\"[deleted]\"), ref, NULL, NULL, porcelain);\n \telse if (is_null_sha1(ref->old_sha1))\n \t\tprint_ref_status('*',\n-\t\t\t(!prefixcmp(ref->name, \"refs/tags/\") ? \"[new tag]\" :\n-\t\t\t\"[new branch]\"),\n+\t\t\t(!prefixcmp(ref->name, \"refs/tags/\") ? N_(\"[new tag]\") :\n+\t\t\t N_(\"[new branch]\")),\n \t\t\tref, ref->peer_ref, NULL, porcelain);\n \telse {\n \t\tchar quickref[84];\n@@ -664,7 +672,7 @@ static void print_ok_ref_status(struct ref *ref, int porcelain)\n \t\tif (ref->forced_update) {\n \t\t\tstrcat(quickref, \"...\");\n \t\t\ttype = '+';\n-\t\t\tmsg = \"forced update\";\n+\t\t\tmsg = N_(\"forced update\");\n \t\t} else {\n \t\t\tstrcat(quickref, \"..\");\n \t\t\ttype = ' ';\n@@ -678,50 +686,57 @@ static void print_ok_ref_status(struct ref *ref, int porcelain)\n \n static int print_one_push_status(struct ref *ref, const char *dest, int count, int porcelain)\n {\n-\tif (!count)\n-\t\tfprintf(porcelain ? stdout : stderr, \"To %s\\n\", dest);\n+\tif (!count) {\n+\t\tif (porcelain)\n+\t\t\tfprintf(stdout, \"To %s\\n\", dest);\n+\t\telse\n+\t\t\tfprintf_ln(stderr, _(\"To %s\"), dest);\n+\t}\n \n \tswitch(ref->status) {\n \tcase REF_STATUS_NONE:\n-\t\tprint_ref_status('X', \"[no match]\", ref, NULL, NULL, porcelain);\n+\t\tprint_ref_status('X', N_(\"[no match]\"), ref, NULL,\n+\t\t\t\t NULL, porcelain);\n \t\tbreak;\n \tcase REF_STATUS_REJECT_NODELETE:\n-\t\tprint_ref_status('!', \"[rejected]\", ref, NULL,\n-\t\t\t\t\t\t \"remote does not support deleting refs\", porcelain);\n+\t\tprint_ref_status('!', N_(\"[rejected]\"), ref, NULL,\n+\t\t\t\t N_(\"remote does not support deleting refs\"),\n+\t\t\t\t porcelain);\n \t\tbreak;\n \tcase REF_STATUS_UPTODATE:\n-\t\tprint_ref_status('=', \"[up to date]\", ref,\n-\t\t\t\t\t\t ref->peer_ref, NULL, porcelain);\n+\t\tprint_ref_status('=', N_(\"[up to date]\"), ref,\n+\t\t\t\t ref->peer_ref, NULL, porcelain);\n \t\tbreak;\n \tcase REF_STATUS_REJECT_NONFASTFORWARD:\n-\t\tprint_ref_status('!', \"[rejected]\", ref, ref->peer_ref,\n-\t\t\t\t\t\t \"non-fast-forward\", porcelain);\n+\t\tprint_ref_status('!', N_(\"[rejected]\"), ref, ref->peer_ref,\n+\t\t\t\t N_(\"non-fast-forward\"), porcelain);\n \t\tbreak;\n \tcase REF_STATUS_REJECT_ALREADY_EXISTS:\n-\t\tprint_ref_status('!', \"[rejected]\", ref, ref->peer_ref,\n-\t\t\t\t\t\t \"already exists\", porcelain);\n+\t\tprint_ref_status('!', N_(\"[rejected]\"), ref, ref->peer_ref,\n+\t\t\t\t N_(\"already exists\"), porcelain);\n \t\tbreak;\n \tcase REF_STATUS_REJECT_FETCH_FIRST:\n-\t\tprint_ref_status('!', \"[rejected]\", ref, ref->peer_ref,\n-\t\t\t\t\t\t \"fetch first\", porcelain);\n+\t\tprint_ref_status('!', N_(\"[rejected]\"), ref, ref->peer_ref,\n+\t\t\t\t N_(\"fetch first\"), porcelain);\n \t\tbreak;\n \tcase REF_STATUS_REJECT_NEEDS_FORCE:\n-\t\tprint_ref_status('!', \"[rejected]\", ref, ref->peer_ref,\n-\t\t\t\t\t\t \"needs force\", porcelain);\n+\t\tprint_ref_status('!', N_(\"[rejected]\"), ref, ref->peer_ref,\n+\t\t\t\t N_(\"needs force\"), porcelain);\n \t\tbreak;\n \tcase REF_STATUS_REJECT_STALE:\n-\t\tprint_ref_status('!', \"[rejected]\", ref, ref->peer_ref,\n-\t\t\t\t\t\t \"stale info\", porcelain);\n+\t\tprint_ref_status('!', N_(\"[rejected]\"), ref, ref->peer_ref,\n+\t\t\t\t N_(\"stale info\"), porcelain);\n \t\tbreak;\n \tcase REF_STATUS_REMOTE_REJECT:\n-\t\tprint_ref_status('!', \"[remote rejected]\", ref,\n-\t\t\t\t\t\t ref->deletion ? NULL : ref->peer_ref,\n-\t\t\t\t\t\t ref->remote_status, porcelain);\n+\t\tprint_ref_status('!', N_(\"[remote rejected]\"), ref,\n+\t\t\t\t ref->deletion ? NULL : ref->peer_ref,\n+\t\t\t\t ref->remote_status, porcelain);\n \t\tbreak;\n \tcase REF_STATUS_EXPECTING_REPORT:\n-\t\tprint_ref_status('!', \"[remote failure]\", ref,\n-\t\t\t\t\t\t ref->deletion ? NULL : ref->peer_ref,\n-\t\t\t\t\t\t \"remote failed to report status\", porcelain);\n+\t\tprint_ref_status('!', N_(\"[remote failure]\"), ref,\n+\t\t\t\t ref->deletion ? NULL : ref->peer_ref,\n+\t\t\t\t N_(\"remote failed to report status\"),\n+\t\t\t\t porcelain);\n \t\tbreak;\n \tcase REF_STATUS_OK:\n \t\tprint_ok_ref_status(ref, porcelain);\n-- \n1.8.2.83.gc99314b\n"},{"id":"231463","messageId":"20131203200857.GE29959@google.com","threadId":"35462","inReplyTo":"1386066409-15262-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH/RESEND] transport.c: mark push status strings for translation","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-12-03T20:08:57Z","receivedAt":"2013-12-03T20:08:57Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Nguyễn Thái Ngọc Duy wrote:\n\n> Mark strings like \"[up to date]\" passed to print_ref_status() for\n> translation with N_() instead of _() so they can remain untranslated\n> in porcelain mode.\n\nMakes sense.\n\n[...]\n> --- a/builtin/push.c\n> +++ b/builtin/push.c\n\nPerhaps it would make sense to send these as a separate patch, since\nthey are simpler than the rest.\n\n[...]\n> --- a/transport.c\n> +++ b/transport.c\n> @@ -14,6 +14,7 @@\n>  #include \"url.h\"\n>  #include \"submodule.h\"\n>  #include \"string-list.h\"\n> +#include \"utf8.h\"\n>  \n>  /* rsync support */\n>  \n> @@ -627,16 +628,23 @@ static void print_ref_status(char flag, const char *summary, struct ref *to, str\n>  \t\telse\n>  \t\t\tfprintf(stdout, \"%s\\n\", summary);\n>  \t} else {\n> -\t\tfprintf(stderr, \" %c %-*s \", flag, TRANSPORT_SUMMARY_WIDTH, summary);\n> +\t\tint width = TRANSPORT_SUMMARY_WIDTH;\n> +\t\tconst char *localized_summary = _(summary);\n\nThe summary arg comes from one of a few places:\n\n (a) [deleted] etc from print_ok_ref_status, which you marked\n     with N_ (good)\n\n (b) deadbe... from status_abbrev via print_ok_ref_status.  Can we\n     avoid passing it to gettext()?\n\n (c) [no match] etc from print_one_push_status, marked with\n     N_ (good)\n\nI am tempted to suggest something like\n\n\t\tconst char *localized_summary;\n\n\t\tif (*summary != '[')\n\t\t\t/* Leave abbreviated sha1 from status_abbrev() alone */\n\t\t\tlocalized_summary = summary;\n\t\telse\n\t\t\tlocalized_summary = _(summary);\n\nbut that's kind of ugly.  Is there a simpler way?  Should the summary\narg be passed in already localized (with 'porcelain' handling higher\nup)?\n\nThanks,\nJonathan\n"}]}