Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Owain Williams 480 posts 1412 karma points MVP 6x c-trib
    Apr 20, 2023 @ 15:01
    Owain Williams
    0

    How to create a filterable multilingual alphabet list

    Hey everyone,

    I've an interesting problem I'm looking for some help with. I've been tasked with creating a page that has a filterable list of items on it. This list of items can then be fitlered by the letter it starts with via a list of letters. e.g.

    A - B - C - D - E - F - G ......

    If you click on the "B" then you see all items that start with a "B".

    Now the really interesting bit comes in when this list has to also work on a Welsh version of the site and the Welsh alphabet is different to the English alphabet e.g.

    A - B - C - CH - D - DD - E - F - FF ....

    Has anyone done anything like this before and if so, how did you solve it?

    I'm thinking I might need to add a custom field in Examine which reads the title of the page to see if it starts with a letter and then check if the letter is repeated to allow my to attach DD for example.

    I also need to think of a way to display the alphabet depending on culture.

    There is also sub filtering to be done on this too, so if you click on D and then there is a sub filter of "News items", then I would only see news items that start with the letter D.

    This is my problem and all thoughts welcome as this is a tough one :D

    O.

  • Anders Bjerner 487 posts 2989 karma points MVP 7x admin c-trib
    Apr 20, 2023 @ 15:45
    Anders Bjerner
    1

    I think you're on the right track with your description. If you don't care about the casing of the first letter (which you probably don't for this kind of search), you can get the first letter something like:

    using System;
    using System.Globalization;
    
    public class Program
    {
    
        public static readonly CultureInfo Welsh = CultureInfo.GetCultureInfo("cy");
    
        public static readonly CultureInfo English = CultureInfo.GetCultureInfo("en-GB");
    
        public static void Main()
        {
    
            Console.WriteLine(GetFirstLetter("HelloWorld", English));
    
            Console.WriteLine(GetFirstLetter("Ddyrchafedig", English));
    
            Console.WriteLine(GetFirstLetter("Ddyrchafedig", Welsh));
    
        }
    
        public static string GetFirstLetter(string value, CultureInfo culture) {
    
            if (value.Length == 0) throw new Exception("Computer says no!");
    
            value = value.ToLowerInvariant();
    
            if (value.Length == 1) value.Substring(0, 1);
    
            if (culture.TwoLetterISOLanguageName == "cy") {     
                if (value[0] == 'c' && value[1] == 'h') return "ch";
                if (value[0] == 'd' && value[1] == 'd') return "dd";
                if (value[0] == 'f' && value[1] == 'f') return "ff";
                if (value[0] == 'n' && value[1] == 'g') return "ng";
                if (value[0] == 'l' && value[1] == 'l') return "ll";
                if (value[0] == 'p' && value[1] == 'h') return "ph";
                if (value[0] == 'r' && value[1] == 'h') return "rh";
                if (value[0] == 't' && value[1] == 'h') return "th";        
            }
    
            return value.Substring(0, 1);
    
        }
    
    }
    

    In Examine it would probably make sense adding a firstLetter field that follows traditional "Western" alphabets. And then an extra field like firstLetter_cy for Welsh.

    So for the English site you would search for firstLetter:{letter}, but firstLetter_cy:{letter} on the Welsh site.

    If you know what nodes are in a particular language, you could perhaps go with a single field instead. So in the indexing event, you check against the path to determine the site language, and then pass the culture on to the method as in my example.

    How to limit the search to news items only, it depends on how you determine the type. If each type has their own content type, you could check against the __NodeTypeAlias field.

    In terms of the raw Examine query, it would be something like:

    firstLetter:a AND __NodeTypeAlias:newsPage
    

    Hope that helps 😉

  • Owain Williams 480 posts 1412 karma points MVP 6x c-trib
    Apr 20, 2023 @ 15:54
    Owain Williams
    0

    Thanks Anders - ye, I already have the datatypes setup so can and currently to filter by using them.

    How would you output the full alphabet list on the front-end?

    One option I've seen is to create a constant which has all the letters of the alphabet in it, then you parse that - I guess I could do a comma separated string and the split that to give me all the individual letters.

  • Anders Bjerner 487 posts 2989 karma points MVP 7x admin c-trib
    Apr 20, 2023 @ 16:07
    Anders Bjerner
    100

    Declaring a static readonly array would somewhat be equal to a constant, which should in theory be better than splitting a string constant into an array.

    So I would probably create a GetAlphabet method like below:

    public static readonly string[] EnglishAlphabet = new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "X", "X", "Y", "Z" };
    
    public static readonly string[] WelshAlphabet = new string[] { "A", "B", "C", "CH", "D", "DD", "E", "F", "FF", "G", "NG", "H", "I", "J", "L", "LL", "M", "N", "O", "P", "PH", "R", "RH", "S", "T", "TH", "U", "W", "Y" };
    
    public static string[] GetAlphabet(CultureInfo culture) {
        if (culture.TwoLetterISOLanguageName == "cy") return WelshAlphabet;
        return EnglishAlphabet;
    }
    
  • Owain Williams 480 posts 1412 karma points MVP 6x c-trib
    Apr 20, 2023 @ 16:10
    Owain Williams
    0

    Oh, that's nice! Really useful. Thanks for your help with this :)

    #h5yr

    O.

Please Sign in or register to post replies

Write your reply to:

Draft