Bug 0014146: Display Name Editor does not allow to enter keyword "Notpatronymic" into Format string, replaces it with "NotPatronymic"

This is how the bug comes out:

It happens because internal keyword patronymic is a part of another, longer, external (i.e. visible to a user) keyword ‘Notpatronymic’ and vice versa. The same bug exists for Rawsurnames for the same reason: surname is an internal keyword too.

The bug appears to be fixed by mangling internal keywords patronymic, notpatronymic, surname and rawsurnames so they are not parts of each other anymore.

Keywords are duplicated (twice!) in gramps/gen/display/name.py , so they need to be changed there too.

Pull request has been submitted to the current maintenance branch. Detailed description of the bug and its solution follows.

Below is the fragment of the code processing string entered by the user into Format field, copied from gramps/gui/configure.py:

Fragment A
            # build a pattern from translated pattern:
            pattern = new_text
            if len(new_text) > 2 and new_text[0] == '"' and new_text[-1] == '"':
                passtag
            else:
                for key in get_translations():
                    if key in pattern:
                        pattern = pattern.replace(
                            key, get_keyword_from_translation(key)
                        )
            # now build up a proper translation:
            translation = pattern
            if len(new_text) > 2 and new_text[0] == '"' and new_text[-1] == '"':
                pass
            else:
                for key in get_keywords():
                    if key in translation:
                        translation = translation.replace(
                            key, get_translation_from_keyword(key)
                        )

Above code uses 4 functions from gramps/gen/utils/keyword.py, namely get_translations(), get_keyword_from_translation(key) , get_keywords() and get_translation_from_keyword(key)

Fragment B
KEYWORDS = [
    ("title", "t", _("Title", "Person"), _("TITLE", "Person")),
    ("given", "f", _("Given"), _("GIVEN")),
    ("surn2me", "l", _("Surname"), _("SURNAME")),
    ("call", "c", _("Call", "Name"), _("CALL", "Name")),
    ("common", "x", _("Common", "Name"), _("COMMON", "Name")),
    ("initials", "i", _("Initials"), _("INITIALS")),
    ("suffix", "s", _("Suffix"), _("SUFFIX")),
    ("primary", "m", _("Primary", "Name"), _("PRIMARY")),
    ("primary[pre]", "0m", _("Primary[pre]"), _("PRIMARY[PRE]")),
    ("primary[sur]", "1m", _("Primary[sur]"), _("PRIMARY[SUR]")),
    ("primary[con]", "2m", _("Primary[con]"), _("PRIMARY[CON]")),
    ("patr2nymic", "y", _("Patronymic"), _("PATRONYMIC")),
    ("patronymic[pre]", "0y", _("Patronymic[pre]"), _("PATRONYMIC[PRE]")),
    ("patronymic[sur]", "1y", _("Patronymic[sur]"), _("PATRONYMIC[SUR]")),
    ("patronymic[con]", "2y", _("Patronymic[con]"), _("PATRONYMIC[CON]")),
    ("rawsurn0mes", "q", _("Rawsurnames"), _("RAWSURNAMES")),
    ("notpatr0nymic", "o", _("Notpatronymic"), _("NOTPATRONYMIC")),
    ("prefix", "p", _("Prefix"), _("PREFIX")),
    ("nickname", "n", _("Nickname"), _("NICKNAME")),
    ("familynick", "g", _("Familynick"), _("FAMILYNICK")),
]
KEY_TO_TRANS = {}
TRANS_TO_KEY = {}
for key, code, standard, upper in KEYWORDS:
    KEY_TO_TRANS[key] = standard
    KEY_TO_TRANS[key.upper()] = upper
    KEY_TO_TRANS["%" + ("%s" % code)] = standard
    KEY_TO_TRANS["%" + ("%s" % code.upper())] = upper
    TRANS_TO_KEY[standard.lower()] = key
    TRANS_TO_KEY[standard] = key
    TRANS_TO_KEY[upper] = key.upper()


def get_translation_from_keyword(keyword):
    """Return the translation of keyword"""
    return KEY_TO_TRANS.get(keyword, keyword)


def get_keyword_from_translation(word):
    """Return the keyword of translation"""
    return TRANS_TO_KEY.get(word, word)


def get_keywords():
    """Get all keywords, longest to shortest"""
    keys = list(KEY_TO_TRANS.keys())
    keys.sort(key=lambda a: len(a), reverse=True)
    return keys


