Translating error messages in SketchObjectPyImp.cpp

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
chennes
Veteran
Posts: 3877
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Translating error messages in SketchObjectPyImp.cpp

Post by chennes »

In the file SketchObjectPyImp.cpp we generate a bunch of text strings that are used as the message text in PyErr_SetString -- eventually, when running the GUI, these strings are displayed to the user, untranslated. I'm unsure of the correct path forward here. Should we be translating these strings? Should we never actually show them to the user, but just display the (localized) equivalent of "An error occurred"? See https://github.com/FreeCAD/FreeCAD-tran ... issues/183 for the issue that originated this discussion.
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
abdullah
Veteran
Posts: 4935
Joined: Sun May 04, 2014 3:16 pm
Contact:

Re: Translating error messages in SketchObjectPyImp.cpp

Post by abdullah »

@chennes

I am afraid I do not have a full solution.

I am inclined to think that we should not have such blocking popups at all (popups where the only option is to click ok).

If we use the NotificationArea instead, we could:

Option A

Mark these for translation with the Notifications context:

Code: Select all

QT_TRANSLATE_NOOP("Notifications","Parabolas were migrated. Migrated files won't open in previous versions of FreeCAD!!");
Then the NotificationArea always tries to translate errors/warnings/notifications using that context.

The problem with this approach is that the string needs to be fixed. This is a problem:

Code: Select all

        std::stringstream str;
        if (err == -1)
            str << "Invalid constraint index: " << Index;
We would need to give away the index information for it to work. Something like this:

Code: Select all

        std::stringstream str;
        if (err == -1)
            str << QT_TRANSLATE_NOOP("Notifications", "Invalid constraint index");
        else if (err == -3)
            str << QT_TRANSLATE_NOOP("Notifications", "Cannot set the datum because the sketch contains conflicting constraints");
        else if (err == -2)
            str << QT_TRANSLATE_NOOP("Notifications", "Datum is invalid");
        else if (err == -4)
            str << QT_TRANSLATE_NOOP("Notifications", "Negative datum values are not valid for the constraint");
        else if (err == -5)
            str << QT_TRANSLATE_NOOP("Notifications", "Zero is not a valid datum for the constraint");
        else if (err == -6)
            str << QT_TRANSLATE_NOOP("Notifications", "Cannot set the datum because of invalid geometry");
        else
            str << QT_TRANSLATE_NOOP("Notifications", "Unexpected problem at setting datum");
That is not very nice. This is just some example code showing what I mean exactly:
https://github.com/abdullahtahiriyo/Fre ... 2d0325dfdc

Option B

Creating translated strings in SketchObjectPyImp. I have tried to avoid this in the App part of FreeCAD, to avoid inserting additional dependencies.

The good part of this solution is that it is there that all the information is available (error code).

Option C

Leave SketchObjectPyImp alone and create a TranslatedNotification in EditDatumDialog from scratch. But then, there is not the same degree of granularity in the error, as EditDatumDialog does not know the error code (and string comparison to create new strings is really awful as a solution).

I think we have make a leap forward with notification area. However, I do not have yet a clear idea yet of which information should be handled how (error, warning, notification, translatednotification). Some cases are easy and clear. There are others where the information should probably be just a report view error, and then, the question arises whether some of the errors that we want to see in the notificationarea, perhaps these should be notifications instead...
abdullah
Veteran
Posts: 4935
Joined: Sun May 04, 2014 3:16 pm
Contact:

Re: Translating error messages in SketchObjectPyImp.cpp

Post by abdullah »

One possible argument in favour of moving user meaningful errors to another category (e.g. notifications), is that python exceptions get reported as errors, via:

Code: Select all

void PyException::ReportException () const
{
    if (!_isReported) {
        _isReported = true;
        Base::Console().Error("%s%s: %s\n",
            _stackTrace.c_str(), _errorType.c_str(), what());
    }
}
There are two types of users: developers who love to see this in this form, and users, who may not like it.

NotificationArea can be configured not to show errors (errors and warnings can be deselected in configuration). However, then we should move all meaningful errors from being errors to being notifications...

... alternatively, if necessary and if it makes sense in the whole, we could create another category UserError, but is there a use case for user errors and notifications, or should notifications be considered user errors? At the end, when we talk about the user, all the user needs is to be notified... but then, the user appreciates that the software can provide the level of severity, a notification (with an "i" icon) does not convey the idea of an error (with an "x" icon)...

There are plenty of ways forward. The framework is quite flexible...
abdullah
Veteran
Posts: 4935
Joined: Sun May 04, 2014 3:16 pm
Contact:

Re: Translating error messages in SketchObjectPyImp.cpp

Post by abdullah »

@chennes
@wmayer

Although I have not yet come to a global solution, today I have dedicated some time to think about this kind of messages and translations.

I have the idea that we do not translate messages that are reported in the report view. This is mostly messages triggered from the App part of FreeCAD (not the Gui part). However, I would like to double check with other developers on this, as I am not sure myself if I perceived this or if there is a rule or guidance.

