-
Posts
17,090 -
Joined
-
Days Won
1,638
Everything posted by ryan
-
It looks to me like you were logging in on the /processwire/login/logout/ page? Hitting that page always logs you out. You can login on any page just by pointing your browser to it... if you don't have access, you'll get a login form. So if you hit the /logout/ page and you aren't already logged in, you'll get a login form. The behavior is intentional (for all admin pages), but this particular iteration of it isn't useful and is confusing as you found out. I want to retain the behavior, but want to remove any links that might point one to experience that confusing behavior. What path did you take to get to the logout page? Did you reload it or click one of the links we're going to remove (mentioned in the previous messages)? Other than those instances, the only way I can duplicate this in Chrome (or other browser) is by pointing my browser to the /logout/ page when I'm not already logged in. Perhaps the update discussed earlier will solve this one too (since we'll redirect back to the login page), but just wanted to double check.
-
Glad you found it, and thanks for posting the solution. I love that site too... probably one of the most useful sites I come across regularly.
-
Hey guys, this makes sense to me. I'll plan to implement. I can't say as though I ever really logout of my PW installs, so have probably only seen the logout screen a handful of times. When all that stuff on the screen is drawn, they are actually still logged in (though by the time you see it, they aren't) so that's why you are seeing links to stuff that's not applicable. I'll put a redirect in between those which will solve that part of it.
-
@Ryan & Senior Members, Recommended Reading?
ryan replied to Crash-n-Burn's topic in Getting Started
Thanks for replying Antti! I agree with everything Antti said. Except for one thing: I don't recommend buying anything from SitePoint. They are an active supporter of spec work, which is bad for designers and bad for our industry. From their previous "SitePoint Contests" to their 99Designs.com company, they are taking advantage of the design community in a bad way. This isn't to say anything bad about their books or authors, just the company behind it. So buy their titles used. When it comes to books, I usually head over to Amazon and hunt through reviews. People learn differently and books communicate in different ways. I try and find the reviews from people that are looking for the same things I am, and focus in on the books that seem to have a solid set of positive reviews with like-minded individuals. I don't have any books that I feel are must-haves, but I generally like everything I've purchased from O'Reilly, APress, and Wrox. My only jQuery book is Learning jQuery 1.3, which I think is excellent, but I'm guessing it's been updated since then. While the two ProcessWire titles were a joke, I do think we will have a real book after a year or 2. If not through a well known publisher, then we'll self publish. My father owns/runs a design book publishing company, so lots of experience there to learn from. With regard to the 'Beginning ProcessWire' book: While much of the language and examples could be potentially upsetting to any females that might come across the book, and nearly every sentence either starts or ends with some variant of the F-word, there is much wisdom and wit to be found in it's pages as you can probably derive from the author's photo on the cover. Can't believe I forgot to mention PHP on the homepage. I have updated this so there are a couple of PHP mentions now. But seriously looking forward to Adam's work on the homepage. -
@Ryan & Senior Members, Recommended Reading?
ryan replied to Crash-n-Burn's topic in Getting Started
Thanks for your question and welcome to the forums. Can you tell me more about the types of books you are looking for? General web development books, or something more specific? I have a lot of books in my library, but very few recent stuff other than the Book Apart mini-books (CSS3, HTML5, Responsive Web Design). And just for fun, here's a couple of highly recommended books on ProcessWire (below) written by our forum members. -
This should not be the case. One can sort without moving. But please let me know if you find otherwise. Note that PW's PageList uses the "move" label to refer to both. As long as you don't change the parent, your "move" is considered a sort, behind the scenes. Once you change parent (i.e. drag to another branch), it's considered a "move" behind the scenes. And that's also how PW determines what permission to check. So using the term "move" is just to maintain simplicity at the UI level. I thought separate "move" and "sort" links would be confusing at this level. What you are describing should be the current behavior (at least, that is what's intended). It sounds like it didn't behave that way in your instance? If so, let me know how to reproduce. Here is the current logic that determines whether it's going to show a "move" link (whether that means sorting or changing parent): <?php if($page->moveable() || ($page->sortable() && $page->sortfield == 'sort')) { // show the 'move' link in the PageList } And here's how it determines what to do after you dragged a page. It will attempt both move and sort, but you can see it won't attempt the 'move' if the parent wasn't changed: <?php if($page->parent-> !== $newParent) { // user moved the page to another parent if($user->hasPermission('page-move', $page) && $user->hasPermission('page-add', $newParent)) { // user has access to to move the page to the new parent } } if($user->hasPermission('page-sort', $page->parent)) { // user has permission to sort this page and it's siblings // but we need to make sure this parent has children that aren't already presorted. if($page->parent->sortfield == 'sort') { // these children are not presorted // user can save the new order they dragged to } } When you edit a page with children, you'll see on it's children tab that it has a field where you can select an automatic sorting order. This is where $page->sortfield is set. If it's set to "sort" (the default value, aka no value selected) that means you can drag to sort them in any order. But if it's set to some other field, then you won't be able to drag to sort because it would violate the preset order. For instance, if you had a page of news items sorting by date, you wouldn't want users moving stuff out of that order. So this preset sortfield on the parent takes precedence even if you have page-sort access. You can see that in the code above. It's also worth nothing that "page-sort" permission needs to be assigned to the parent whereas "page-move" is assigned to the child. Since sorting a single page can feasibly affect the order of all siblings, I thought this permission belonged with the parent. Otherwise PW would need to check all the child pages for "page-sort" permission before you could sort any one of them... and that could lead to real confusion when one of the siblings was not like the others. But perhaps "page-sort" would more accurately be termed "page-sort-children". I think that makes sense. Though the intention with these links is that they will be pluggable (like anything else in PW), and modules can add additional links here if the given page calls for it. So it's feasible down the road that there might be a dozen possibilities of what links appear there, and I think that might be a lot to look at. But that's not the case now, so I will look at this more closely and experiment with it. I like your idea of an "create another one?" in the save notification, and will look at adding this. Also wanted to mention a time saving tip for when you have to add lots of pages. After adding your page (and publishing it if necessary) click the breadcrumb trail at the top for the parent. It should take you to the page list with that parent opened and a "new" link right there waiting for you to add another. Not quite as simple as the idea you mentioned, but still useful when adding lots of pages. Btw, 2.1 does this, but 2.0 doesn't (though Adam wrote a plugin that will do it in 2.0 among other things). Your debugging tool is really looking good–please keep us up to date. And you mentioned some stuff that you didn't yet know how to do, but I wasn't clear about what that was–please post questions any time. Also, if you are interested, I can show you how to develop this as a module so that you don't even have to put this in your templates (the module can slip it in there at page render time, in any template's output).
-
Technically these are two different actions. Moving among siblings is what the 'page-sort' permission refers to. Moving to other parents is what the 'move pages (change parent)' permission refers to. If you have one or the other, PW should let you drag the pages around in the PageList wherever you want. But it won't actually perform the move/sort unless you have access to do it (if you don't have access, you should get a javascript alert after you try). The reason for this is that I don't have PW communicating the permissions to javascript, but probably will eventually just to clarify where you can and can't move a page. The current outcome is that it may appear that you've moved a page even when the system didn't actually do it (due to lack of permission). Though you should get a javascript alert if that were the case. You could solve it by creating two roles. One that provides just the sort capability (to be added to your 'projects' template), and the other that provides the edit capability (to be added to your 'project' template). Then give both of those roles to the user. Still, creating two roles for the above scenario is more work than I want people to have to do. So you'll see that's why PW lets you define what roles can add pages below a given template (rather than the separate and deprecated page-add permission, which would have required two roles: one for page-add and another for page-edit). What I'll probably do is setup the permissions so that if you have access to add children below a given parent, and you have page-sort permission, then it'll let you sort the siblings. I think that would make the most sense, and be an expected behavior. I've not worked out all the scenarios, which is one reason why 2.1 is still in beta (even though I consider it stable otherwise). Feedback is much appreciated in this area, as we're in uncharted territory with some of this stuff. I just want to make sure it's as simple and clear as possible. You are right that's not the intended behavior. PW will let you drag it wherever in javascript, but did it actually perform the move in the system? (like after reloading). If so, it's a bug. Actually I think I spotted where it is. /wire/modules/Process/ProcessPageSort.module, line 87: if(!$this->user->hasPermission('page-add', $parent)) throw new WirePermissionException("You do not have permission to move pages to parent {$parent->path}"); Should be: if(!$parent->addable()) throw new WirePermissionException("You do not have permission to move pages to parent {$parent->path}"); I've updated my source and will push to GitHub, but just wanted to make sure this is consistent with the problem you were running into. Because technically, this was still using the deprecated 'page-add' permission, which should have prevented you from being able to move-to-add-children for any users other than superuser (unless you assigned 'page-add' to a role shared by the user and parent's template). That page-add permission is still in 2.1's DB, but it's no longer needed so I'm going to be removing it completely in one of the next updates. Anyway, it seems to me like this bug should have prevented moving of any page for non-superusers rather than the behavior you described, so I'm just wondering if you have page-add permission assigned to any of your roles? If so, remove it (no need for it anymore). If you have time, please let me know what you find. Interested to hear more about your debugging tool! Thanks, Ryan
-
Welcome to the forums. Thanks for the feedback. In /site/config.php there is an entry for 'adminEmail'. If you set that to your email address, it will send you email notifications of any fatal errors that occur. The only other place where PW currently uses email is with the 'forgot password' function in PW 2.1. For these functions, it uses PHP's built-in mail() function, which I believe uses sendmail as the default transport agent.
-
Typed equality purists probably aren't using a lot of PHP. But if it makes you happy I'm willing to add it. So I went in to add it, but now it's opening more questions. What would you expect this to return: <?php $page = new Page(); if($page->exists) { // not a NullPage, but not in the DB either } I'm thinking I would expect the above to return false, even though Page is not a NullPage. Thinking on practical terms, a page doesn't 'exist' until it has an ID in the system... But this is different from a NullPage, which is ProcessWire's way of telling you something wasn't found (while allowing you to write code that doesn't have to always check). Basically, it's a question of whether it does this: public function exists() { return !($this instanceof NullPage); } or this: public function exists() { return (bool) $page->id; } I am thinking the second example is the right way, but letting it marinate. Interested in your thoughts.
-
Thanks for these instructions Jose, I will definitely have to give this a try sometime. I've been running on entry-level VPSs for a long time, and something that uses less resources than Apache could actually be very useful in this environment. I would appreciate your help in writing the formal documentation for install under nginx and making the installer more nginx friendly. It sounds like what we should do is have the installer suppress a couple of it's error messages if it detects nginx as the server software. If you can send me the output of this from an nginx server sometime, this may help: <?php print_r($_SERVER); I think adding a page a formal documentation to the site would be great, so lets plan on that, and I'll definitely take you up on your offer to help write it. For security, there are actually quite a few things that you need to block access to. It's important that http access be blocked to all of these: *.module *.cache /wire/core/*.php and *.inc /wire/modules/*.php and *.inc (and all dirs below) /site/modules/*.php and *.inc (and all dirs below) /site/templates/*.php and *.inc (and all dirs below) /site/templates-admin/*.php and *.inc /wire/templates-admin/*.php and *.inc /site/assets/*.php (and all dirs below) /site/assets/cache/* everything /site/assets/logs/* everything /site/assets/sessions/* everything /site/assets/backups/* everything /site/assets/config/* everything /site/assets/install/* everything /site/install/* (and all dirs below) /site/config.php Lastly, the server should not pass the request to ProcessWire if the URL doesn't match this pattern: -_.a-zA-Z0-9/ If the URL contains anything other than those characters (and ranges), the server should not send the request to PW. (excluding query strings, which aren't a consideration). Let me know if this is not possible in nginx for some reason, as it may still be okay since PW sanitizes this too. But this can really help with keeping out a lot of junk/bot/exploratory traffic.
-
I've developed an upgrade script that upgrades a 2.0 site to a 2.1 site. But I'm going to get 2.1 released stable (very soon) and keep the upgrade script in beta until we've run it through it's paces some more. I'm looking for people to help test the upgrade script if you are interested. But I recommend only performing the upgrade in your dev environment before any live environment. If you are creating new sites now, I would probably recommend just using 2.1 as it really is stable at this point. What the upgrade script won't be able to do is copy all your access settings from PW 2.0 to 2.1. This is because 2.1's access system is quite a bit different. However, I don't think many have setup much with regard to access control in 2.0, so for most this won't be a consideration during upgrade. But if it is a consideration, it'll be something that you have to setup manually after the upgrade. It'll copy of your users and roles, but you'll have to reassign them to templates (rather than pages). Beyond that consideration, the intention is to make the upgrade as automated, easy and simple as possible. The upgrade script runs from your browser and tells you what it's doing step by step. All you have to do is watch it and click "next".
-
I like the readability of the $page->exists -- something to consider. But I want to make sure I understand what you are saying, because technically there wouldn't be any difference in how you use it from $page->id, unless I'm not reading it right? i.e. these two would do exactly the same thing: $page = $this->pages->get($id); if($page->id) { // success } $page = $this->pages->get($id); if($page->exists) { // success } I guess what I'm not clear about what would be the benefit of a typed boolean here? Btw, here's another trick to do the same thing. Surround the $page in "quotes" to see if it exists: $page = $this->pages->get($id); if("$page") { // success }
-
Edit your tinymce field in Setup > Fields. Near the bottom you'll see "TinyMCE advanced configuration options". Click that, and locate the "valid_elements" input. This contains a list of all tags it will allow and the attributes it will allow with them. You should see the one for the "a" tag that currently looks like this: a[href|target|name] Update that to add the 'title' attribute to it, like this: a[href|target|name|title] But before you do this... This came up with a client recently, so we still have the research. Title attributes are likely not used for search engine ranking purposes. My thought is you shouldn't worry about putting SEO time/budget towards crafting link title attributes… focus on the anchor text and alt tags instead. There are times when title attributes can be handy for providing additional context or tooltips, but use them for that reason and not for SEO or accessibility. I say 'not for accessibility' because last I heard, those using screen readers are generally annoyed by the title attributes and much prefer the anchor text (or the alt tag, if it's a linked image). I realize it's hard to go on anything that one person says unless they work at Google. But here are a couple of recent sources for title attributes lack of SEO value: This page summarizes it best, and is consistent with other trusted seo's in the industry: http://www.highrankings.com/useless-seo-tactics-303 The results of a recent test in google involving the link title attribute (also consistent with other's results and tests): http://www.webmasterworld.com/google/4265397.htm And a couple from seomoz: http://www.seomoz.org/learn-seo/external-link http://www.seomoz.org/qa/view/48761/does-the-title-attribute-in-a-link-add-any-a-value-for-the-ranking-of-the-mentioned-keywords
-
To add a new menu item in the admin, you just go in there and add a page like you would anywhere else (and use the 'admin' template for that page, or one of your own if you prefer). If you want it to live between 'Pages' and 'Modules' then just drag it between those two. If this is something that you want to do automatically (like as part of a module installer) let me know and I'll post a code example. My understanding is that you want to display a custom HTML table of pages on your new admin page. You can go about this in two ways: Option 1 You can do it the same way as you would for any other template in your site. Only you would select your new template for that page rather than the 'admin' template. You would set access with the page (2.0) or with the template (2.1). The advantage of this approach is that it's really easy. The disadvantage is that your page may not look like the rest of the admin or use it's systems (which may or may not be useful to your need). Option 2 Use the 'admin' template for your page, create a new 'Process' module and install it. When you edit your new page, it will ask you what Process it should run, and you'll select the new Process module you created. This is the approach you want to take if you want to maintain a consistent admin experience or you want to package your functionality into a reusable module. Here's an example of how to create a Process module: /site/modules/ProcessHello.module <?php class ProcessHello extends Process { public static function getModuleInfo() { return array( 'title' => 'Hello', 'summary' => 'Simple Process module demo', 'version' => 001, ); } public function execute() { return "<p><a href='./hi'>hi</a> or <a href='./bye'>bye</a></p>"; } public function executeHi() { $this->message("Well hello"); return "<p>You clicked hi!</p>"; } public function executeBye() { $this->setFuel('processHeadline', 'Goodbye?'); $this->error('Not so fast!'); return "<p>You clicked bye!</p>"; } } Regarding your question about permissions: The user must have access to the page your Process is on before they can execute it. And they will already by default (unless you change around the page/template permissions). But in PW 2.0, they must also have access to a permission with the same name as the module. PW 2.0 installs that automatically with your module. This is only applicable to non-superuser roles (superuser can already access everything regardless of permission). In 2.1, PW doesn't install a permission and access to the Process is assumed if user has access to the page it's on. If you want PW 2.1 to behave like PW 2.0 and require a specific permission before it'll run the module, you want to specify it in your getModuleInfo function: <?php public static function getModuleInfo() { return array( 'title' => 'Hello', 'summary' => 'Simple Process module demo', 'version' => 001, 'permission' => 'name-of-permission', // NOTE THIS ); } Replace 'name-of-permission' with the permission name you want it to require. It can be any existing permission, or one that you've created. Your module can also check other permissions on-the-fly, but I won't get into that here unless someone wants me to.
-
Jose, Thanks so much for your efforts here. We would definitely appreciate your help in getting official nginx support for PW. I don't have experience with nginx, but your post makes me want to try it out. For starters, I will update our site next week to cross reference your info here so it'll be easy for others to find, and let me know what else I can do to provide better support for nginx. You'd mentioned the installer, but I'm not exactly sure what to detect--I think I need to get nginx installed on my dev server. I look forward to the next steps here. Thanks!! Ryan
-
You can modify the titles of the items before sending them to $rss->render: <?php // retrieve the RSS module $rss = $modules->get("MarkupRSS"); // configure the feed. see the actual module file for more optional config options. $rss->title = "Latest updates"; $rss->description = "The most recent pages updated on my site"; // find the pages you want to appear in the feed. // this can be any group of pages returned by $pages->find() or $page->children(), etc. $items = $pages->find("limit=10, sort=-modified"); // add something to the item titles foreach($items as $item) { $item->title = $item->title . " my text"; } // send the output of the RSS feed, and you are done $rss->render($items);
-
Site says: "Unable to complete this request due to an error"
ryan replied to nikoka's topic in General Support
Thanks for the followup. Just to confirm, it was a server outage not a ProcessWire one? The error message you posted sounds like it was running into trouble trying to access the MySQL db. -
Adam, good find. I've updated the code to this and am committing it now: <?php // convert 1-100 (worst-best) scale to 0-9 (best-worst) scale for PNG $quality = round(abs(($this->quality - 100) / 11.111111)); imagepng($thumb2, $dest, $quality); I also tested the quality settings manually by inserting the quality number in there. The problem is that [at least on my dev server] there is no visible difference in quality or filesize between specifying 0 and 9 to the imagepng() function. Do you find this to be the case there too?
-
Site says: "Unable to complete this request due to an error"
ryan replied to nikoka's topic in General Support
Nikoka, Can you edit /site/config.php -- locate the line that says "$config->debug = false;" and change it to true. Then try to load a page in your site. You should get a more specific error message. I am guessing that there was some change at the server that affects PW or the database index needs a repair or something simple like that, but let me know what you find. OR, you can check /site/assets/logs/errors.txt and see what it says at the bottom of it. For security, you can't access this file from your web browser, so you'd have to do it from the file system (FTP, shell, etc.) Please reply to let me know what you find, Ryan -
Thanks for the followup. Glad that worked.
-
Alex, TinyMCE seems to be inconsistent about when it applies the <p> tag inside tables. I think its behavior may vary from browser to browser, though have not confirmed that. I'm using Firefox 4 and Chrome 12. On the sites that I use it on, it's only on rare occasions that a <p> tag shows up inside table cells. Because it's so rare, I just remove them manually when it happens in the HTML code view of TinyMCE. If you are finding it's doing it all the time, first check that you don't have any TextFormatters turned on in your field. When using TinyMCE, you generally don't want any other text formatting to take place since TinyMCE is writing out HTML. If you can't solve this with TinyMCE settings, you may want to do something more brute force. Edit this file: /wire/modules/Inputfield/InputfieldTinyMCE/InputfieldTinyMCE.module Then locate this function: <?php public function setAttribute($key, $value) { if($key != 'value') return parent::setAttribute($key, $value); /* // remove empty tags $value = preg_replace('{<([a-z0-9]+)>\s*( |<br />)*\s*</\\1>}i', '', $value); // replace fake bulleted lists $value = preg_replace('{<br />\s*[-*]\s*}m', '<br />', $value); // fix breaks to be paragraphs $value = str_replace(array('<br /> <br />', '<br /><br />'), '</p><p>', $value); // fix paragraphs that start with a break $value = str_replace('<p><br />', '<p>', $value) ; // remove arbitrary and incorrect bulleted lists $value = preg_replace('{\s*•\s*}', ' ', $value); // fix those darn tags $value = str_replace(' ', ' ', $value); */ return parent::setAttribute($key, $value); } That function is what sets the value in ProcessWire, so you can modify the output from TinyMCE before it gets saved if you want to. Note all the commented stuff in orange. Those are all various solutions I've had to use to solve a specific problem on a specific site at one time or another. They are commented out because they really only apply in specific cases. But it sounds like you have a specific case like this. So what I would do is add something like this before or after that commented stuff already in the function: $value = str_replace("<td><p>", "<td>", $value); $value = str_replace("</p></td>", "</td>", $value); That would make it remove <p> tags that open and close with the <td> tags. This may not be an ideal solution, but it would get the job done. If you want to account for possible whitespace between the opening or closing table cell and paragraph tags, here is another solution to try (though writing in browser, not tested): if(preg_match('/<td>\s*<p>/', $value)) { $value = preg_replace('{(<td>\s*<p>|</p>\s*<(/)td>)}', '<$2td>', $value); }
-
404 Page Not Found Error When Saving Edits to an Existing Page
ryan replied to srbobc's topic in General Support
This is one I've not heard of before, but I'm guessing some error is occurring that's getting thrown by PageEdit and then misinterpreted by PageRender. Which version of ProcessWire? 2.0 or 2.1? The following applies regardless of version, but this might help me to determine the source of the problem. Can you edit /site/config.php and find the line with $config->debug = false, and set it to true. Try to perform the page save again and see if you get any other error messages. If there's anything revealing post here. Otherwise, edit one of your site's existing template files and add this temporarily at the top: <?php echo "<pre>"; $p = $pages->get(5772); if($p->id) { echo "\n{$p->path}\n{$p->status}\n{$p->template}"; $p->setOutputFormatting(false); $p->status = Page::statusOn; $p->title = $p->title . " (test)"; $p->save(); echo "\nSaved page\n"; } else { echo "\nUnable to load page\n"; } return; Now view the page using the template where you pasted that. What does it say? If it appears to have saved the page successfully, try and edit again in the admin and see if you still run into the 404 error? Thanks, Ryan -
There are positives with every CMS project and things to learn. There is no one-true way to approach things. Instead it's just a matter of different CMSs meeting different people's needs and preferences. My relatively brief experience with Symphony left me feeling that it was very much in opposition to how I work. But I have no doubt there are also good points and ideas to learn from, as there are with many products. I try to spend a good deal of time experimenting with other CMSs and will be sure to give Symphony more time based on your suggestion. In terms of organizing content for an editor with some form of limited access (as opposed to a superuser), I would suggest experimenting with ProcessWire 2.1 rather than 2.0. I think that 2.1 represents a stronger system for working with access to specific types of content. You define the access with the template rather than the page in PW 2.1. My opinion is that the tree view is the right approach whether you have access to all the branches in the tree or not. It is consistent and representative of the site's front-end structure. On large sites, confusion arises when you start pulling things out of the context of the site's structure (at least, that's my experience). You actually have quite a lot of flexibility in defining how this tree works in 2.1, including the ability to specify what fields appear in it on a template-by-template basis. But the desire to display pages in an alternate way in the admin has come up before, so you'll also be glad to know the new page search module can be used as a page listing filter (enabling nearly any kind of page listing display), and we'll be taking this utility a lot further as we move forward in PW development. But the tree structure will always be PW's native view into your site... we'll just provide more options for those that want it. The debug tool sounds interesting. I wouldn't want to take the approach of intercepting GET vars or making PW produce output directly in that manner, because PW promises not to take that control from your template. But you can achieve a similar type of result pretty easily just by adding a little code to your template's file. For example: <?php if($input->get->debug && !$user->isGuest()) { echo $page->renderFields(); // uses the MarkupPageFields core module // or iterate through the page's fields on your own to produce JSON, XML, etc. return; } // otherwise render regular page output
-
Okay that's good to know, thanks for the clarification. We've already got the note about the RewriteBase commented in the htaccess file so I won't worry about that one. But knowing that it's required at 1&1 (a fairly major hosting service) I might need to call more attention to this in the install directions.
-
Very cool, it looks like the 2 languages work beautifully in this example. This is the first time I've seen such a solution in place, nice work. I also like that the language-switching links stay on the current page, so that hopefully Google will index the whole thing in both languages (using the url segments). My only concern would be about whether this might confuse Google (or other search engines)–I suppose that would only confuse Google if GoogleBot maintained session cookies… and I don't know if it does. But if it does, you might be better off requiring a form POST before setting the session cookie to change the language, setting the cookie with Javascript, or forcing the language URL segment to always be on the URL for one of the languages. The last solution mentioned there would be the best but also be a little harder to implement. If you are interested, I can describe how to do it. But if potential confusion to the search engines is not a concern, then you don't need to worry about any of these as the site appears to function beautifully for the user.