def get_translations():
    """Get all translations, longest to shortest"""
    trans = list(TRANS_TO_KEY.keys())
    trans.sort(key=lambda a: len(a), reverse=True)
    return trans

The first loop in Fragment A uses get_translation() to replace all external keywords entered by a user with their internal equivalents.

The second loop in Fragment A uses get_keywords() to replace all internal keywords by their external equivalents.

As it can be seen from Fragment B, both get_translations() and get_keywords() starts from longer keywords and proceed towards shorter ones.

Suppose that a user entered “Notpatronymic” into new_text variable. Then first loop transform it first into “notpatronymic” internal keyword (as soon as it recognizes “Notpatronymic”) and then it will see external keyword “patronymic” and will replace it with *internal" keyword for external “patronymic”. (Currently they are the same, but if internal keyword for “patronymic” were “pAtRoNyMiC”, the stringu would transform into the wrong string “notpAtRoNyMiC”).

In a similar fashion, the second loop first translates “notpatronymic” into “Notpatronymic” (since Notpatronymic is longer than Patronymic) and then into the wrong “NotPatronymic”.

Mangling of internal keywords patronymic, notpatronymic, surname and rawsurnames into patr2nymic, notpatr0nymic, surn2me, rawsurn0mes respectively solves the issue.

Please let me know if you see any issues with the proposed solution.

After some good discussion on the Pull Request, I think you have a great solution. Thanks for working on that!

I think next time, you can skip this post in discourse. If you want to have this level of conversation, @Nick-Hall has suggested we could use github’s discussions. But that isn’t turned on yet. Or just create the PR as you did. Developers will see your contribution and review.

Thanks again!

2 Likes

I think these types of discussions are highly valuable here, even though I am not a developer myself.

Why shouldn’t a non-developer be able to read or join a technical issue discussion? This is essential for learning purposes, but also because users often have a crucial perspective on how these features actually work in practice.

Furthermore, users should be able to participate and report issues to a greater extent WITHOUT being forced to use GitHub. Requiring a separate developer-oriented account just to contribute feedback creates an unnecessary barrier. Technical logic—like why a specific keyword is being replaced in the name editor—affects every user, and we should be able to discuss and influence these fixes right here in the forum.

3 Likes

@StoltHD I think you misinterpreted the intention of my comment. I only mentioned that @petr_fedorov need not post here too. Why not? Because no developer saw it. I think it is asking too much for developers to duplicate their work in two places.

In any event, the above description of a fix was incorrect, and there was a discussion on the issue, a related bug report, and the analysis that lead to the real solution. What was the final outcome? If you actually want to know any of that then you’ll want to read it here:

1 Like

Well, that is exactly my point. If the discussion only exists on GitHub, people like me—but who may not have a GitHub account—will never be able to learn the technical aspects of an issue. This, in turn, makes them less efficient at providing adequate information or helping out where we can.

Personally, I have no problem going to GitHub or Mantis to contribute if I know an issue actually exists. However, I refuse to spend my time chasing discussions across the numerous platforms Gramps now uses—be it mailing lists, GitHub, the Mantis bug tracker, Discourse, or social media like Reddit and Facebook.

I stopped following the different Facebook groups for Gramps, Reddit, and all the mailing lists years ago. To be effective, we need a centralized place where users and developers can actually meet without these unnecessary barriers.

I can take one very important example, and that is the time/period handling in Gedcom/Gramps and other genealogy systems, which is historically wrong and will end up falsifying historical timespans/periods. It feels like the developers used a template from MS Project or Artemis instead of historical logic.

Treating an ‘After December’ as a ‘Start No Earlier Than’ constraint is a catastrophic logical error. In project management, this constraint exists for resource planning—if a resource becomes available early, the task might start sooner. But history is not a project plan; it is fixed. ‘After December’ means January or later. By using project management logic, you are allowing a ‘float’ where events leak into a month the source has already defined as passed. This is project management, not genealogy.
I have added this to discussed here:

and here:

If I had been aware of these issues at the moment they were raised, I would have been screaming my throat out not to follow this historically incorrect way of interpreting time periods! For me, this has actually become a reason to reconsider the use of Gramps and other genealogy software altogether.


