One of the things that I don't necessarily enjoy is messed up URL's. Don't get me wrong, I've done my part in creating some apps that create unreadable url's, but that doesn't mean that I liked it.
One of the issues we've had a work is part of CLF 2.0 (because it's a 2.0 world) where they talk about url's and how they should give equal treatment to both official languages when naming folders and files
. Now, having people talented at development and translation and have those translations jive with what the client feels is correct can be almost impossible. So having url's that are contained within an app is just a recipe for tons of QA and redeploys as discussions over the proper word happens.
Using annotations and spring's @RequestMapping
value attribute you can tie a controller or method of a controller to multiple url mappings. e.g. you can have your method run if someone hits home.html or maison.html The issue with this solution is 1) that your mapping is still within your code 2) you can't easily add support for another language.
Aside: stay with me on this one, I haven't worked through the issues like security. Andrew and I only came up with this last thing today.
Normally if you're using the @RequestMapping annotation you need to have the DefaultAnnotationHandlerMapping bean configured. This is what connects the url's coming into the app with the annotations configured. On start up it "registers" all the annotations. What you can do is have an external data store (property files, db, it doesn't matter) that will contain all the accepted urls for what's contained in the annotation.
Example:
public class MultilingualAnnotationHandlerMapping extends DefaultAnnotationHandlerMapping {
// TODO inject into bean
private String suffix = ".html";
// TODO inject as well, for both possibily have them as a Collection
private String prefix = "/";
@Override
protected void addUrlsForPath(Set<String> urls, String path) {
// this map you get from another service / file etc. Either cache it on this bean or somewhere else.
Map<String, Collection<String>> urlMapping = // ...
// the path is the thing that's found in the annotation
if (urlMapping.containsKey(path)) {
Collection<String> languageUrls = urlMapping.get(path);
// register each url
for (String url : languageUrls) {
super.addUrlsForPath(urls, buildKey(url));
}
}
// make sure we also add the original path as well
super.addUrlsForPath(urls, path);
}
private String buildKey(String path) {
return prefix + path + suffix;
}
}
Now in your controller class, you can just put in a something like @RequestMapping("my.admin.controller.key")
and have the urlMapping object above populated with a list of all the different translations for that key. eg. You can have key "my.admin.controller.key" point to [home, maison, casa], etc. You can even leave it to the original home.html as your key and just add mappings for the other languages.
This solution only helps solve the different translations coming in, it would still be required to have a tag lib or EL function or something that would put the correct name into your jsp or whatever. But having done this you can have the app provide meaningful urls to all the users, rather than a subset or none.
I'm actually hopeful that this solution would work well. ;-)
Personally, I don't think most regular users care about the URL. I really don't think most people are looking there. I can understand making the domain name multilingual, but further than that is just kind of pointless, as most users won't be typing in URLs anyway. There should be a switch language link on every page, but nobody really wants to go editing urls to switch languages.
ReplyDeleteThe funny stipulation as pointed out here (http://www.tbs-sct.gc.ca/clf2-nsi2/clfs-nnsi/clfs-nnsi-1-eng.asp#cn_2_pa) is that if you don't use words at all in your folder names then you don't have to translate at all. This means that if you take the easy way out, that you aren't even generating human readable urls, but you are perfectly within the guidelines.
Also, the spec seems to be focused on folder and file names. In the framework you're using, and in many of the popular MVC frameworks, there are no folders and files, but rather paths that map to some controller. in many cases, there will be no file name at all.
Anyway, I think you have a pretty good solution. I would, if possible put the URL mappings in a database so that you don't have to recompile or change any actual files if somebody has a problem with the way a URL is named. Even if you don't have a live database with this information, it's probably a good idea to just have this information in an offline database or flat file, so that you can autogenerate the part of the JSP file that defines the different URL mappings, without editing the JSP file itself.
I think that readable url's are useful for a bunch of reasons.
ReplyDelete1) much nicer when you're cutting / pasting into email or IM
2) can use in marketing material much easier
3) for web analytics you can easily see what's being hit from the logs etc
4) why make it long when you can make it short? :-P
As for the folders / files part of the spec - in gov't don't assume that the people writing the spec understand the current technology (as of 10 years ago).
I don't really what you mean by an "offline database", but ya, the idea was to stick these translations into the db. "What you can do is have an external data store (property files, db, it doesn't matter) ..."
I'm also not clear what you mean by "autogenerate the part of the JSP file that defines the different URL mappings". The jsp gets turned into a servlet -> java file -> .class file. I'm not sure if that's how asp works or if it's more of a script that gets run each time.
By offline database, I mean a database that only exists while you're building the application, and isn't there when you deploy this application to the internet. Use the information in the database to help generate some source code, so that when you compile it, all the right routes are there in the code.
ReplyDeleteAlso, by autogenerate, I mean, write code that writes the code for you. I'm not to familiar with exactly how everything gets wired up in JSP, so if you need the actual paths in some string somewhere in your file, then it would help to be able to run a script, which would generate that part of the class for you. .Net has partial classes, so you can put part of a class in another file. The part that's created by a program could be put in another file, and then you don't even have to look at that code unless there's something going weird. In .Net this partial class stuff is useful when you have a form, and all the stuff that defines the layout of the form is put in some file that you never look at, while all the control handling functions are placed in another file.
I do think that having readable URLs is very useful. However, I don't think that the standard is trying to promote readable URLs, or is it trying to make things easier for the user. Let's take a look at the URL I posted in my previous post.
http://www.tbs-sct.gc.ca/clf2-nsi2/clfs-nnsi/clfs-nnsi-1-eng.asp#cn_2_pa
For anybody who doesn't actually work for the government, that URL is complete gibberish. Completely unreadable. Even just the domain name would be hard for most people to remember. Because of the rules that govern that you must have paths for both languages, or that paths must contain both languages, they have made each directory in the form eng-fra, which means that the URL is twice as long as it needs to be. I realize what the intent might have been in this spec, but rarely have I seen a government site with readable urls like you would find at StackOverflow, or some other MVC site.