If we do not translate them, when a string is fixed (not construed on the base of parameters like the example below), the NotificationArea can still provide support for translations (as described in the previous post). The report view will show the string in English and the NotificationArea would report a translated version.

Problem A

One problem starts when we have dynamically generated strings, such as this code (from SketchObjectPyImp.cpp):

Code: Select all

    if (err) {
        std::stringstream str;
        if (err == -1)
            str << "Invalid constraint index: " << Index;
        else if (err == -3)
            str << "Cannot set the datum because the sketch contains conflicting constraints";
        else if (err == -2)
            str << "Datum " << (const char*)Quantity.getUserString().toUtf8() << " for the constraint with index " << Index << " is invalid";
        else if (err == -4)
            str << "Negative datum values are not valid for the constraint with index " << Index;
        else if (err == -5)
            str << "Zero is not a valid datum for the constraint with index " << Index;
        else if (err == -6)
            str << "Cannot set the datum because of invalid geometry";
        else
            str << "Unexpected problem at setting datum " << (const char*)Quantity.getUserString().toUtf8() << " for the constraint with index " << Index;
        PyErr_SetString(PyExc_ValueError, str.str().c_str());
        return nullptr;
    }
All the premises above being true, we cannot generate the translations here. If we do not the flow is as follows:
PyErr_SetString => void PyException::ThrowException() => myexcp.ReportException() => myexcp.raiseException() => EditDatumDialog::accepted():

Code: Select all

       catch (const Base::Exception& e) {
            QMessageBox::critical(Gui::getMainWindow(), QObject::tr("Dimensional constraint"), QString::fromUtf8(e.what()));
            Gui::Command::abortCommand();

            if(sketch->noRecomputes) // if setdatum failed, it is highly likely that solver information is invalid.
                sketch->solve();

        }
So the string text will be reported to the ReportView and the NotificationArea (via myexcp.ReportException() => Base::Console().Error). NotificationArea will try to translate it, but not having a translated counterpart for the dynamically generated string, it will fail to and will show the original English. Then EditDatumDialog::accepted will show the pop-up with the untranslated string. We could change the call to QMessageBox::critical with a notification function that reports a pop-up or to the notification area based on whether the intrusive notifications are activated or not. This would try to translate the message (either for the NotificationArea or for the Pop-up). However, English test will be shown as there is no match for translation.

Which options do we have?
1. We could only generate static strings for errors. We lose information. Perhaps more importantly, we lose information when reporting to the report-view (where we would have no problem to show the dynamically generated English version) and in the NotificationArea/Pop-up.

2. We could enrich the exception with additional data, such as an errorCode and an affectedID. The dynamically generated English version will still go thru the pipeline and will be printed (at least to the ReportView) in English. However, we could change EditDatumDialog::accepted(), to check the errorcode and affectedId information to create a meaningful translated notification. This would be fed to the notification system, so a translated pop-up or a translated notification in the notification area is shown.

Enriching exceptions is possible, as additional information can be coded in the Python Dictionary to be handled when creating the c++ exception from the Python one (example FileException in Exception.h/.cpp).

Problem B: Duplicated notifications when Python exceptions occur.

The fact that a python exception generates a report and the report is sent via Console.Error may lead to duplicated exceptions, if the c++ exception handling generates another notification.

I think it is right that python exception sends to Console.Error. FreeCADCmd needs this.

It is possibly also right that the gui c++ exception handling code generates a notification, if only, because the user may have the "intrusive mode" on and want a pop-up instead of a NotificationArea notification.

If a user would configure FC not to show errors on the NotificationArea, he could get just the notification. Developers like me wanting to see everything in the notification area would see it twice... not sure what else could be done here.

Problem C: Notifications with developer grade semantics are shown

An image is worth a thousand words:
Screenshot_20230517_184659.png
Screenshot_20230517_184659.png (70.43 KiB) Viewed 1057 times
The first message is probably what we are aiming for (except the localisation problem indicated under Problem A). The rest is probably only wanted by Developers.

One option not to get those errors, is to configure FreeCAD not to show errors in the notification area (not desirable by me, but understandable for users). One possibility is disable the errors and to make the notification in EditDatumDialog a Notification rather than error. This is the result:
Screenshot_20230517_185447.png
Screenshot_20230517_185447.png (115.44 KiB) Viewed 1057 times
So one notification in the notification area (with an "i" icon, rather than an error one), and one (detailed) error in the report view.

A developer/user having errors enabled in the notification area would get:
Screenshot_20230517_185800.png
Screenshot_20230517_185800.png (42.49 KiB) Viewed 1057 times
Here, one could say the "i" icon is not desirable (icons can be changed, that easy). I no longer know.

When I started the work on the NotificationArea consulted the community. We came to the necessity of a "Notification" which would be a "User Mistake". In this specific case, one could argue that inserting a negative datum for a distance constraint qualifies as a "User Mistake".