I didn’t misinterpret your comment; I am challenging the very logic that developers ‘don’t need’ to look where the users actually are and involve users and especially power users of a system.


Author’s Note: This text was originally written in Norwegian and later translated and edited for clarity with the assistance of Google AI. Some structural adjustments were made during the process to improve coherence, but all analytical content and conclusions remain my own.


Edit: I added some more info in a section of my writing.>

1 Like

What is your proposal?

Here is an idea: what if every time a Pull Request was created on github, it posted a message in the Developer topic here in discourse? It is possible, but I worry that it would put more burden on the contributors to follow two conversations.

The issue isn’t about setting up automatic notifications or ‘more posts’ for developers to follow. It’s about where the actual discussion and decision-making happen.

Technical programming discussions—like whether to use ‘if’ or ‘or’ in the code, or whether a function adheres to the Gramps standard—can certainly stay on GitHub or in a mailing list if some prefer.
However, if a technical choice (like the date logic) affects the historical integrity of the data, that discussion belongs here on Discourse where power users and historians can contribute—not hidden away in a GitHub Pull Request that 99% of users never see.

Relatively small bugfixes do not need a discussion here, but technical issues that can affect data and data integrity should. This is because there may be researchers, historians, or seasoned genealogists in this forum who do not frequent GitHub, Mantis, or the mailing lists.

My proposal is simple:
Before a technical path is locked in via a PR on GitHub, the core logic should be presented and discussed here on Discourse.
Ideally, these posts should use some form of ‘Attention’ tag, making it easier for users who are only visiting briefly to notice that a new, serious topic is being discussed.

This isn’t a ‘burden’; it’s quality insurance.
Involving users, and especially power users, at an early stage might prevent the corruption of historical data and other issues that a user or power user of the system will spot long before they even arise in the code—issues that at a later stage might become a real problem regarding data integrity or functionality.

A simple link from GitHub to a Discourse thread is a small task that could have prevented the catastrophic historical errors I mentioned earlier.

And just to be clear, I am not talking about someone wanting to add a new view that doesn’t alter the data or similar features; it is specifically when changes can or might have a direct impact on the data itself or core usage itself.


Author’s Note: This text was originally written in Norwegian and later translated and edited for clarity with the assistance of Google AI. Some structural adjustments were made during the process to improve coherence, but all analytical content and conclusions remain my own.

It seems that the first half of the discussion about some new bug should be here, in discourse, and the second (final) in Github. Those non-technical users who wants to follow the second part may join GitHub for this purpose. The migration to Github will happen as soon as PR is created there. Reference to the PR may be provided in discourse. Usually it will take some time between the first part of the discussion and creation of PR.

What I write is not a critique of you or what you have done in this specific case; it is about the general workflow.

While providing a reference to a PR is a step in the right direction, the problem is that ‘migrating’ to GitHub often means the functional logic is already being locked in. As I mentioned with the Project Management vs. Historical logic for dates, these are fundamental principles that need to be fully vetted here on Discourse before they are moved to a technical implementation on GitHub.

And in the specific case of dates and periods, those should never have been adopted from GEDCOM in the first place. By adopting a flawed standard without a deep functional discussion with power users and historians, we end up with the data integrity issues we see today.

If the functional discussion stops here the moment a PR is created, we risk losing the insight from those who can spot these issues long before they become hard-coded reality. We need to ensure that the logic remains a conversation here, while the code happens there."


Author’s Note: This text was originally written in Norwegian and later translated and edited for clarity with the assistance of Google AI. Some structural adjustments were made during the process to improve coherence, but all analytical content and conclusions remain my own.


At this moment I will stop, because I feel I start hijacking your post… sorry. "

There is a fallow RSS “Headline News” addon Gramplet in Gramps that might serve the purpose with some modification.
It is so seldomly updated that no one seems to use it. I tried launching it and it was stuck on “Loading Gramps Headline News…”. So the feed might be dead?

Say that RSS feeds were added from Discourse, GitHub issues, possibly the Gramps-Devel maillist. Perhaps the gramplet could be adapted to as a QuickView that runs in the Gramps minor alert window or launches an undocked Headline News gramplet from the Dashboard?

Add a different emoji (:megaphone:) than the Lightbulb :light_bulb: Warning to the status bar to indicate there is news? And have checkboxes for the each heading that less users persistently choose which Feeds they follow?