Yesterday we had a Play 2.0 presentation at our local JUG but we couldn't figure out whether it is possible to have localized URLs (for SEO purposes).
For example /help, /hilfe etc should point to the same controller but the template should be rendered with different language content.
Is there any way to do this in Play 2.0?
I like your question, because it was creative at least for me :) Check this approach it works for me:
conf/routes:
GET /help controllers.Application.helpIndex(lang = "en")
GET /hilfe controllers.Application.helpIndex(lang = "de")
GET /help/:id controllers.Application.helpTopic(lang = "en", id: Long)
GET /hilfe/:id controllers.Application.helpTopic(lang = "de", id: Long)
controllers/Application.java:
public static Result helpIndex(String lang) {
return ok("Display help's index in " + lang.toUpperCase());
}
public static Result helpTopic(String lang, Long id) {
return ok("Display details of help topic no " + id + " in " + lang.toUpperCase());
}
views/someView.scala.html:
Help index<br/>
Hilfe index<br/>
Help topic no 12<br/>
Hilfe topic no 12
(This is different approach than in previous answer, therefore added as separate one)
You can also create some kind of mapping table in DB where you can store full paths to records with different params:
urlpath record_id lang
/help/some-topic 12 en
/hilfe/ein-topic 12 de
than in conf/routes file you need to use rule allowing you to use Dynamic parts spanning several / (see routing doc) ie:
GET /:topic controller.Application.customDbRouter(topic:String)
You can also mix both - standard routing mechanismus with custom one by placing above rule at the end of your conf/routes file if no 'static' rule will be available, then it will try to find it in mapping table or will return notFound() Result.
You use from GlobalSettings.onHandlerNotFound() and check if the is a translated version of the url. Then you can make a redirect. However this ends with urls in default language.
More cleaner would be to use the GlobalSettings.onRouteRequest where you can implement your own logic to get the handler.
Furthermore you can create your own router. There was a discussion about it at google-groups with a scala solution.
It was possible in Play 1.2.x, not in 2.x as far as I know. I mean, it's not possible without duplicating the mappings in your file, adding one for EN, one for DE, etc.
A simpler alternative for SEO may be to "fake" the urls in your Sitemaps file.
So your Routes file has
GET /action/:param/:seo-string Controller.methodAction(param)
so seo-string will be ignored in processing, and you generate several links on your Sitemaps file:
/action/1/english-text
/action/1/german-text
This would set the search engines. For users, so they see the url in the right language, you could change the URL using HTML 5 history.
It's extra work, but if you really want it...
Related
I was wondering whats the best approach to have a hierarchical structured urls such as for example:
If i have 3 categories
-Cateogory1
--Category2
---Category3
I would like the urls to resolve to
/category1
/category1/category2
/category1/category2/category3
I am also using jms_i18n_routes to support locales in the routes. I have the SymfonyExtraBundle already enabled. The only way i see for now is just to create a new router and add it to the list of routers but the problem is the jms_i18_router extends the symfony default router so if i do that i will be able to have internationalized urls for all the default routes but not for this custom router, which means i will have to copy the functionality which i already have into the new router (pretty pointless)
Furthermore if I add this router for a category hierarchy, I will probably have to have different versions of it for different entity types in addition to categories where i want this functionality (or have one giant if statement to check for each scenario) - neither solution seems very elegant to me, so I was wondering what are your thoughts on the matter?
Thanks!
you can do this by setting rout repetitive pattern, use regular expression on the "requirements" part of rout, similar this:
# categories rout:
categories:
pattern: /{cat}
defaults: { _controller: HelloBundle:Default:categories }
requirements:
cat: (category[1-9]\/)+
notice:
you should recognize slashes on $cat variable on the "categoriesAction" function.
of course if you want make dynamic hierarchical URL from non-ascii characters and make this URL from persisted entities i think you can do this by create URL from a ascii entity field such as entity-id or other entity-special-keys.
I am using ColdFusion 9.
I am creating a brand new site that uses three templates. The first template is the home page, where users are prompted to select a brand or a specific model. The second template is where the user can view all of the models of the selected brand. The third template shows all of the specific information on a specific model.
A long time ago... I would make the URLs like this:
.com/Index.cfm // home page
.com/Brands.cfm?BrandID=123 // specific brand page
.com/Models.cfm?ModelID=123 // specific model page
Now, for SEO purposes and for easy reading, I might want my URLs to look like this:
.com/? // home page
.com/?Brand=Worthington
.com/?Model=Worthington&Model=TX193A
Or, I might want my URLs to look like this:
.com/? // home
.com/?Worthington // specific brand
.com/?Worthington/TX193A // specific model
My question is, are there really any SEO benefits or easy reading or security benefits to either naming convention?
Is there a best URL naming convention to use?
Is there a real benefit to having a URL like this?
http://stackoverflow.com/questions/7113295/sql-should-i-use-a-junction-table-or-not
Use URLs that make sense for your users. If you use sensible URLs which humans understand, it'll work with search engines too.
i.e. Don't do SEO, do HO. Human Optimisation. Optimise your pages for the users of your page and in doing so you'll make Google (and others) happy.
Do NOT stuff keywords into URLs unless it helps the people your site is for.
To decide what your URL should look like, you need to understand what the parts of a URL are for.
So, given this URL: http://domain.com/whatever/you/like/here?q=search_terms#page-frament.
It breaks down like this:
http
what protocol is used to deliver the page
:
divides protocol from rest of url
//domain.com
indicates what server to load
/whatever/you/like/here
Between the domain and the ? should indicate which page to load.
?
divides query string from rest of url
q=search_terms
Between the ? and the # can be used for a dynamic search query or setting.
#
divides page fragment from rest of the url
page-frament
Between the # and the end of line indicates which part of the page to focus on.
If your system setup lets you, a system like this is probably the most human friendly:
domain.com
domain.com/Worthington
domain.com/Worthington/TX193A
However, sometimes a unique ID is needed to ensure there is no ambiguity (with SO, there might be multiple questions with the same title, thus why ID is included, whilst the question is included because it's easier for humans that way).
Since all models must belong to a brand, you don't need both ID numbers though, so you can use something like this:
domain.com
domain.com/123/Worthington
domain.com/456/Worthington/TX193A
(where 123 is the brand number, and 456 is the model number)
You only need extra things (like /questions/ or /index.cfm or /brand.cfm or whatever) if you are unable to disambiguate different pages without them.
Remember: this part of the URL identifies the page - it needs to be possible to identify a single page with a single URL - to put it another way, every page should have a unique URL, and every unique URL should be a different page. (Excluding the query string and page fragment parts.)
Again, using the SO example - there are more than just questions here, there are users and tags and so on too. so they couldn't just do stackoverflow.com/7275745/question-title because it's not clearly distinct from stackoverflow.com/651924/evik-james - which they solve by inserting /questions and /users into each of those to make it obvious what each one is.
Ultimately, the best URL system to use depends on what pages your site has and who the people using your site are - you need to consider these and come up with a suitable solution. Simpler URLs are better, but too much simplicity may cause confusion.
Hopefully this all makes sense?
Here is an answer based on what I know about SEO and what we have implemented:
The first thing that get searched and considered is your domain name, and thus picking something related to your domain name is very important
URL with query string has lower priority than the one that doesn't. The reason is that query string is associated with dynamic content that could change over time. The search engine might also deprioritize those with query string fearing that it might be used for SPAM and diluting the result of SEO itself
As for using the URL such as
http://stackoverflow.com/questions/7113295/sql-should-i-use-a-junction-table-or-not
As the search engine looks at both the domain and the path, having the question in the path will help the Search Engine and elevate the question as a more relevant page when someone typing part of the question in the search engine.
I am not an SEO expert, but the company I work for has a dedicated dept to managing the SEO of our site. They much prefer the params to be in the URI, rather than in the query string, and I'm sure they prefer this for a reason (not simply to make the web team's job slightly trickier... all though there could be an element of that ;-)
That said, the bulk of what they concern themselves with is the content within and composition of the page. The domain name and URL are insignificant compared to having good, relevant content in a well defined structure.
I have a news section where the pages resolve to urls like
newsArticle.php?id=210
What I would like to do is use the title from the database to create seo friendly titles like
newsArticle/joe-goes-to-town
Any ideas how I can achieve this?
Thanks,
R.
I suggest you actually include the ID in the URL, before the title part, and ignore the title itself when routing. So your URL might become
/news/210/joe-goes-to-town
That's exactly what Stack Overflow does, and it works well. It means that the title can change without links breaking.
Obviously the exact details will depend on what platform you're using - you haven't specified - but the basic steps will be:
When generating a link, take the article title and convert it into something URL-friendly; you probably want to remove all punctuation, and you should consider accented characters etc. Bear in mind that the title won't need to be unique, because you've got the ID as well
When handling a request to anything starting with /news, take the next part of the path, parse it as an integer and load the appropriate article.
Assuming you are using PHP and can alter your source code (this is quite mandatory to get the article's title), I'd do the following:
First, you'll need to have a function (or maybe a method in an object-oriented architecture) to generate the URLs for you in your code. You'd supply the function with the article object or the article ID and it returns the friendly URL with the ID and the friendly title.
Basically function url(Article $article) => URL.
You will also need some URL rewriting rules to remove the PHP script from the URL. For Apache, refer to the mod_rewrite documentation for details (RewriteEngine, RewriteRule, RewriteCond).
I'd like to be able to change the extension of a url and recieve the model in a different format.
e.g. if
/products/list
returns a html page containing a list of products, then
/products/list.json
would return them in a json list.
Note: I like the simplicity of the ASP.NET MVC REST SDK, it only requires about 5 lines of code to hook it in, but the format is specified as a query string parameter i.e. /products/list?format=json which is not what I want, I could tweak this code if there are no other options, but I don't want to reinvent the wheel!
I wrote a blog post that shows one possible example. It's a tiny bit complicated, but might work for your needs.
http://haacked.com/archive/2009/01/06/handling-formats-based-on-url-extension.aspx
You should be able to just use routes in conjunction with the rest sdk
If you have the flexibility to drop Apache or something similar in front of your service, you can always use mod_rewrite to rewrite an external http://products/list.json into http://products/list?format=json which your framework can render more easily.
Instead of "list.json", you could choose "list/json" and use a route like
{controller}/{action}/{id}
Then ProductController.List would be called, with an ID parameter of "json". The .List() action then would decide whether or not to return an HTML view or JSON content.
I would like to develop URL's which look like the following:
http://mysite.com/products/1/best-product-in-the-world
Where all i need to get to the proper record is the following route:
http://mysite.com/products/1
When I add the product description piece to the URL ("best-product-in-the-world") I get URL encoding issues. I've tried to use Server.UrlEncode when constructing this portion of my URL in an ActionLink(...):
<%= Html.ActionLink(item.Subject, "../Post/Detail",
new { id = item.ID,
descriptiveUrl = Server.UrlEncode(Product.ShortDescription) },
new { rel = "canonical",
title = Product.ShortDescription,
#class = "product-hyperlink" })%>
But this renders regularly encoded elements for special characters and spaces, much like the following:
http://localhost:2392/Products/Detail/1/best+product+in+the+world253f
...which creates a 400, bad request exception. Not sure I've done the question justice, but can provide further clarification if need be.
Update: this post's URL is as follows, and i'm trying to do something very similar!
http://stackoverflow.com/questions/1148955/creating-search-engine-friendly-urls-in-asp-net-mvc
In a deeper Google search, I found the following link for generating slugs:
http://www.intrepidstudios.com/blog/2009/2/10/function-to-generate-a-url-friendly-string.aspx
Thanks #Rob and #Coding the Wheel for giving me the terminology I really needed to find this answer!
A simple option would be to add a property to your model object with an accessor that normalises the appropriate field (short description in this case) down to a suitable "slug"; that is, the bit of junk text after the identifier. You then use this when constructing the URI.
The normalisation process might be as simple as removing any non-alphanumeric characters and replacing spaces with hyphens.
The standard practice here is to store a 'slug' with each post that will function as the post's outward-facing URL. For example, your slug for the above post would be:
best-product-in-the-world
A decent CMS will do this for you automatically, and allow you to tweak the slug before saving.