Complex URL schema with i18n and l10n

Splash Forums Rewrite Users Complex URL schema with i18n and l10n

This topic contains 13 replies, has 3 voices, and was last updated by  detestable 4 years, 11 months ago.

Viewing 14 posts - 1 through 14 (of 14 total)
  • Author
    Posts
  • #18361

    detestable
    Participant

    We are starting a web project in jee and I’m trying to evaluate if rewrite can be used for our rewriting needs.

    Despite the lack of documentation we are quite interested in your plugin because of it’s flexibility and configurability.

    In our project we need to have information in URL that inform us on the place where resids the visitor and on the language he speaks.

    Here is the schema :

    [ISO 3166-1].domain.com/[ISO 639-1/]path/subpath[…]

    https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2

    https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes

    For exemple for united states we would have something like :

    us.domain.com

    for root path.

    In the case of Switzerland where 4 languages are spoken (french, italian, german and romansh) :

    ch.domain.com/fr/

    ch.domain.com/it/

    ch.domain.com/de/

    ch.domain.com/rm/

    The rule is simple, if we have only one official spoken language in the country we won’t append the language code at the beginning of the path.

    The best example I found to achieve this is the domain showcase which would handle the case of [something].domain.com but I’m quite afraid by the optional part with the language code.

    Is this possible to realize with ocpsoft rewrite?

    #22537

    Hi there,

    Yes this sounds doable quite easily :) It might take a little creativity but this should work fine. It’s made much easier still since you know which languages you need to support in each country, thus you can specify constraints to ensure that they are correct.

    If you post a little more of your URL-schema and requirements, I can try to help you learn to build the rules.

    ~Lincoln

    #22538

    detestable
    Participant

    Wow cool, good news!

    If think the most complex part of our needs is the optional part at the beginning of the path.

    For the subdomain part, the showcase is quite explicit and a rule like this should do the job :

    @Override
    public Configuration getConfiguration(final ServletContext context) {
    return ConfigurationBuilder
    .begin()
    .defineRule()
    .when(Domain.matches("{subdomain}.domain.com")
    .where("subdomain")
    .bindsTo(El.property("#{clientStuff.subdomain}"))
    .and(DispatchType.isRequest()));
    }

    With this kind of bean :

    // (we are using CDI instead of JSF container)
    @Named
    @SessionScoped
    public class ClientStuff implements Serializable {

    private String subdomain;

    public String getSubdomain() {
    return this.subdomain;
    }

    public void setSubdomain(String subdomain) {
    // BTW, when testing, this setter is called twice (a System.out.println would produce 2 output for a call on en.domain.com for example)
    this.subdomain = subdomain;
    }
    }

    When testing I made an other HttpConfigurationProvider for other mappings :

    @Override
    public Configuration getConfiguration(ServletContext t) {
    return ConfigurationBuilder.begin()
    .addRule(Join.path("/").to("/WEB-INF/jsf/index.xhtml"))
    .addRule(Join.path("/login").to("/WEB-INF/jsf/login.xhtml"))
    /* And so on ... */;
    }

    Which would work flawlessly for :

    en.domain.com

    en.domain.com/login

    uk.domain.com

    uk.domain.com/login

    (And so on)

    Now for the optional part of the path for the language I’m clueless.

    Let’s stick with Switzerland example, we know that subdomain “ch” would involve 4 possibilities :

    de, it, fr and rm =>

    ch.domain.com/de/

    ch.domain.com/de/login

    ch.domain.com/it/

    ch.domain.com/it/login

    (And so on)

    I need to get the “de” or “it” without confusing with the “login” information.

    Shall I add a ConfigurationProvider that would act “between” the domain configuration and the path configuration?

    Ooh, while writing an idea comes to me, I could inject my ClientStuff in my configuration provider and rebuild the rules but I’m afraid to loose some flexibility. I’ll give a try and come back with what I did.

    Thanks for your answer!

    #22539

    Why not do this? :)

    Add another rule in your routing config:

    @Override
    public Configuration getConfiguration(ServletContext t) {
    return ConfigurationBuilder.begin()
    .addRule(Join.path("/{lang}").to("/WEB-INF/jsf/index.xhtml").where("lang").matches("(de|fr|it|rm)"))
    .addRule(Join.path("/{lang}/login").to("/WEB-INF/jsf/login.xhtml").where("lang").matches("(de|fr|it|rm)"))
    /* And so on ... */;
    }

    Would that do what you want?

    ~Lincoln

    #22540

    detestable
    Participant

    Finaly I failed with my idea.

    Your configuration works perfectly when there is the need of a /{lang} in the path but in order to handle for example en.domain.com (I don’t want a /{lang} in that case) it won’t match.

    I have the feeling that I’ll need to build custom rules depending on the subdomain.

    What do you think?

    Thank you again!

    [EDIT]

    I justed noticed the Add another rule in your reply,

    Then I understand I have no choice, I’ll have to create different rules depending on the subdomain.

    Thank you a lot for your support!

    I may came back for some other questions later!

    #22541

    Well, I don’t know that you’ll have to create different rules based on the subdomain – remember that you can also create your own entirely custom rule objects! You don’t need to stick with what is in Rewrite servlet config.

    You can create your own rule (take a look at Join if you need an example.) It’s pretty straightforward. Just create the custom behavior you need with any combination of new or existing rules/conditions/operations! :)

    So again, don’t feel limited by the existing rules. Just create your own composite rule.

    #22542

    detestable
    Participant

    The aim was to avoid writing

    .addRule(Join.path("/{lang}").to("/WEB-INF/jsf/index.xhtml").where("lang").matches("(de|fr|it|rm)"))

    +

    .addRule(Join.path("/").to("/WEB-INF/jsf/index.xhtml")

    to avoid having 2 rules to maintain in the case of changes, but I’ll stick with this solution for the moment which does exactly what I needed!

    Many thanks!

    #22543

    You’re welcome!

    We can always make improvements :) How would you like to see this work, in terms of syntax?

    What do you think?

    ~Lincoln

    #22544

    detestable
    Participant

    Hmmm, may be my case is quite specific, but it would be possible to handle it with regexes.

    What do you think about a full regex rule like this :

    private static final String pathExpr = "(?<lang>de|fr|it|rm)";
    private static final String rootLangPath = "^(/" + pathExpr + ")?";

    @Override
    public Configuration getConfiguration(ServletContext t) {
    return ConfigurationBuilder.begin()
    // Binds lang once for all
    .addRule(Regex.path(rootLangPath + ".*") // permissive regex
    .where("lang")
    .bindsTo(El.property("#{langBean.lang}")))

    // Index rule
    .addRule(Regex.path("^/" + pathExpr + "?$")
    .to("/WEB-INF/jsf/index.xhtml"))

    // Login rule
    .addRule(Regex.path(rootLangPath + "/login$")
    .to("/WEB-INF/jsf/login.xhtml"))

    // Logout rule
    .addRule(Regex.path(rootLangPath + "/logout$")
    .to("/WEB-INF/jsf/logout.xhtml"))
    /* And so on ... */;
    }

    I have to admit that it looks like patchwork but it allows us to handle one rule per path, with our optional lang.

    #22545

    I don’t see the harm in multiple rules – I think you’re probably better off and more maintainable with the former. Not to mention that you lose out on the outbound URL-rewriting with your regex approach.

    #22546

    However, we could possibly add something like:

    Join.paths("/login", "/{lang}/login").to("login.xhtml").where("lang").matches(...)

    That might be nicer. The outbound URL would be selected based on order and availability of named parameters (‘lang’ in this case.)

    #22547

    I’m not sure I like this. And this only works if the number of parameters are different for each pattern, right? And it’s not easy to understand what is happening behind the scenes so it may confuse people.

    I for myself prefer to have a single URL for a page. If there are alternative URLs they should be redirected to the correct one. That’s a pattern that makes most sense IMHO.

    Just my two cents. :)

    #22548

    Yeah, I agree.

    #22549

    detestable
    Participant

    I’m finaly joining you as most of the time URLs depends on i18n.

    Thank you for your support!

Viewing 14 posts - 1 through 14 (of 14 total)

You must be logged in to reply to this topic.

Comments are closed.