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
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:
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.
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:
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.
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:
In Examine it would probably make sense adding a
firstLetter
field that follows traditional "Western" alphabets. And then an extra field likefirstLetter_cy
for Welsh.So for the English site you would search for
firstLetter:{letter}
, butfirstLetter_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:
Hope that helps 😉
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.
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:Oh, that's nice! Really useful. Thanks for your help with this :)
#h5yr
O.
is working on a reply...