Add a way to load the hierarchy tree and get a language children.

Created on 22 February 2023, almost 2 years ago
Updated 23 February 2023, almost 2 years ago

Problem/Motivation

I have the following structure of languages:

en
--en-NA(North America)
----en-US
----en-CA

I have to handle with nodes being created in en and falling back to en-US for example, so sometimes, I have to find out the children of a node, eg: An node en has the following children: en-NA, en-US, en-CA, I think this kind of stuff should be inside the language hierarchy module, the module already have a language_hierarchy_get_ancestors function, that loads the "parents" of a language. And one more thing that could be usefull at least for me is to return the tree of languages, it would help me a lot since sometimes I have to build it manually.

Proposed resolution

Add a language_hierarchy_get_children function to return the children languages of a language and a language_hierarchy_tree to return all the hierarchy tree.

Remaining tasks

  1. Review
  2. RTBC
Feature request
Status

Needs work

Version

2.0

Component

Code

Created by

🇧🇷Brazil murilohp

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @murilohp
  • Status changed to Needs review almost 2 years ago
  • Status changed to Needs work almost 2 years ago
  • 🇬🇧United Kingdom james.williams

    Nice idea in general; thanks for contributing! I'm curious to understand your use case, please could you explain how you will be using these functions? I'd love to better understand how people use this module's functionality.

    As for the actual implementation, it could definitely be more performant. Instead of loading and iterating across every language in language_hierarchy_get_children(), I would think entity queries could be used to do breadth-first searches across children. Something along the lines of the following, to get direct children, then querying in the same way for each child and onwards.

      $child_language_ids = \Drupal::entityQuery('configurable_language')
        ->condition('third_party_settings.language_hierarchy.fallback_langcode', $language->getId())
        ->execute();
    

    The structure of what you return from language_hierarchy_tree() is also interesting. It doesn't look like the kind of structure I might expect to be returned for general purposes (e.g. it doesn't look much like what is returned from other tree-fetching code in core, such as for menus or taxonomy terms). But again, it might help us to understand how you're using this function.

  • Status changed to Needs review almost 2 years ago
  • 🇧🇷Brazil murilohp

    please could you explain how you will be using these functions?

    Sure! Well, as I mentioned, we have some language structure as described on the IS, and inside my project, content editors have the ability to create a single en node, and this node will be available in en-US and en-CA for example, and this is working fine, but we're also working with simple xml sitemap , and thinking about the SEO of the site, I have to map, for each node all the languages available, and make a structure shows the node with all available languages, so, every time that I have to generate the sitemap, I have to search for the children languages of each node.

    I would think entity queries could be used to do breadth-first searches across children.

    Wow, thank you so much, I didn't had enough time to validate the performance and your suggestion is definitely a better way, here's a new patch! Just for you know, if I have the following structure:

    en
    --en-NA(North America)
    ----en-US
    ----en-CA
    

    If I want to know the children of en, the first time I execute:

    $child_language_ids = \Drupal::entityQuery('configurable_language')
        ->condition('third_party_settings.language_hierarchy.fallback_langcode', $language->getId())
        ->execute();
    

    I'll get something like:

    ^ array:1 [▼
      "en-NA" => "en-NA"
    ]
    

    So I'll have to keep loading each language children until none children is found, so I've changed the function to be recursive, what do you think?

    The structure of what you return from language_hierarchy_tree() is also interesting

    Yeahh, I know it's not a common thing and just for you know, I had to do something quick, as mentioned, I'm working with sitemap, and having a function to get all languages with their parents and children would help me a lot, since I have the langcode of the node then I just need to access the array key of the language to have all the stuff I need. I think we can discuss how we could have this tree, and maybe I can move this into a custom module of mine if this makes sense.

    Moving this back to NR to see your thoughts here.

  • Status changed to Needs work almost 2 years ago
  • 🇬🇧United Kingdom james.williams

    Ah, so this is for a sitemap... funnily enough, I've coded a custom solution myself for this very problem! I've attached my code, in case it helps. I don't know whether there's a sensible one-size-fits-all approach - or something configurable enough to cover most use cases - that could just become an addition to language_hierarchy, (or a sub-module for it). I find with SEO issues, everyone has subtly different requirements so making an 'opinionated' solution isn't always good (which is also why I never contributed my custom solution back before).

    FYI - my client project used a 'field_hide_translation' field to allow blocking access to certain translations, so that's in there, but couldn't really work in a general-purpose solution (though perhaps an alternative could be found).

    I've changed the function to be recursive, what do you think?

    Yes, that makes good sense. I'm still not sure about the format of the array that is returned though; it's currently just a 'flat' array as opposed to a nested structure? What order is it in? etc.

    Also relevant: there's some code in language_hierarchy_form_language_admin_overview_form_alter() which builds up a 'flattened' tree as well. (That one was using a similar approach to your previous patch, so no doubt could be improved too.)

  • 🇬🇧United Kingdom james.williams

    Oh I might as well add a little bit more from my client project; I used hook_simple_sitemap_url_generators_alter() to respect that 'field_hide_translation' field. I think that other hook might have relied on this too.

Production build 0.71.5 2024