gui: Introduce bilingual GUI error messages #15340

pull hebasto wants to merge 5 commits into bitcoin:master from hebasto:20190204-bilingual-initerror changing 13 files +106 −48
  1. hebasto commented at 2:59 pm on February 4, 2019: member

    Ref: #16218

    This PR:

    • makes GUI error messages bilingual: user’s native language + untranslated (i.e. English)
    • insures that only untranslated messages are written to the debug log file and to stderr (that is not the case on master).

    Screenshot from 2019-06-17 01-15-06

    Note for reviewers: InitWarning() is out of this PR scope.

  2. in src/ui_interface.h:135 in ecd619726c outdated
    132 
    133+template <typename... Args>
    134+bool InitErrorFormat(const char* fmt, const Args&... args)
    135+{
    136+    std::string original_message = strprintf(fmt, args...);
    137+    std::string translated_message = strprintf(_(fmt), args...);
    


    MarcoFalke commented at 3:38 pm on February 4, 2019:
    I believe make translate wouldn’t pick those up any more.
  3. hebasto force-pushed on Feb 4, 2019
  4. laanwj commented at 3:41 pm on February 4, 2019: member
    This effectively removes all the translations as there is no _() to pick up anymore by gettext.
  5. DrahtBot commented at 3:46 pm on February 4, 2019: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #16194 (refactor: share blockmetadata with BlockManager by jamesob)
    • #16127 (Add support for thread safety annotations when using std::mutex by ajtowns)
    • #16112 (util: Log early messages by MarcoFalke)
    • #16003 (init: an incorrect amount of file descriptors is requested, and a different amount is also asserted by tryphe)
    • #15946 (Allow maintaining the blockfilterindex when using prune by jonasschnelli)
    • #15891 (test: Require standard txs in regtest by default by MarcoFalke)
    • #15848 (Add a check for free disk space at first startup. by darosior)
    • #15606 ([experimental] UTXO snapshots by jamesob)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  6. luke-jr commented at 3:51 pm on February 4, 2019: member
    This would be much easier to review if InitErrorFormat was named InitError
  7. hebasto force-pushed on Feb 4, 2019
  8. hebasto commented at 4:52 pm on February 4, 2019: member

    @MarcoFalke

    I believe make translate wouldn’t pick those up any more. @laanwj This effectively removes all the translations as there is no _() to pick up anymore by gettext.

    Fixed.

    The main goal of this PR is to avoid printing localized messages to the debug log file and stderr. Bilingual GUI messages come for free.

  9. hebasto commented at 4:55 pm on February 4, 2019: member

    @luke-jr

    This would be much easier to review if InitErrorFormat was named InitError

    Rationale: InitErrorFormat can accept a format string as the first argument.

  10. hebasto closed this on Feb 4, 2019

  11. jonasschnelli commented at 7:19 pm on February 4, 2019: contributor
    I haven’t looked at the code but printing error message always (additionally) in english seems to be a clever idea (especially with the faced complexity and immaturity of the UX).
  12. hebasto reopened this on Feb 4, 2019

  13. hebasto force-pushed on Feb 4, 2019
  14. hebasto force-pushed on Feb 4, 2019
  15. hebasto force-pushed on Feb 4, 2019
  16. fanquake added the label GUI on Feb 4, 2019
  17. hebasto commented at 11:12 pm on February 4, 2019: member
    @MarcoFalke @laanwj it works with gettext now. @luke-jr your comment has been addressed.
  18. hebasto commented at 11:20 pm on February 4, 2019: member
    Rebased.
  19. in src/init.cpp:717 in fb394a610d outdated
    712@@ -713,16 +713,16 @@ static void ThreadImport(std::vector<fs::path> vImportFiles)
    713  */
    714 static bool InitSanityCheck()
    715 {
    716-    if(!ECC_InitSanityCheck()) {
    717-        InitError("Elliptic curve cryptography sanity check failure. Aborting.");
    718+    if (!ECC_InitSanityCheck()) {
    719+        InitError(_("Elliptic curve cryptography sanity check failure. Aborting.", true));
    


    MarcoFalke commented at 4:04 pm on February 5, 2019:
    I don’t understand why this should be translated. This should never fail and if it fails, I bet you are better off with the english error message?

    laanwj commented at 4:06 pm on February 5, 2019:
    Agree, I feel we had this discussion already. Please don’t translate extremely rare or technical errors.

    hebasto commented at 7:20 pm on February 5, 2019:

    Fixed.

    btw, this PR aims that a translated message:

    • is written to debug log in English
    • is printed to stderr in English
    • is shown in GUI in both languages

    Therefore, english error message is always available even for translated messages.

  20. in src/init.cpp:725 in fb394a610d outdated
    723     if (!glibc_sanity_test() || !glibcxx_sanity_test())
    724         return false;
    725 
    726     if (!Random_SanityCheck()) {
    727-        InitError("OS cryptographic RNG sanity check failure. Aborting.");
    728+        InitError(_("OS cryptographic RNG sanity check failure. Aborting.", true));
    


    laanwj commented at 4:09 pm on February 5, 2019:
    Same for this one

    hebasto commented at 7:20 pm on February 5, 2019:
    Fixed.
  21. in src/ui_interface.cpp:38 in fb394a610d outdated
    34@@ -35,6 +35,7 @@ struct UISignals {
    35     }
    36 
    37 ADD_SIGNALS_IMPL_WRAPPER(ThreadSafeMessageBox);
    38+ADD_SIGNALS_IMPL_WRAPPER(ThreadSafeMessageBox2);
    


    laanwj commented at 4:11 pm on February 5, 2019:
    Please use a better name than ThreadSafeMessageBox2. What makes this function different?

    hebasto commented at 7:24 pm on February 5, 2019:

    Fixed.

    btw, 2 in ThreadSafeMessageBox2 meant “bi-” in bilingual rather “second” :)

  22. hebasto force-pushed on Feb 5, 2019
  23. hebasto commented at 7:13 pm on February 5, 2019: member
    @MarcoFalke @laanwj Thank you for your reviews. All your comments have been addressed. Would you mind re-reviewing?
  24. in src/init.cpp:909 in 01781b4665 outdated
    905@@ -904,7 +906,7 @@ bool AppInitBasicSetup()
    906 #endif
    907 
    908     if (!SetupNetworking())
    909-        return InitError("Initializing networking failed");
    910+        return InitError(_("Initializing networking failed", true));
    


    MarcoFalke commented at 7:53 pm on February 5, 2019:
    same here. This should never fail

    hebasto commented at 8:01 pm on February 5, 2019:
    Fixed.
  25. hebasto force-pushed on Feb 5, 2019
  26. DrahtBot added the label Needs rebase on Feb 8, 2019
  27. flack commented at 8:48 pm on February 8, 2019: contributor

    If the point is to make it easier to google error messages, wouldn’t it be more efficient to add some kind of error code to the output? E.g. the example from the screenshot could look like this in the English version:

    0ERR38278: Prune cannot be configured with a negative value
    

    and like this in the German version:

    0ERR38278: Kürzungsmodus kann nicht mit einem negativen Wert konfiguriert werden
    

    This would also help searchability if the English error text changes between versions. Only drawback I suppose is that somebody would have to come up with all the error codes :-)

  28. gmaxwell commented at 8:35 pm on February 11, 2019: contributor

    I like the idea (so Concept ACK), no thoughts on the implementation. @flack Trying to assign numerical error codes in the face of parallel development seems tricky… but not impossible.

    The dual languages also helps in the common case that the user also reads English… since the translation may not be good or may not be clear (esp. even a native speaker of another language may have only seen various technical terms but a translator managed to use a rarely used word in the translated language). Error numbers don’t have this benefit, so the dual language output would be useful independently of error numbers.

  29. flack commented at 8:55 pm on February 11, 2019: contributor

    @gmaxwell yes, it would require some coordination. But I suppose a linter can take care of most of the problems, esp. since the numbers don’t have to be consecutive or follow any kind of logic really.

    It’s true what you say about wonky translations. “Kürzungsmodus” from the screenshot is actually a case in point. It literally means “shortening mode”. No way I would have guessed that this refers to pruning (or at least not on the first try). But otoh, if users have the UI set to e.g. German, then all they see are German terms, i.e. there’s probably a checkbox labeled “Kürzungsmodus” somewhere and they might remember that they clicked that. Throwing the word “pruning” into the mix might just add to the confusion at this point, exactly because the meaning is different (“I selected shortening mode and now it’s complaining about ‘pruning’ ?!?”).

    Anyhow, I get that my suggestion cannot be easily implemented in the short term, but how about making it a bit more clear that the two messages are actually referring to the same thing (instead of being one translated error and one untranslated error)? E.g. something like:

    0Kürzungsmodus kann nicht mit einem negativen Wert konfiguriert werden
    1
    2Original-Meldung: Prune cannot be configured with a negative value
    

    “Original-Meldung” means “original message”. Could also say “untranslated message” or something.

  30. laanwj commented at 10:30 am on February 12, 2019: member

    since the translation may not be good or may not be clear

    I think we need to be careful here also to respect the translators. They are not developers and will not understand internal technical details in error messages.

    If an error message has more technical terms in it than the standard bitcoin and GUI ones such as window, wallet, block, transaction …. then it shouldn’t be translated.

    Translators will get pissed at me for this or substitute some nonsense word. In both cases no one is better off.

  31. flack commented at 10:44 am on February 12, 2019: contributor

    If an error message has more technical terms in it than the standard bitcoin and GUI ones such as window, wallet, block, transaction …. then it shouldn’t be translated.

    Still, you have to enable the user to make the connection between the error message and what they might have selected in the GUI settings. So e.g. if you don’t translate “prune” in the error message, then you also shouldn’t translate it in the rest of the GUI (or at least show the English term in brackets)

  32. laanwj commented at 11:08 am on February 12, 2019: member

    prune is a grey area I guess. It doesn’t go with the obvious bitcoin or computer words but it also isn’t something like “glibc sanity check failed” which makes no sense to users nor translators whatsoever.

    So to be clear Im not against showing error messages in both languages, but this shouldn’t a reason to translate things that would otherwise not be because the English message can be used to work around a terrible translation.

  33. hebasto force-pushed on Feb 12, 2019
  34. hebasto commented at 10:28 pm on February 12, 2019: member
    Rebased.
  35. DrahtBot removed the label Needs rebase on Feb 12, 2019
  36. DrahtBot added the label Needs rebase on Mar 2, 2019
  37. DrahtBot commented at 10:37 pm on March 2, 2019: member
  38. hebasto closed this on Mar 9, 2019

  39. hebasto reopened this on Jun 16, 2019

  40. Do not translate captions in log and stderr 810e228ed2
  41. Do not translate extremely rare / technical errors fea324f90e
  42. Add bilingual messages facilities a9be63d720
  43. Add bilingual InitError() function 302806ebf5
  44. Use bilingual InitError() in simple cases 8aca2cf3b1
  45. hebasto force-pushed on Jun 16, 2019
  46. hebasto commented at 10:20 pm on June 16, 2019: member

    Rebased after #15288 merged. @flack your comment has been addressed.

    OP and screenshot updated.

  47. flack commented at 10:25 pm on June 16, 2019: contributor
    @hebasto awesome!
  48. hebasto commented at 10:33 pm on June 16, 2019: member

    After the e2c8ba9f6e782e2545b71e9e34b967c69e18c7f0 commit merged there is no straight way to pass function template InitError(const bilingual_str& fmt, const Args&... args) through the Chain interface.

    I ask for advice @ryanofsky, @MarcoFalke, @jonasschnelli, @promag.

  49. in src/util/system.h:62 in 8aca2cf3b1
    53@@ -54,6 +54,16 @@ inline std::string _(const char* psz)
    54     return G_TRANSLATION_FUN ? (G_TRANSLATION_FUN)(psz) : psz;
    55 }
    56 
    57+struct bilingual_str {
    58+    std::string original_str;
    59+    std::string translated_str;
    60+};
    61+
    62+inline bilingual_str _(const char* psz, bool translate)
    


    MarcoFalke commented at 1:11 am on June 17, 2019:

    What is the point of the bool argument, when it is always set to true at the call site? Should be called bool ignored or something like this?

    0enum class Tr{BI;};
    1inline bilingueal_str_(const char* psz, Tr ignored);
    
  50. fanquake removed the label Needs rebase on Jun 17, 2019
  51. in src/ui_interface.h:139 in 8aca2cf3b1
    133@@ -130,4 +134,20 @@ bool InitError(const std::string& str);
    134 
    135 extern CClientUIInterface uiInterface;
    136 
    137+/** Show bilingual error message **/
    138+template <typename... Args>
    139+bool InitError(const bilingual_str& fmt, const Args&... args)
    


    MarcoFalke commented at 10:22 am on June 17, 2019:

    I’d prefer if you removed the plain InitError, since it doesn’t seem to be required.

    Also, would be nice to add InitError to the linter ./test/lint/lint-format-strings.sh


    hebasto commented at 11:28 am on June 17, 2019:

    I’d prefer if you removed the plain InitError, since it doesn’t seem to be required.

    If I understand you correctly then what about #15340 (review)? Also see: fea324f90e58f74ad76045bd68db1f96f4b00200


    MarcoFalke commented at 11:41 am on June 17, 2019:
    I mean that InitError could take as first argument a string or bilingual string, so that the formatting always happens inside of InitError. Then add InitError to the linter.
  52. MarcoFalke commented at 10:22 am on June 17, 2019: member
    Concept ACK
  53. hebasto commented at 1:04 pm on June 17, 2019: member

    After the e2c8ba9 commit merged there is no straight way to pass function template InitError(const bilingual_str& fmt, const Args&... args) through the Chain interface.

    The solution is #16224.

    Should this PR be closed?

  54. hebasto commented at 3:58 pm on June 17, 2019: member
    Closing in favor of #16224 which provides a different approach and works with the Chain interface as expected.
  55. hebasto closed this on Jun 17, 2019

  56. hebasto deleted the branch on Jul 18, 2019
  57. MarcoFalke referenced this in commit 5b24f6084e on May 8, 2020
  58. sidhujag referenced this in commit fc9f727a08 on May 12, 2020
  59. DrahtBot locked this on Feb 15, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-18 09:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me