Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

URL rewrite in ASP.net for multi language

With the example URL:

www.domain.com/contact-us

Which renders in English. There are a set of other languages this website supports:

www.domain.com/es/contact-us
www.domain.com/jp/contact-us  
www.domain.com/de/contact-us
www.domain.com/pt/contact-us

Here is the re-write rule for English (default language)

<rewrite url="^/contact-us(\?(.+))?$" to="~/Pages/Contact.aspx$1" processing="stop"/>

How would I modify this/add a new rule to re-write:

www.domain.com/jp/contact-us  

To:

~/Pages/Contact.aspx?language=jp

Preferably without having to write a new rule, for every language for every content page!

To complicate things, it needs to match IETF language tags. These are varied enough that it looks like a regex to match them would be a difficult route: https://en.wikipedia.org/wiki/IETF_language_tag

Ideally I need to get the list of languages from the database, and match the language tag field on the fly. But I'm not sure how to do this as I've only ever written static rules.

like image 202
Tom Gullen Avatar asked Sep 27 '22 01:09

Tom Gullen


1 Answers

Solved this by writing my own URL rewrite module. Sample code for anyone who runs into similar problems is below. Decided to dump all other URL rewriting and route everything through this module instead.

Don't think this is easily possible with static rules.

public class DynamicURLRewrite : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.AuthorizeRequest += new EventHandler(context_AuthorizeRequest);
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }

    void context_AuthorizeRequest(object sender, EventArgs e)
    {
        var rw = new Rewriter();
        rw.Process();
    }
}

public class Rewriter
{
    public void Process()
    {
        using (MiniProfiler.Current.Step("Rewriter process"))
        {
            var context = HttpContext.Current;

            var rawURL = context.Request.RawUrl;
            var querystring = String.Empty;
            var urlParts = rawURL.Split('?');
            var url = urlParts[0];
            if (urlParts.Count() == 2) querystring = urlParts[1];
            if (url.StartsWith("/")) url = url.Substring(1);

            // Get language component
            Translation.Language inLanguage = null;
            {
                foreach (var lang in Translation.Language.GetAllLanguages())
                {
                    if (url.StartsWith(lang.LanguageTag, StringComparison.CurrentCultureIgnoreCase))
                    {
                        inLanguage = lang;
                        url = url.Substring(lang.LanguageTag.Length);
                        if (url.StartsWith("/")) url = url.Substring(1);
                        break;
                    }
                }
                if (inLanguage == null)
                {
                    inLanguage =
                        Translation.Language.GetLanguage(
                            Settings.Translation.ProjectReferenceVersionRequiredLanguageTag);
                }
            }

            // Querystring
            {
                if (!String.IsNullOrEmpty(querystring)) querystring += "&";
                querystring += "lang=" + inLanguage.LanguageTag.ToLower();
                querystring = "?" + querystring;
            }

            // Root pages
            {
                if (String.IsNullOrEmpty(url))
                {
                    context.RewritePath("~/pages/default.aspx" + querystring);
                    return;
                }
                if (url.Equals("login"))
                {
                    context.RewritePath("~/pages/login.aspx" + querystring);
                    return;
                }

And then some more complex rules:

            // Handlers
            if (url.StartsWith("handlers/"))
            {
                // Translation serving
                if(url.StartsWith("handlers/translations/"))
                {
                    var regex = new Regex("handlers/translations/([A-Za-z0-9-]+)/([A-Za-z0-9-]+).json", RegexOptions.IgnoreCase);
                    var match = regex.Match(url);
                    if (match.Success)
                    {
                        context.RewritePath("~/handlers/translation/getprojecttranslation.ashx" + querystring + "&project=" + match.Groups[1] + "&language=" + match.Groups[2]);
                        return;
                    }
                }
            }
like image 141
Tom Gullen Avatar answered Nov 13 '22 05:11

Tom Gullen