However, there are software errors that I think we want to notify to the user, and that are not "User Mistakes". While some current error messages are "developer" grade only, such as exception reports, others I think they are NotificationArea material.

We could redefine "Notification" to encompass also the errors we want to notify to the user, even if they are not user mistakes.

Yet another alternative would be to create yet another category of message (UserError). This will work similar to the Notification, and enable to separate Developer errors from other errors. While this may seem plausible, it could just increase the segmentation of types of messages too much.

If I could have some additional input on how you guys see this, I could dedicate some developer time to improve the situation, at least at sketcher level. If we are satisfied with the outcome, then we could expand it FreeCAD-wide.
User avatar
chennes
Veteran
Posts: 3877
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: Translating error messages in SketchObjectPyImp.cpp

Post by chennes »

There's a lot to unpack there, so let me start with the most basic. My approach is that any string that we intend to show to an end-user should be translatable -- for me, this is everything at Warning-level and above (I do not translate "log" and "message"-level events). It doesn't matter where we show it, because I figure that could change at any time (e.g. now we have the notification area, so many things that were hidden before are now visible).

I think this resolves a lot of the following problems, because you can nearly always achieve the best error string by doing the translation at the location where you have the most information. It is up to developers to show some discretion here: we have many instances where developer-only information is placed into a Warning- or Error-level text string, when I think it ought to be split up into a user-visible error text, and then log-level debugging output. IMO developers should assume that the "message" of an exception will be displayed to users at some point (use translation context "Exception" for those).
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
abdullah
Veteran
Posts: 4935
Joined: Sun May 04, 2014 3:16 pm
Contact:

Re: Translating error messages in SketchObjectPyImp.cpp

Post by abdullah »

chennes wrote: Wed May 17, 2023 5:29 pm It doesn't matter where we show it, because I figure that could change at any time (e.g. now we have the notification area, so many things that were hidden before are now visible).
I do think indeed it is an important first question to ask and get replied.

Two observations:
1. This would mean that a report view would have mixed language output (log English, error Japanese, for example). If a user makes a screenshot to get help from the community... well, it may not be so convenient.

2. There are additional dependencies that App will have to have to handle this. Werner would be in a better position than be to ascertain whether it is reasonable to make App dependent on the translation framework (for example SketchObject).
User avatar
chennes
Veteran
Posts: 3877
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: Translating error messages in SketchObjectPyImp.cpp

Post by chennes »

abdullah wrote: Wed May 17, 2023 7:36 pm 1. This would mean that a report view would have mixed language output (log English, error Japanese, for example).
In the best possible world we'd translate everything: but I consider log- and message-level events to be specific to developers. In most cases end users will never see those unless a developer has asked them to turn on logging for debugging purposes. Since development is happening in English, this seems like a reasonable compromise to me.

2. There are additional dependencies that App will have to have to handle this.
App is actually already being compiled with translation support, so from a big-picture perspective we are already doing this. On a file-by-file and class-by-class basis, yes, this will require additional includes, and in many cases the use of the Q_DECLARE_TR_FUNCTIONS macro.
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
abdullah
Veteran
Posts: 4935
Joined: Sun May 04, 2014 3:16 pm
Contact:

Re: Translating error messages in SketchObjectPyImp.cpp

Post by abdullah »

This PR is intended as a working live implementation to test on Sketcher WB what we discuss here:
https://github.com/FreeCAD/FreeCAD/pull/9604

@chennes

Thank you for your input.

These two points are very important, as they set different requirements for a translation framework.

I have worked so far with the contrary assumptions, and the frameworks I have developed over time were based on them (exception translation framework and the new console framework that notification area uses). They are limited to handle what I understood as requirements.

At this point, I think further development requires that we users (point 1) and developers (point 2) can agree what we set as requirements. All remaining topics depend heavily on these two decisions.
User avatar
onekk
Veteran
Posts: 6144
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Translating error messages in SketchObjectPyImp.cpp

Post by onekk »

From an user perspective, I search for an error message on the net.

If error messages are translated I have less chances to find an answer as many infos are in English.

So a description like "An error is occured" or similar should be translated but the puthin error message it is better to be left in English to maximize chances to find solutions.

But this is a perfonal point of view, as some softwares have the other way behaviuor, but in these cases debugging could be a pain, as i have to change the language to English and to have more chances to find a hints on the net.

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
User avatar
chennes
Veteran
Posts: 3877
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: Translating error messages in SketchObjectPyImp.cpp

Post by chennes »

onekk wrote: Fri May 19, 2023 5:07 am From an user perspective, I search for an error message on the net.
Yes, this is exactly the crux of the issue: whether it is better for the error message to make direct sense to you (in your native language) so you have a chance to correct whatever is wrong, or whether the error message is "universal" so that you don't even try to understand it, you just hit Google immediately. I suppose this is one of the reasons that "error codes" have stuck with us.
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
Post Reply