Hello Ekki, On 08/20/2010 11:25 PM, Ekki Plicht (DF4OR) wrote: > Two pre-requisites which I must fulfill in my webshop: > > 1.) I have to consider internationalisation (i18n) of my app. It has to serve > pages in 5 languages (today), probably more later. Language is depending on > browser header information or user choice.
Some things to consider: · Should the user be able to override the language? · Do you want to separate language by domain or URI part? > 2.) I must have 'speaking' URIs for better SEO. I.e. URIs like > /cars/volkswagen/sedan instead of /products?manufacturer=23&prodid=42. In > German that URI would probably be /fahrzeuge/volkswagen/limousinen. Other > example: > EN: /cars/rangerover/fourwheeldrive > DE: /fahrzeuge/rangerover/allrad > FR: /voitures/rangerover/tout-terrain > (All examples are fictious.) What would happen if someone who only accepts DE as language requests the EN page? Browser language detection is pretty easy with the I18N plugin, but the implementation of the language logic is dependent on what you want to happen. > Now, where does that leave me with the controller and dispatch actions? > > One idea comes to mind which is to use n different controllers, one for each > language (Controller::Cars, Controller::Fahrzeuge, Controller::Voitures > etc.). > In each controller the same list of actions is repeated (yuck!), each action > sub has it's counterpart in each other language. > Currently we have 234 entries in our product selection tree (i.e. navigation > tree) grouped into 12 major categories and several subcategories, up to 5 > levels deep. > WTF? Maintain 5 (or more) navig trees plus write 5 (or more) more or less > idetical controllers (one for each language) with ~234 action subs each. No > way! That's a maintenance nightmare. > > That cannot be a viable solution... Where am I wrong in my thinking? Both the language and the article to display are variables in the process of displaying the page. The language can come from a cookie, the browser language setting, a query parameter, the domain name, a part of the URI, or multiple of those using the first it can find. I'd always advise to build the actual business logic of the application outside of the web front-end. You can test it easier, and you'll often want to have access to it from outside anyway. Also, this keeps your controller logic small and only concerned with the interaction of model and view. If you have a path segment like '/car/brand/model' or something you can basically imagine it as a (pseudo) model call like: $ctx->stash(page => $ctx->model('ModelName')->find( lang => $ctx->stash->{language}, path => [...@segments], ); Which would be done in an action taking a variable number of arguments. Then your error handling (malformed or unknown paths, etc.) can be handled by your model as well. (Note: I omitted error handling in the above for simplicity) If you read your data from a database, a configuration file, or some flat-file hierarchy mostly depends on your needs (or rather: the needs of those who will maintain the content). > What I am envisioning is a central file where I (somehow, XML?, database?) > maintain a navigation tree (ok, 5 or more), mapping menu entries to URIs. > Some > process then maps these entries to actions. But how? As a model. Look at Config::Any (already used by Cat) for loading of configuration files. For a database model I'd point you towards DBIx::Class, but mostly because of community-size and personal preference. There are other solutions, but I feel it is a good start. Hooking the model into Catalyst is rather easy. You can take a look at the Catalyst::Model::* namespace on CPAN to get a feel for what's already there and what's possible. Also, take a look at Moose. It's the OO system that Catalyst is built on. You can reuse controller code just like any other code via inheritance and role-composition. And as said above, you shouldn't need that many actions in the first place. Code-repetition can usually be avoided in Catalyst. If you want to separate different stages of the request processing, Catalyst::DispatchType::Chained is a good way to do that. > Other ideas coming to my mind: > > - Create actions on the fly, mapped from the Menu/URI table. Is this possible > with Catalyst? AFAIK Catalyst checks all controllers at startup and builds a > list of actions only once - at startup... right? Right. If you want something to be dynamic, it's some kind of parameter most of the time. > - Have one controller per language and write a central dispatcher action, > which does nothing more than use the lookup table mapping menus to URIs? To > me > this has not the right feel, giving up all the nice dispatcher possibilities > of Catalyst... I usually let the Root controller have a base action that selects the language (either from the URI or however it is required), and a separate controller for content delivery that chains off the root's base and that takes its arguments and looks up the content from wherever. > - Put the navig tree in a separate view per language. Maintain n different > files when the tree changes. Still leaves me with the dispatcher issue. The view should (in my opinion) not care about the content it renders, only about its structure. There are exceptions, but they are rare. > - Maintain the navig tree somehow (XML, SQL) and write a small script which > produces the Conntrollers and actions from the data (plus a navig view for > each language)? No, I would definitely go the dynamic route. > Maybe I am just blind to see a radically different solution to my problem... > any takers? Basically I see no need to generate actions for each page at all, since you can have one action that takes multiple arguments and uses them to look up the content in the model. If you manage to design all of the business logic outside of the application, the Catalyst code becomes quite simple. regards, -- Robert 'phaylon' Sedlacek Perl 5 Consultant for Shadowcat Systems Limited - http://shadowcat.co.uk/ _______________________________________________ List: Catalyst@lists.scsys.co.uk Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/ Dev site: http://dev.catalyst.perl.org/