<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>Webtypes - Home</title>
  <id>tag:webtypes.com,2008:mephisto/</id>
  <generator version="0.7.3" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  
  <link href="http://webtypes.com/" rel="alternate" type="text/html" />
  <updated>2007-05-28T12:41:39Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/webtypes" type="application/atom+xml" /><entry xml:base="http://webtypes.com/">
    <author>
      <name>webtypes</name>
    </author>
    <id>tag:webtypes.com,2007-05-21:1861</id>
    <published>2007-05-21T15:15:00Z</published>
    <updated>2007-05-28T12:41:39Z</updated>
    <category term="rails,globalize,mephisto" />
    <link href="http://feeds.feedburner.com/~r/webtypes/~3/120269297/globalizing-mephisto-part-4" rel="alternate" type="text/html" />
    <title>Globalizing Mephisto (Part 4)</title>
<summary type="html">&lt;p&gt;Another update to the plugin means that rather than using subdomains you can now define the locale via a path parameter e.g.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;http://webtypes.com/es/2007/5/15/globalizando-mephisto-3-parte&lt;tt&gt;
&lt;/tt&gt;http://webtypes.com/es/admin/articles/edit/2&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Read on to see how &lt;a href="http://webtypes.com/2007/5/21/globalizing-mephisto-part-4"&gt;…&lt;/a&gt;&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Another update to the plugin means that rather than using subdomains you can now define the locale via a path parameter e.g.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;http://webtypes.com/es/2007/5/15/globalizando-mephisto-3-parte&lt;tt&gt;
&lt;/tt&gt;http://webtypes.com/es/admin/articles/edit/2&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Read on to see how &lt;a href="http://webtypes.com/2007/5/21/globalizing-mephisto-part-4"&gt;…&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Welcome to the fourth part of the &lt;a href="http://www.webtypes.com/2007/03/18/globalizing-mephisto"&gt;Globalizing Mephisto&lt;/a&gt; article series which shows you how to enable the definition of the active locale via a path parameter rather than via subdomains.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="/2007/3/18/globalizing-mephisto"&gt;Part 1 – Installation and usage for &lt;strong&gt;single site&lt;/strong&gt; mephisto&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/2007/3/21/globalizing-mephisto-part-2"&gt;Part 2 – Deployment and production issues&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/2007/5/15/globalizing-mephisto-part-3"&gt;Part 3 – Installation and usage for &lt;strong&gt;multi site&lt;/strong&gt; mephisto&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Part 4 – Using a &lt;strong&gt;path parameter&lt;/strong&gt; to define the locale&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;When I &lt;a href="/2007/3/18/globalizing-mephisto"&gt;first&lt;/a&gt; posted about the mephisto_i18n plugin on the &lt;a href="http://groups.google.com/group/MephistoBlog"&gt;mephisto forum&lt;/a&gt; some people mentioned that they thought using subdomains to define the active locale wasn’t very handy, especially for mephisto instances on shared hosts.&lt;/p&gt;


	&lt;p&gt;In response to that feedback, I’ve now updated the plugin to allow locale definition either via:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;subdomains (default)&lt;/li&gt;
		&lt;li&gt;path parameter&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Using the ‘path parameter’ mode means you can have urls like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;http://webtypes.com/&lt;tt&gt;
&lt;/tt&gt;http://webtypes.com/es&lt;tt&gt;
&lt;/tt&gt;http://webtypes.com/es/2007/5/15/globalizando-mephisto-3-parte&lt;tt&gt;
&lt;/tt&gt;http://webtypes.com/es/sobre&lt;tt&gt;
&lt;/tt&gt;http://webtypes.com/es/admin/articles/edit/2&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h2&gt;Enabling &lt;strong&gt;path&lt;/strong&gt; parameter mode in 3 easy steps&lt;/h2&gt;


	&lt;h3&gt;Update environment.rb&lt;/h3&gt;


Add the following line to your environment file:

  &lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;Mephisto&lt;/span&gt;::&lt;span class="co"&gt;I18N&lt;/span&gt;.locale_definition = &lt;span class="sy"&gt;:path&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h3&gt;Update routes.rb&lt;/h3&gt;


Replace the call to:

  &lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;Mephisto&lt;/span&gt;::&lt;span class="co"&gt;Routing&lt;/span&gt;.connect_with map&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


  with

  &lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;Mephisto&lt;/span&gt;::&lt;span class="co"&gt;I18N&lt;/span&gt;::&lt;span class="co"&gt;Routing&lt;/span&gt;.connect_with map&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


  in your routes file.

	&lt;h3&gt;Update your liquid templates (optional)&lt;/h3&gt;


	&lt;p&gt;Optionally, modify any hard-coded links in your liquid templates like so:&lt;/p&gt;


&lt;strong&gt;before&lt;/strong&gt;

  &lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="ta"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="an"&gt;href&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;/{{'blog' | t: 'urls'}}&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="ta"&gt;&amp;gt;&lt;/span&gt;{{'Weblog' | t}}&lt;span class="ta"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;strong&gt;after&lt;/strong&gt;

  &lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="ta"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="an"&gt;href&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;{{i18n.l}}/{{'blog' | t: 'urls'}}&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="ta"&gt;&amp;gt;&lt;/span&gt;{{'Weblog' | t}}&lt;span class="ta"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;NOTE&lt;/span&gt;&lt;/strong&gt;: This assumes you’ve already installed the plugin for a &lt;a href="/2007/3/18/globalizing-mephisto"&gt;single site&lt;/a&gt; or &lt;a href="/2007/5/15/globalizing-mephisto-part-3"&gt;multi site&lt;/a&gt; globalized mephisto.&lt;/p&gt;


	&lt;h2&gt;What has been done for you automatically…&lt;/h2&gt;


	&lt;p&gt;When in &lt;strong&gt;path&lt;/strong&gt; parameter mode and the active locale is not the base locale then:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;The plugin automatically rewrites urls generated via the url_rewriter which 
means that all links using link_to and family are automatically correctly localized.&lt;/li&gt;
		&lt;li&gt;The article/section &amp; site urls (tag/search) are automatically prepended with 
the correct language code which means most of the links of your site will &lt;strong&gt;just work&lt;/strong&gt;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Please do try out this mode and, as usual, I appreciate your feedback.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://saimonmoore.net"&gt;Saimon Moore&lt;/a&gt; (also in &lt;a href="http://el.saimonmoore.net"&gt;Greek&lt;/a&gt;, &lt;a href="http://es.saimonmoore.net"&gt;Spanish&lt;/a&gt; &amp; &lt;a href="http://ca.saimonmoore.net"&gt;Catalan&lt;/a&gt;  :)&lt;/p&gt;
          </content>  <feedburner:origLink>http://webtypes.com/2007/5/21/globalizing-mephisto-part-4</feedburner:origLink></entry>
  <entry xml:base="http://webtypes.com/">
    <author>
      <name>webtypes</name>
    </author>
    <id>tag:webtypes.com,2007-05-15:1848</id>
    <published>2007-05-15T13:33:00Z</published>
    <updated>2007-06-05T09:01:44Z</updated>
    <category term="globalize" />
    <category term="mephisto" />
    <category term="rails" />
    <link href="http://feeds.feedburner.com/~r/webtypes/~3/120269298/globalizing-mephisto-part-3" rel="alternate" type="text/html" />
    <title>Globalizing Mephisto (Part 3)</title>
<summary type="html">&lt;p&gt;For those of you who asked about multi site support for this plugin, this is now available. Read on to find out how to convert to a globalized multi-site mephisto &lt;a href="/2007/5/15/globalizing-mephisto-part-3"&gt;…&lt;/a&gt;&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;For those of you who asked about multi site support for this plugin, this is now available. Read on to find out how to convert to a globalized multi-site mephisto &lt;a href="/2007/5/15/globalizing-mephisto-part-3"&gt;…&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Welcome to the third part of the &lt;a href="http://www.webtypes.com/2007/03/18/globalizing-mephisto"&gt;Globalizing Mephisto&lt;/a&gt; article series where I’ll be talking about how to use this plugin with a multi site mephisto instance.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="/2007/3/18/globalizing-mephisto"&gt;Part 1 – Installation and usage for &lt;strong&gt;single site&lt;/strong&gt; mephisto&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/2007/3/21/globalizing-mephisto-part-2"&gt;Part 2 – Deployment and production issues&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Part 3 – Installation and usage for &lt;strong&gt;multi site&lt;/strong&gt; mephisto&lt;/li&gt;
		&lt;li&gt;&lt;a href="/2007/5/21/globalizing-mephisto-part-4"&gt;Part 4 – Using a &lt;strong&gt;path parameter&lt;/strong&gt; to define the locale&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I’ve updated the plugin to provide full multisite support:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;All rake tasks now have multi site support, allowing you to easily convert an existing globalized single site mephisto instance into a multisite instance with little effort.&lt;/li&gt;
		&lt;li&gt;You can now also specify separate list of supported locales for each site so that site 1 can support english, french and german, site 2: spanish &amp; catalan and site 3: klingon, esperanto and elfish.&lt;/li&gt;
		&lt;li&gt;SupportedLocales now loads the locales lazily.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Single-site to multi-site.&lt;/h2&gt;


	&lt;h3&gt;Create a new site instance&lt;/h3&gt;


	&lt;p&gt;Create a new site instance. e.g. via something like:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;s = &lt;span class="co"&gt;Site&lt;/span&gt;.create(&lt;span class="sy"&gt;:host&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;webtypes.com&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:title&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Webtypes&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:subtitle&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;We do web, and you?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;s.sections &amp;lt;&amp;lt; &lt;span class="co"&gt;Section&lt;/span&gt;.create(&lt;span class="sy"&gt;:name&lt;/span&gt;=&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Home&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:path&lt;/span&gt; =&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:template&lt;/span&gt;=&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;home.liquid&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;s.save&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Add the following to environment.rb:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;Site&lt;/span&gt;.multi_sites_enabled = &lt;span class="pc"&gt;true&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;SupportedLocales&lt;/span&gt;.define_by_key(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;saimonmoore.net&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;el-GR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;es-ES&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;ca-ES&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;],&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;en-GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;SupportedLocales&lt;/span&gt;.define_by_key(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;webtypes.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;es-ES&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;nl-NL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;],&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;en-GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h3&gt;Create subroots&lt;/h3&gt;


	&lt;p&gt;If you haven’t already &lt;a href="/2007/03/18/globalizing-mephisto"&gt;globalized&lt;/a&gt; your mephisto then follow the same steps as before &lt;strong&gt;what are you referring to?&lt;/strong&gt; ensuring the first step in this list has been done &lt;strong&gt;which list?&lt;/strong&gt;. If you’re upgrading a single site globalized mephisto then just execute:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;svn up vendor/plugins/mephisto_i18n&lt;tt&gt;
&lt;/tt&gt;rake mephisto&lt;span class="sy"&gt;:i18n&lt;/span&gt;&lt;span class="sy"&gt;:ui&lt;/span&gt;&lt;span class="sy"&gt;:setup_subroots&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This will create all the necessary subroots within /public/cache/saimonmoore.net, /public/cache/webtypes.com. It’ll also add symlinks to public/assets so that within your site, you can just access /assets/2007/10/3/myimage.png.&lt;/p&gt;


	&lt;p&gt;This is how my public directory looks after running setup_subroots for a multisite-enabled mephisto:&lt;/p&gt;


	&lt;p&gt;(Note: I’ve retained the previous subroots from my single instance site (the ca,es,el directories, but in a multisite system the base doc root is /public/cache/site_host)&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;42&lt;tt&gt;
&lt;/tt&gt;43&lt;tt&gt;
&lt;/tt&gt;44&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;45&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;46&lt;tt&gt;
&lt;/tt&gt;47&lt;tt&gt;
&lt;/tt&gt;48&lt;tt&gt;
&lt;/tt&gt;49&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;51&lt;tt&gt;
&lt;/tt&gt;52&lt;tt&gt;
&lt;/tt&gt;53&lt;tt&gt;
&lt;/tt&gt;54&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;55&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;56&lt;tt&gt;
&lt;/tt&gt;57&lt;tt&gt;
&lt;/tt&gt;58&lt;tt&gt;
&lt;/tt&gt;59&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;60&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;61&lt;tt&gt;
&lt;/tt&gt;62&lt;tt&gt;
&lt;/tt&gt;63&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;saimon@iris:~/dev/projects/saimonmoore.net$ ll public/&lt;tt&gt;
&lt;/tt&gt;total 32K&lt;tt&gt;
&lt;/tt&gt;-rw-r--r-- 1 saimon  619 2007-04-20 17:04 404.html&lt;tt&gt;
&lt;/tt&gt;-rw-r--r-- 1 saimon  684 2007-04-20 17:04 500.html&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 6 saimon  160 2007-05-14 13:57 assets/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon  304 2007-04-20 17:04 ca/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 5 saimon  136 2007-05-14 14:02 cache/&lt;tt&gt;
&lt;/tt&gt;-rwxr-xr-x 1 saimon  479 2007-04-20 17:04 dispatch.cgi*&lt;tt&gt;
&lt;/tt&gt;-rwxr-xr-x 1 saimon  859 2007-04-20 17:04 dispatch.fcgi*&lt;tt&gt;
&lt;/tt&gt;-rwxr-xr-x 1 saimon  479 2007-04-20 17:04 dispatch.rb*&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 5 saimon  120 2007-04-20 17:04 documents/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon  304 2007-04-20 17:04 el/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon  304 2007-04-20 17:04 es/&lt;tt&gt;
&lt;/tt&gt;-rw-r--r-- 1 saimon    0 2007-04-20 17:04 favicon.ico&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 4 saimon   96 2007-05-11 13:46 images/&lt;tt&gt;
&lt;/tt&gt;-rw-r--r-- 1 saimon 3.3K 2007-04-20 17:04 install.html&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 4 saimon   96 2007-04-20 17:04 javascripts/&lt;tt&gt;
&lt;/tt&gt;-rw-r--r-- 1 saimon   99 2007-04-20 17:04 robots.txt&lt;tt&gt;
&lt;/tt&gt;-rw-r--r-- 1 saimon  631 2007-04-20 17:04 sitemap.txt&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 4 saimon  136 2007-05-14 09:27 stylesheets/&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;saimon@iris:~/dev/projects/saimonmoore.net$ ll public/cache/&lt;tt&gt;
&lt;/tt&gt;total 0&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 6 saimon 400 2007-05-14 14:02 saimonmoore.net/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 5 saimon 376 2007-05-14 14:02 webtypes.com/&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;saimon@iris:~/dev/projects/saimonmoore.net$ ll public/cache/saimonmoore.net/&lt;tt&gt;
&lt;/tt&gt;total 0&lt;tt&gt;
&lt;/tt&gt;lrwxrwxrwx 1 saimon  24 2007-05-18 13:48 404.html -&amp;gt; ../../../public/404.html&lt;tt&gt;
&lt;/tt&gt;lrwxrwxrwx 1 saimon  24 2007-05-18 13:48 500.html -&amp;gt; ../../../public/500.html&lt;tt&gt;
&lt;/tt&gt;lrwxrwxrwx 1 saimon  38 2007-05-18 13:48 assets -&amp;gt; ../../../public/assets/saimonmoore.net/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon 232 2007-05-18 13:50 ca/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon 232 2007-05-18 13:50 el/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon 232 2007-05-18 13:50 es/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon  72 2007-05-18 13:54 images/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon  72 2007-05-18 13:54 javascripts/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon  72 2007-05-18 13:54 stylesheets/&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;saimon@iris:~/dev/projects/saimonmoore.net$ ll public/cache/webtypes.com/&lt;tt&gt;
&lt;/tt&gt;total 0&lt;tt&gt;
&lt;/tt&gt;lrwxrwxrwx 1 saimon  24 2007-05-18 13:48 404.html -&amp;gt; ../../../public/404.html&lt;tt&gt;
&lt;/tt&gt;lrwxrwxrwx 1 saimon  24 2007-05-18 13:48 500.html -&amp;gt; ../../../public/500.html&lt;tt&gt;
&lt;/tt&gt;lrwxrwxrwx 1 saimon  35 2007-05-18 13:48 assets -&amp;gt; ../../../public/assets/webtypes.com/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon 232 2007-05-18 13:50 es/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon  72 2007-05-18 13:54 images/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon  72 2007-05-18 13:54 javascripts/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon 232 2007-05-18 13:50 nl/&lt;tt&gt;
&lt;/tt&gt;drwxr-xr-x 3 saimon  72 2007-05-18 13:54 stylesheets/&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;saimon@iris:~/dev/projects/saimonmoore.net$ ll public/cache/webtypes.com/javascripts/&lt;tt&gt;
&lt;/tt&gt;total 0&lt;tt&gt;
&lt;/tt&gt;lrwxrwxrwx 1 saimon 39 2007-05-18 17:35 mephisto -&amp;gt; ../../../../public/javascripts/mephisto/&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;saimon@iris:~/dev/projects/saimonmoore.net$ ll public/cache/webtypes.com/images/&lt;tt&gt;
&lt;/tt&gt;total 0&lt;tt&gt;
&lt;/tt&gt;lrwxrwxrwx 1 saimon 34 2007-05-18 17:35 mephisto -&amp;gt; ../../../../public/images/mephisto/&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;saimon@iris:~/dev/projects/saimonmoore.net$ ll public/cache/webtypes.com/stylesheets/&lt;tt&gt;
&lt;/tt&gt;total 0&lt;tt&gt;
&lt;/tt&gt;lrwxrwxrwx 1 saimon 39 2007-05-18 17:35 mephisto -&amp;gt; ../../../../public/stylesheets/mephisto/&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h3&gt;Update your webserver&lt;/h3&gt;


	&lt;p&gt;Finally update your webserver to point to the new subroots. For those using the very recommended &lt;a href="http://wiki.codemongers.com/Nginx"&gt;nginx&lt;/a&gt; server that would be:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;server {&lt;tt&gt;
&lt;/tt&gt;    listen       &lt;span class="i"&gt;80&lt;/span&gt;;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;span class="c"&gt;#Spanish locale: es subdomain&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    server_name es.webtypes.com;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    root &lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;www/apps/saimonmoore.net/current/public/cache/webtypes.com/es;&lt;tt&gt;
&lt;/tt&gt;    ...&lt;tt&gt;
&lt;/tt&gt;}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;showing the change needed for the ‘es’ (spanish) virtual host. Update the rest of the virtual hosts as necessary.&lt;/p&gt;


	&lt;h2&gt;Other fixes&lt;/h2&gt;


&lt;ul&gt;
&lt;li&gt;
Fixes for the automatically generated “switch locale” links via:
&lt;pre&gt;&lt;code&gt;{{ i18n.switch_to_locale_links }}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;These no longer break when browsing the archives/tags, searching for articles or using any custom controllers.
&lt;span class="caps"&gt;WARNING&lt;/span&gt;!:  As a result of this change it is necessary to update your schema (which basically localizes site.search_path/tag_path) via:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;{{ rake mephisto:i18n:update_schema }}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Also, in order for the search feature to be correctly localized, you need to ensure the search form submit url is localized (and the view translation is the same as the model translation of site.search_path )&lt;/p&gt;


	&lt;p&gt;e.g.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="ta"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="an"&gt;method&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="an"&gt;id&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;sform&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="an"&gt;action&lt;/span&gt;=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;/{{'search' | t: 'urls'}}&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="ta"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


Note the use of the ‘urls’ namespace….
&lt;/li&gt;
&lt;li&gt;
Within the admin interface, when switching to the base locale, the locale switcher will automatically switch to www.mydomain.com rather than e.g. en.mydomain.com if base locale is english.
&lt;/li&gt;
&lt;li&gt;
Moved certain rake tasks related to schema changes to the mephisto:i18n namespace. 
&lt;/li&gt;
&lt;li&gt;Updated rake tasks. mephisto:i18n:un/install_schema to accept the &lt;span class="caps"&gt;LANGS&lt;/span&gt; environment variable to easily add more languages to the schema. 
&lt;/li&gt;
&lt;li&gt;It’s no longer necessary to manually add the session domain (ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.update(:session_domain =&amp;gt; ’.saimonmoore.net’)) to environments/production.rb as this is now automatically done for you.
&lt;/li&gt;
&lt;li&gt;Various fixes to the Translations module including ordering entries case-insensitively, fixing bug where interpolated keys weren’t being found (‘bla %s ..’), now the search function searches translated text rather than keys.
&lt;/li&gt;
&lt;/ul&gt;

	&lt;h2&gt;Custom controllers&lt;/h2&gt;


	&lt;p&gt;If you’re using a mephisto plugin that injects it’s own custom controller and routes (.e.g the &lt;a href="http://jamescrisp.blogspot.com/2007/03/contact-feedback-form-plugin-for.html"&gt;contact form plugin&lt;/a&gt;) and you’d like to localize it’s url, then simply add something like the following to your routes file:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;Routing&lt;/span&gt;::&lt;span class="co"&gt;Routes&lt;/span&gt;.draw &lt;span class="r"&gt;do&lt;/span&gt; |map|&lt;tt&gt;
&lt;/tt&gt;  map.contact_form &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;contact&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt; &amp;gt;&amp;gt; &lt;span class="sy"&gt;:urls&lt;/span&gt;, &lt;span class="sy"&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;contact_form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;contact_form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  map.contact_submit &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;contact_submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:controller&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;contact_form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;contact_submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:conditions&lt;/span&gt; =&amp;gt; { &lt;span class="sy"&gt;:method&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:post&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;Mephisto&lt;/span&gt;::&lt;span class="co"&gt;Routing&lt;/span&gt;.connect_with map&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The urls in the routes are localized so you need to translate them in the translations tab. This relies on code from the &lt;a href="http://saimonmoore.net/2007/5/17/localized-urls"&gt;following plugin&lt;/a&gt; which has been incorporated into this plugin.&lt;/p&gt;


	&lt;h2&gt;Known bugs/limitations&lt;/h2&gt;


	&lt;p&gt;Currently if multisite mode is enabled, you have to use “SupportedLocales.define_key()” to define the supported locales for each site, even if both site will support the same locales. i.e. You have to duplicate the entries:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;SupportedLocales&lt;/span&gt;.define_by_key(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;saimonmoore.net&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;es-ES&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;nl-NL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;],&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;en-GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;SupportedLocales&lt;/span&gt;.define_by_key(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;webtypes.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,[&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;es-ES&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;nl-NL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;],&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;en-GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


I’ll try and fix this soon so you can just define:

 &lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;SupportedLocales&lt;/span&gt;.define([&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;es-ES&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;nl-NL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;],&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;en-GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;) &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;and both sites will support the same locales.&lt;/p&gt;


	&lt;h2&gt;Future plans&lt;/h2&gt;


	&lt;ul&gt;
	&lt;li&gt;There’s been talk on the mephisto forums about using an &lt;a href="http://errtheblog.com/post/4396"&gt;alternative&lt;/a&gt; localization library to localize mephisto which will make it’s way into trunk. I’ve already expressed my &lt;a href="http://groups.google.com/group/MephistoBlog/browse_thread/thread/9d0e7816d5779599/44db3ee11d5f6145?lnk=gst&amp;amp;#38;q=globalize&amp;amp;#38;rnum=1#44db3ee11d5f6145"&gt;opinions&lt;/a&gt; on that issue so I won’t regurgitate here, suffice to say that if that happens I will still be supporting and maintaining the globalize-plugin. Of course, it’ll be a complete pain and I’ll have to do a quite a bit of hacking but I’m commited to this (since I use it for my own client applications) so I’ll be maintaining it no matter what.&lt;/li&gt;
		&lt;li&gt;“Upgrade for support with the next version of globalize”. &lt;a href="http://www.globalize-rails.org/globalize/authors"&gt;We’re&lt;/a&gt; pushing through a lot of changes for the next version of globalize and this will soon be available. When this happens I’ll be updating this plugin for compatibility with the new globalize.&lt;/li&gt;
		&lt;li&gt;“Edge-Rails support”. I’ve decided to only maintain support for use of the plugin with Rails 1.2.x for now. When the next major release of rails occurs, I’ll update the plugin. That said, anyone wanting to provide patches for edge-rails support is more than welcome. (Patches are generally welcome :)&lt;/li&gt;
		&lt;li&gt;“Support for allowing your readers to translate your content for you”. I’m working on a separate plugin for mephisto to allow you to do this. It’ll obviously depend on this one but I’d rather keep it separate for now. Or should I just bundle it together?&lt;/li&gt;
		&lt;li&gt;“Support for publishing/hiding content without translations”. Currently, untranslated content is visible and shown in the base language. With this feature, you’ll be able to selectively hide/show content that has no translation for a whole locale or on an individual basis. I’m also toying with the idea of providing place holders for untranslated content.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Sites running the mephisto_i18n plugin&lt;/h2&gt;


	&lt;p&gt;We’ve got 4 sites up using this plugin:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://amicsmuseuprecolombi.org/"&gt;amicsmuseuprecolombi.org&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://webtypes.com"&gt;webtypes.com&lt;/a&gt; / &lt;a href="http://saimonmoore.net"&gt;saimonmoore.net&lt;/a&gt; (multisite)&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://ktiniatreio.gr"&gt;ktiniatreio.gr&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h4&gt;Other sites&lt;/h4&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://onlinevortex.com" title="english"&gt;onlinevortex.com&lt;/a&gt; &amp; &lt;a href="http://bitmapped.onlinevortex.com" title="spanish"&gt;bitmapped.onlinevortex.com&lt;/a&gt;. (This site by Carlos Mendoza is running a slightly customized version of the plugin to allow specifically named domains to indicate the language rather than using the language code prefix)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;If you’ve got a site running this plugin, please let me know so I can add it to the list. Also if you’ve set it up using a different webserver/app server configuration, I’d like to know about it too. Just leave a comment here&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://webtypes.com/2007/5/21/globalizing-mephisto-part-4"&gt;Prefer to use a &lt;strong&gt;path parameter&lt;/strong&gt; to define the active locale? Read Part 4&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://saimonmoore.net"&gt;Saimon Moore&lt;/a&gt; (also in &lt;a href="http://el.saimonmoore.net"&gt;Greek&lt;/a&gt;, &lt;a href="http://es.saimonmoore.net"&gt;Spanish&lt;/a&gt; &amp; &lt;a href="http://ca.saimonmoore.net"&gt;Catalan&lt;/a&gt;  :)&lt;/p&gt;
          </content>  <feedburner:origLink>http://webtypes.com/2007/5/15/globalizing-mephisto-part-3</feedburner:origLink></entry>
  <entry xml:base="http://webtypes.com/">
    <author>
      <name>webtypes</name>
    </author>
    <id>tag:webtypes.com,2007-03-21:1694</id>
    <published>2007-03-21T08:40:00Z</published>
    <updated>2007-06-01T08:46:46Z</updated>
    <category term="rails,globalize,mephisto" />
    <link href="http://feeds.feedburner.com/~r/webtypes/~3/120269299/globalizing-mephisto-part-2" rel="alternate" type="text/html" />
    <title>Globalizing Mephisto (Part 2)</title>
<summary type="html">&lt;p&gt;I’ll be walking you through, the deployment issues that arise with the setup enforced by the plugin covering topics such as web server configuration (nginx) and mongrel hacking &lt;a href="/2007/3/21/globalizing-mephisto-part-2"&gt;…&lt;/a&gt;&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;I’ll be walking you through, the deployment issues that arise with the setup enforced by the plugin covering topics such as web server configuration (nginx) and mongrel hacking &lt;a href="/2007/3/21/globalizing-mephisto-part-2"&gt;…&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Welcome to the second part of the &lt;a href="http://www.webtypes.com/2007/03/18/globalizing-mephisto"&gt;Globalizing Mephisto&lt;/a&gt; article series where I discuss various deployment issues surrounding the use of this plugin.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="/2007/3/18/globalizing-mephisto"&gt;Part 1 – Installation and usage for &lt;strong&gt;single site&lt;/strong&gt; mephisto&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Part 2 – Deployment and production issues&lt;/li&gt;
		&lt;li&gt;&lt;a href="/2007/5/15/globalizing-mephisto-part-3"&gt;Part 3 – Installation and usage for &lt;strong&gt;multi site&lt;/strong&gt; mephisto&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/2007/5/21/globalizing-mephisto-part-4"&gt;Part 4 – Using a &lt;strong&gt;path parameter&lt;/strong&gt; to define the locale&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I’ll be walking you through, the deployment issues that arise with the setup enforced by the plugin.&lt;/p&gt;


	&lt;h4&gt;Document Roots and Virtual Hosts&lt;/h4&gt;


	&lt;p&gt;As I mentioned in my previous article, the mephisto_i18n plugin maintains the current locale of a session by assuming that the top level subdomain of the host indicates the language part of the locale.&lt;/p&gt;


e.g.
&lt;pre&gt;
&lt;code&gt;
  example.com =&amp;gt; base locale is currently active (e.g. English )
  es.example.com =&amp;gt; 'es' locale is currently active (e.g. Spanish )
  fr.example.com =&amp;gt; 'fr' locale is currently active (e.g. French )
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;So the web server needs multiple virtual hosts, one for each of the languages to be supported.&lt;/p&gt;


	&lt;p&gt;e.g&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
  * RAILS_ROOT/public               (Holds the base locale's doc root)
  * RAILS_ROOT/public/es             (Holds the 'es' locale's doc root)
  * RAILS_ROOT/public/fr             (Holds the 'fr' locale's doc root)
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;In the previous article we’ve seen how the rake tasks provided by the plugin, make setting up these doc roots a piece of cake, and from now on I’m assuming that you’ve got all that setup and mephisto is globalized and running well in development mode.&lt;/p&gt;


	&lt;h4&gt;Setting up the web server&lt;/h4&gt;


	&lt;p&gt;So we need to setup the web server to hande multiple document roots. You need to have a server that has support for &lt;a href="http://en.wikipedia.org/wiki/Name-based_virtual_hosting"&gt;name-based virtual hosts&lt;/a&gt;. These days any decent web server should have this baked in.&lt;/p&gt;


	&lt;h5&gt;Mine’s a cup of nginx&lt;/h5&gt;


	&lt;p&gt;My current preferred web server is &lt;a href="http://sysoev.ru/nginx/"&gt;Nginx&lt;/a&gt; (go &lt;a href="http://wiki.codemongers.com/Nginx"&gt;here&lt;/a&gt; for details in other languages) so I’m going to show you the configuration I use for this particular web server.&lt;/p&gt;


	&lt;p&gt;Of course, any web server that can handle virtual hosts will do. e.g. &lt;a href="http://httpd.apache.org/"&gt;Apache&lt;/a&gt; , &lt;a href="http://www.lighttpd.net"&gt;Lighttpd&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;The nginx config file usually resides at /usr/local/nginx/conf/nginx.conf&lt;/p&gt;


	&lt;p&gt;The following nginx.conf assumes there are 4 different virtual hosts. One each for the en,es,ca and fr locales. It also assumes that Catalan (ca) is the base locale.&lt;/p&gt;


	&lt;p&gt;Additionally, it redirects all requests for any unrecognised subdomains (as well as the base locale subdomain) to www.&lt;/p&gt;


	&lt;p&gt;e.g. requests coming to somesubdomain.example.com will be redirected to www.example.com
 Also if we assume catalan is the base locale, requests for ca.example.com will be redirected to www.example.com&lt;/p&gt;


	&lt;p&gt;Just leave the last virtual host out if you don’t want this redirection to occur.&lt;/p&gt;


	&lt;p&gt;Also, I’m showing the whole nginx.conf here including the virtual hosts, but what i like to do for production is to put the different server directives for a specific site in their own file and use an &lt;a href="http://wiki.codemongers.com/NginxHttpMainModule#include"&gt;include&lt;/a&gt; directive to pull it in.&lt;/p&gt;


	&lt;p&gt;e.g. /usr/local/nginx/conf/apps/saimonmoore.net.conf&lt;/p&gt;


	&lt;p&gt;and just add:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
include apps/saimonmoore.net.conf;
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;within the http directive. (I usually add it at the bottom). Within each app config I also include the call to the &lt;a href="http://wiki.codemongers.com/NginxHttpUpstreamModule"&gt;upstream&lt;/a&gt; directive&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
upstream mongrel_saimonmoore.net {
   server 127.0.0.1:8080;
   server 127.0.0.1:8081;
}
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Here is the full example nginx.conf file though:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
  # user and group to run as
  #user  www-data www-data;
  # number of nginx workers
  worker_processes  2;

  # pid of nginx master process
  pid        /var/log/nginx/nginx.pid;

  # Number of worker connections. 1024 is a good default
  events {
      worker_connections  1024;
  }

  # start the http module where we config http access.
  http {
    # pull in mime-types. You can break out your config
    # into as many include's as you want to make it cleaner
      include       conf/mime.types;
      # set a default type for the rare situation that
      # nothing matches from the mimie-type include
      default_type  application/octet-stream;

      # configure log format
      log_format  main  '$remote_addr - $remote_user [$time_local] $status '
                        '"$request" $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';

      # main access log
      access_log  /var/log/nginx/access.log  main;
      # main error log
      error_log  /var/log/nginx/error.log info;

      # no sendfile on OSX uncomment
      #this if your on linux or bsd
      #sendfile        on;

      # These are good default values.
      tcp_nopush     on;
      keepalive_timeout  65;
      tcp_nodelay        on;

      # this is where you define your mongrel clusters.
      # you need one of these blocks for each cluster
      # and each one needs its own name to refer to it later.
      # To determine how many mongrels are necessary follow:
      # http://mongrel.rubyforge.org/docs/how_many_mongrels.html
      upstream mongrel_example.com {
          server 127.0.0.1:8080;
          server 127.0.0.1:8081;
      }

      # output compression saves bandwidth
      gzip on;
      gzip_comp_level 2;
      gzip_min_length  1100;
      gzip_buffers     4 8k;
      #gzip_proxied any;
      gzip_types       text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

      #server_names_hash_bucket_size 32/64/128
      server_names_hash_bucket_size 64;

      #vhosts for example.com
      #
      #root /var/www/apps/example.com/current/public;
      #Spanish locale: es subdomain
      server {
          listen       80;

          server_name es.example.com;

          root /var/www/apps/example.com/current/public/es;

          access_log  /var/log/nginx/host.access.log  main;
          rewrite_log on;

          if (-f $document_root/maintenance.html){
            rewrite  ^(.&amp;amp;#42;)$  /maintenance.html last;
            break;
          }

          location /index2 {
            rewrite (.&amp;amp;#42;) / permanent;
          }

          location / {
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect false;

            # If the file exists as a static file serve it directly without
            # running all the other rewite tests on it
            if (-f $request_filename) {
              break;
            }

            # check for index.html for directory index
            # if its there on the filesystem then rewite
            # the url to add /index.html to the end of it
            # and then break to send it to the next config rules.
            if (-f $request_filename/index.html) {
              rewrite (.&amp;amp;#42;) $1/index.html break;
            }

            # this is the meat of the rails page caching config
            # it adds .html to the end of the url and then checks
            # the filesystem for that file. If it exists, then we
            # rewite the url to have explicit .html on the end
            # and then send it on its way to the next config rule.
            # if there is no file on the fs then it sets all the
            # necessary headers and proxies to our upstream mongrels
            if (-f $request_filename.html) {
              rewrite (.&amp;amp;#42;) $1.html break;
            }

            if (!-f $request_filename) {
              proxy_pass http://mongrel_example.com;
              break;
            }
          }
      }

      #French locale: fr subdomain
      server {
          listen       80;

          server_name fr.example.com;

          root /var/www/apps/example.com/current/public/fr;

          access_log  /var/log/nginx/host.access.log  main;

          if (-f $document_root/maintenance.html){
            rewrite  ^(.&amp;amp;#42;)$  /maintenance.html last;
            break;
          }

          location /index2 {
            rewrite (.&amp;amp;#42;) / permanent;
          }

          location / {
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect false;

            if (-f $request_filename) {
              break;
            }

            if (-f $request_filename/index.html) {
              rewrite (.&amp;amp;#42;) $1/index.html break;
            }

            if (-f $request_filename.html) {
              rewrite (.&amp;amp;#42;) $1.html break;
            }

            if (!-f $request_filename) {
              proxy_pass http://mongrel_example.com;
              break;
            }
          }
      }

      #English locale: en subdomain
      server {
          listen       80;

          server_name en.example.com;

          root /var/www/apps/example.com/current/public/en;

          access_log  /var/log/nginx/host.access.log  main;

          if (-f $document_root/maintenance.html){
            rewrite  ^(.&amp;amp;#42;)$  /maintenance.html last;
            break;
          }

          location /index2 {
            rewrite (.&amp;amp;#42;) / permanent;
          }

          location / {

            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect false;

            if (-f $request_filename) {
              break;
            }

            if (-f $request_filename/index.html) {
              rewrite (.&amp;amp;#42;) $1/index.html break;
            }

            if (-f $request_filename.html) {
              rewrite (.&amp;amp;#42;) $1.html break;
            }

            if (!-f $request_filename) {
              proxy_pass http://mongrel_example.com;
              break;
            }
          }
      }

      # Catalan locale: www
      server {
          listen       80;

          server_name www.example.com;

          root /var/www/apps/example.com/current/public;

          access_log  /var/log/nginx/host.access.log  main;

          if (-f $document_root/maintenance.html){
            rewrite  ^(.&amp;amp;#42;)$  /maintenance.html last;
            break;
          }

          location /index2 {
            rewrite (.&amp;amp;#42;) / permanent;
          }

          location / {
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect false;

            if (-f $request_filename) {
              break;
            }

            if (-f $request_filename/index.html) {
              rewrite (.&amp;amp;#42;) $1/index.html break;
            }

            if (-f $request_filename.html) {
              rewrite (.&amp;amp;#42;) $1.html break;
            }

            if (!-f $request_filename) {
              proxy_pass http://mongrel_example.com;
              break;
            }
          }
      }

      #Catalan locale: tld
      server {
          listen       80;

          server_name example.com;

          root /var/www/apps/example.com/current/public;

          access_log  /var/log/nginx/host.access.log  main;

          if (-f $document_root/maintenance.html){
            rewrite  ^(.&amp;amp;#42;)$  /maintenance.html last;
            break;
          }

          location /index2 {
            rewrite (.&amp;amp;#42;) / permanent;
          }

          location / {
            proxy_set_header  X-Real-IP  $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect false;

            if (-f $request_filename) {
              break;
            }

            if (-f $request_filename/index.html) {
              rewrite (.&amp;amp;#42;) $1/index.html break;
            }

            if (-f $request_filename.html) {
              rewrite (.&amp;amp;#42;) $1.html break;
            }

            if (!-f $request_filename) {
              proxy_pass http://mongrel_example.com;
              break;
            }
          }
      }

      #Catalan locale: any other subdomain (redirected to www)
      server {
          listen       80;

          server_name ca.example.com &amp;amp;#42;.example.com;
          rewrite  ^(.&amp;amp;#42;) http://www.example.com$1  permanent;
      }
  }
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;By the way, you can find this file within the resources/config directory in the mephisto_i18n plugin.&lt;/p&gt;


	&lt;h4&gt;Here doggyâ€¦&lt;/h4&gt;


	&lt;p&gt;So once we’ve got the web server all configured, it’s time to take the dog for a walk. :) Unfortunately, this &lt;a href="http://mongrel.rubyforge.org/"&gt;pup&lt;/a&gt; is going to be a tad stroppy. Right, enough with the dog lingo, let’s get down to details.&lt;/p&gt;


	&lt;p&gt;Mephisto is great. However, it likes to serve files.&lt;/p&gt;


	&lt;p&gt;- That’s not bad is it, I hear someone say.&lt;/p&gt;


	&lt;p&gt;Not at all, except when you’ve got multiple document roots. Your web server should be configured to forward any request for non-static content to mongrel. That’s fine, mongrel receives the request, and creates a rails process to handle it.&lt;/p&gt;


	&lt;p&gt;However, by default Mongrel will also attempt to serve static content if it receives a request for something available in the &lt;span class="caps"&gt;RAILS&lt;/span&gt;_ROOT/public (your application’s document root).&lt;/p&gt;


	&lt;p&gt;This “feature” allows it to be used as is (without the need for a separate web server) while developing normal applications and works great.&lt;/p&gt;


	&lt;p&gt;But imagine the scenario where a request comes in for:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
http://example.com
&lt;/code&gt;
&lt;/pre&gt;

	&lt;ol&gt;
	&lt;li&gt;The web server checks the base locale’s doc root (RAILS_ROOT/public), doesn’t find any index.html and forwards the request to mongrel.

	&lt;p&gt;Let me represent that as:&lt;/p&gt;&lt;/li&gt;
	&lt;/ol&gt;


&lt;pre&gt;
&lt;code&gt;
http://example.com =&amp;gt; [nginx] RAILS_ROOT/public/index.html ? serve : forward (forward)
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;(Is that understandable?)&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Mongrel also checks but doesn’t find any index.html in the application doc root (RAILS_ROOT/public – which is the only one mongrel knows about), so it creates a rails process which caches the result as &lt;span class="caps"&gt;RAILS&lt;/span&gt;_ROOT/public/index.html.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;This is then returned to the web server for serving to the client’s browser. i.e.&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
http://example.com/index.html (via nginx) =&amp;gt; [mongrel] RAILS_ROOT/public/index.html ? serve : pass_to_rails (pass_to_rails)
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Ok, so now we’ve cached the home page for the base locale. Let’s refresh the browser and ask for the same page. In short hand:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
http://example.com =&amp;gt; [nginx] RAILS_ROOT/public/index.html ? serve : forward (serve)
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;i.e. the web server correctly found &lt;span class="caps"&gt;RAILS&lt;/span&gt;_ROOT/public/index.html in the doc root for the base locale and served it. “yoopee” for page caching.&lt;/p&gt;


	&lt;p&gt;But now our viewer wants to see the home page in spanish, so we clicks on the “switch locale” link in the home page which sends a request for:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
http://es.example.com
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;The web server receives this and correctly identifies the doc root for the &lt;em&gt;es&lt;/em&gt; domain as &lt;span class="caps"&gt;RAILS&lt;/span&gt;_ROOT/public/es. i.e.&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
http://example.com =&amp;gt; [nginx] RAILS_ROOT/public/es/index.html ? serve : forward (forward)
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;index.html in the &lt;span class="caps"&gt;RAILS&lt;/span&gt;_ROOT/public/es doc root isn’t found so it forwards to mongrel.&lt;/p&gt;


	&lt;p&gt;Mongrel being a very alert puppy, checks to see if it can serve any static content.&lt;/p&gt;


	&lt;p&gt;Since it hasn’t got any idea about multiple doc roots, it checks the only doc root it knows about which is &lt;span class="caps"&gt;RAILS&lt;/span&gt;_ROOT/public. i.e.&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
http://es.example.com/index.html (via nginx) =&amp;gt; [mongrel] RAILS_ROOT/public/index.html ? serve : pass_to_rails (serve)
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Mongrel finds the index.html created for the base locale, and although alert, it’s not a very bright puppy so it goes ahead and serves that rather than as we’d hope; create a rails processes to cache:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
http://es.example.com/index.html =&amp;gt; RAILS_ROOT/public/es/index.html
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;So what has happened here is that the client asked for&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
http://es.example.com/index.html (RAILS_ROOT/public/es/index.html)
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;but actually got served&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
http://example.com/index.html (RAILS_ROOT/public/index.html)
&lt;/code&gt;
&lt;/pre&gt;

	&lt;h5&gt;Lay!&lt;/h5&gt;


	&lt;p&gt;This is a bit of a problem :) and I’m sure there are a number of ways to solve this (.e.g. use &lt;strong&gt;fcgi&lt;/strong&gt;/&lt;strong&gt;scgi&lt;/strong&gt;) but if you want to keep using mongrel, then you need to be able to tell mongrel that you don’t ever want it to serve static content ever again.&lt;/p&gt;


	&lt;p&gt;This way the web server is responsible for serving existing static content and mongrel is responsible for creating the static content only.&lt;/p&gt;


	&lt;p&gt;Currently (as far as I know), mongrel doesn’t have this capability nor does it support virtual hosts.&lt;/p&gt;


	&lt;p&gt;Ideally it should support virtual hosts but as it was a lot simpler, I created my own hacked version of mongrel (and the mongrel_cluster gem) to allow for an extra configuration option (&lt;strong&gt;dont_serve_static&lt;/strong&gt; default: false).&lt;/p&gt;


	&lt;p&gt;When this is set to &lt;em&gt;true&lt;/em&gt;, mongrel will diligently create rails processes for every single request that it receives, which solves our little problem nicely.&lt;/p&gt;


	&lt;p&gt;You can find these hacked versions of mongrel &lt;a href="http://www.webtypes.com/projects/files/basecamp/webtypes/webtypesthebusiness/mongrel_with_dont_serve_static.tar.gz"&gt;here&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;To install:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
#kill mongrel if its running
sudo /etc/init.d/mongrel_cluster stop
sudo gem uninstall mongrel mongrel_cluster
cd /tmp
wget http://www.webtypes.com/projects/files/basecamp/webtypes/webtypesthebusiness/mongrel_with_dont_serve_static.tar.gz
tar xvfz mongrel_with_dont_serve_static.tar.gz
cd mongrel_with_dont_serve_static
rake package
sudo gem install pkg/mongrel-1.0.1.gem
#Successfully installed mongrel, version 1.0.1
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;the same for mongrel_cluster :&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
cd projects/mongrel_cluster/
rake package
sudo gem install pkg/mongrel_cluster-0.2.1.gem
#Successfully installed mongrel_cluster, version 0.2.1
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Once you’ve got that installed, then just modify you mongrel_cluster.yml to something like:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
---
user: saimon
cwd: /var/www/apps/saimonmoore.net/current
port: "8080" 
environment: production
group: deploy
address: 127.0.0.1
pid_file: log/mongrel.pid
servers: 2
dont_serve_static: true
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Note the &lt;strong&gt;dont_serve_static: true&lt;/strong&gt;. That’ll tell mongrel to just do as it’s told and create rails processes.&lt;/p&gt;


	&lt;h5&gt;Conclusion&lt;/h5&gt;


	&lt;p&gt;Well, between these two articles, you should be able to &lt;strong&gt;globalize&lt;/strong&gt; mephisto quite easily. If you have any doubts, questions, feedback or bug reports then feel free to leave a comment here.&lt;/p&gt;


	&lt;p&gt;Hope this provides a decent i18n solution for people using Mephisto.&lt;/p&gt;


	&lt;p&gt;P.S. I’m planning on writing a third article about tips an tricks with localising your templates and other tid bits. 
Perhaps, we could offer alternative globalized versions of the main mephisto themes?&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://webtypes.com/2007/5/15/globalizing-mephisto-part-3"&gt;Want a globalized &lt;strong&gt;multi site&lt;/strong&gt; mephisto? Read Part 3&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://saimonmoore.net"&gt;Saimon Moore&lt;/a&gt; (also in &lt;a href="http://el.saimonmoore.net"&gt;Greek&lt;/a&gt;, &lt;a href="http://es.saimonmoore.net"&gt;Spanish&lt;/a&gt; &amp; &lt;a href="http://ca.saimonmoore.net"&gt;Catalan&lt;/a&gt;  :)&lt;/p&gt;
          </content>  <feedburner:origLink>http://webtypes.com/2007/3/21/globalizing-mephisto-part-2</feedburner:origLink></entry>
  <entry xml:base="http://webtypes.com/">
    <author>
      <name>webtypes</name>
    </author>
    <id>tag:webtypes.com,2007-03-18:1693</id>
    <published>2007-03-18T13:56:00Z</published>
    <updated>2007-06-05T09:09:58Z</updated>
    <category term="rails,globalize,mephisto" />
    <link href="http://feeds.feedburner.com/~r/webtypes/~3/120269300/globalizing-mephisto" rel="alternate" type="text/html" />
    <title>Globalizing Mephisto</title>
<summary type="html">&lt;p&gt;In this article I hope to walk you through the successful installation of the &lt;a href="http://rubyforge.org/projects/sidirodromos"&gt;mephisto_i18n plugin&lt;/a&gt;. This plugin converts &lt;a href="http://mephistoblog.com/"&gt;mephisto&lt;/a&gt; into a fully internationalized cms &lt;a href="/2007/3/18/globalizing-mephisto"&gt;…&lt;/a&gt;&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;In this article I hope to walk you through the successful installation of the &lt;a href="http://rubyforge.org/projects/sidirodromos"&gt;mephisto_i18n plugin&lt;/a&gt;. This plugin converts &lt;a href="http://mephistoblog.com/"&gt;mephisto&lt;/a&gt; into a fully internationalized cms &lt;a href="/2007/3/18/globalizing-mephisto"&gt;…&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the first part of a four-part series on &lt;a href="http://globalize-rails.org"&gt;Globalizing&lt;/a&gt; your &lt;a href="http://mephistoblog.com"&gt;Mephisto&lt;/a&gt; application.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Part 1 – Installation and usage for &lt;strong&gt;single site&lt;/strong&gt; mephisto&lt;/li&gt;
		&lt;li&gt;&lt;a href="/2007/3/21/globalizing-mephisto-part-2" title="this article"&gt;Part 2 – Deployment and production issues&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/2007/5/15/globalizing-mephisto-part-3"&gt;Part 3 – Installation and usage for &lt;strong&gt;multi site&lt;/strong&gt; mephisto&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="/2007/5/21/globalizing-mephisto-part-4"&gt;Part 4 – Using a &lt;strong&gt;path parameter&lt;/strong&gt; to define the locale&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;In this article I hope to walk you through the successful installation of the &lt;a href="http://rubyforge.org/projects/sidirodromos"&gt;mephisto_i18n plugin&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;In the forthcoming article I’m going to cover getting your web server properly configured and other issues related to the plugin.&lt;/p&gt;


	&lt;h5&gt;Background history&lt;/h5&gt;


	&lt;p&gt;From the clients requirements, we knew that our &lt;a href="http://amicsmuseuprecolombi.org"&gt;latest project&lt;/a&gt; had to have a decent cms tool. Since we wanted to write this using rails, we searched around and after having looked at a few possibilities we settled on Mephisto.&lt;/p&gt;


	&lt;p&gt;However, one other important requirement was for the site to be available in multiple languages (at least spanish, catalan, english and french). We knew we had more or less just the one real option, the Globalize plugin.&lt;/p&gt;


	&lt;p&gt;So I set about to “Globalize” Mephisto.&lt;/p&gt;


	&lt;h5&gt;Globalizing Mephisto&lt;/h5&gt;


	&lt;p&gt;As Mephisto is still in beta (though currently it’s stable for production use) I didn’t want to modify mephsito code directly, rather I set about writing a rails plugin which would monkey patch mephisto to add globalize support.&lt;/p&gt;


	&lt;p&gt;I decided to use subdomains to indicate the current locale of the application, mostly because it was a lot easier. Otherwise, I’d have had to add in the locale extra parameter all over the place in mephisto code.&lt;/p&gt;


	&lt;p&gt;So I decided to setup a system where by:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
example.com/ www.example.com =&amp;gt; base locale is current
es.example.com =&amp;gt; es (spanish) locale is current
fr.example.com =&amp;gt; fr (french) locale is current
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;i.e. Several virtual hosts, each of which would have their own document roots:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
RAILS_ROOT/public       =&amp;gt; doc root for base locale
RAILS_ROOT/public/es    =&amp;gt; doc root for es locale
RAILS_ROOT/public/fr    =&amp;gt; doc root for fr locale
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;With the version of Globalize at that time being 1.1, the going was quite tough, mainly because of the select/include limitations enforced by Globalize’s external storage mechanism. As time went on it became progressively more and more difficult to override the mephisto code with the globalize limitations without touching the mephisto code itself (which was my aim).&lt;/p&gt;


	&lt;p&gt;The story now diverges to the creation of the Globalize internal storage mechanism which is nicely described &lt;a href="http://saimonmoore.net/2007/3/17/globalize-internal-storage-mechanism"&gt;here&lt;/a&gt; so I won’t go into any more detail, suffice to say that with this new way of storing translations, it suddenly became a lot easier to globalize the mephisto models and I quickly got to the point where all my tests were passing.&lt;/p&gt;


	&lt;p&gt;I then had to deal with things like caching &amp; sweeping for multple doc roots, permalinks and other bits and pieces.&lt;/p&gt;


	&lt;p&gt;For our application, I then went on to create another couple of plugins to add in extra functionality specific to our application but for the needs of this article that’s enough history for now.&lt;/p&gt;


	&lt;p&gt;I’ve since cleaned up the plugin a lot, added in rake tasks to simplify the operation of migrating to the globalized system and integrated a number of extra features from our application specific code.&lt;/p&gt;


	&lt;p&gt;So let me take you through what’s necessary to migrate your mephisto installation to a fully internationalised Mephisto instance.&lt;/p&gt;


	&lt;p&gt;It just so happens, I want to do the same thing for my own personal blog so I’m going to walk you through what I did to get my own site migrated.&lt;/p&gt;


	&lt;h4&gt;Migrating http://saimonmoore.net; step by step&lt;/h4&gt;


	&lt;p&gt;So my current site is running a stock mephisto instance (Rev:2812).&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This plugin has only really been tested with Rails 1.2.x but there are changes in trunk (.e.g multiple controller view paths) that will simplify this plugin a bit but I haven’t got round to testing it with trunk yet.&lt;/p&gt;


	&lt;p&gt;Let’s go…&lt;/p&gt;


	&lt;p&gt;We start off by installing Globalize release for-1.2&lt;/p&gt;


	&lt;h5&gt;Installing the Globalize plugin&lt;/h5&gt;


	&lt;p&gt;Open up a shell and type:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$script/plugin install -x http://svn.globalize-rails.org/svn/globalize/branches/for-1.2
A    /home/saimon/dev/projects/saimonmoore.net/vendor/plugins/for-1.2/test
A    /home/saimon/dev/projects/saimonmoore.net/vendor/plugins/for-1.2/test/unit
A    /home/saimon/dev/projects/saimonmoore.net/vendor/plugins/for-1.2/test/view_picking_test.rb
A    /home/saimon/dev/projects/saimonmoore.net/vendor/plugins/for-1.2/test/render_test.rb
...
Obtained revision: 91
(in /home/saimon/dev/projects/saimonmoore.net)
Globalize has not been setup yet. Generate a migration via script/generate globalize or run rake globalize:setup
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note&lt;/em&gt;&lt;/strong&gt; that the globalize install has detected that the globalize project files haven’t been installed yet and suggests a couple of ways for you to get them in your db.&lt;/p&gt;


	&lt;p&gt;Before we setup the globalize tables I’m just going to rename the plugin to globalize as it was saved as for-1.2&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$svn pe svn:externals vendor/plugins/
globalize http://svn.globalize-rails.org/svn/globalize/branches/for-1.2
$svn up
Obtaining external item in 'vendor/plugins/globalize'
A    vendor/plugins/globalize/test
A    vendor/plugins/globalize/test/unit
...
$rm -fR vendor/plugins/for-1.2
$svn ci vendor/plugins
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Let’s check that globalize was installed properly. We should see the globalize rake tasks:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$rake -T | grep globalize
rake globalize:create_tables              # Create Globalize database tables
rake globalize:drop_tables                # Drops Globalize database tables
rake globalize:load_locale_data           # Load locale data
rake globalize:purge_locale_data          # Purge locale data
rake globalize:reset                      # Reset the Globalize data
rake globalize:setup                      # Create Globalize database tables and load locale data
rake globalize:teardown                   # Remove all globalizedata
rake globalize:test                       # Run tests
rake globalize:upgrade_schema_to_1_dot_2  # Upgrade to Globalize 1.2 schema
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Looking good…&lt;/p&gt;


	&lt;p&gt;So let’s create and populate the globalize tables:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$rake globalize:setup
(in /home/saimon/dev/projects/saimonmoore.net)
NOTICE:  CREATE TABLE crear una secuencia implÃ­cita `globalize_countries_id_seq` para la columna serial `globalize_countries.id`
NOTICE:  CREATE TABLE / PRIMARY KEY crear el Ã­ndice implÃ­cito `globalize_countries_pkey` para la tabla `globalize_countries`
NOTICE:  CREATE TABLE crear una secuencia implÃ­cita `globalize_translations_id_seq` para la columna serial `globalize_translations.id`
NOTICE:  CREATE TABLE / PRIMARY KEY crear el Ã­ndice implÃ­cito `globalize_translations_pkey` para la tabla `globalize_translations`
NOTICE:  CREATE TABLE crear una secuencia implÃ­cita `globalize_languages_id_seq` para la columna serial `globalize_languages.id`
NOTICE:  CREATE TABLE / PRIMARY KEY crear el Ã­ndice implÃ­cito `globalize_languages_pkey` para la tabla `globalize_languages`
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;I’m also going to update db/schema.rb:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$rake db:schema:dump
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;That’s globalize installed. On to the next step which is installing the mephisto_i18n plugin.&lt;/p&gt;


	&lt;h5&gt;Installing the Mephisto_I18n plugin&lt;/h5&gt;


&lt;pre&gt;
&lt;code&gt;
$script/plugin install -x svn://rubyforge.org/var/svn/sidirodromos/plugins/mephisto_i18n/trunk
A    /home/saimon/dev/projects/saimonmoore.net/vendor/plugins/mephisto_i18n/test
A    /home/saimon/dev/projects/saimonmoore.net/vendor/plugins/mephisto_i18n/test/unit
A    /home/saimon/dev/projects/saimonmoore.net/vendor/plugins/mephisto_i18n/test/unit/asset_test.rb
...
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;The plugin install hook prints out the plugin’s &lt;span class="caps"&gt;INSTALL&lt;/span&gt; file for us so we can immediately see what the next steps are.&lt;/p&gt;


	&lt;p&gt;Before we continue let’s have a look at the rake tasks available to us:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$rake -T | grep 18
rake mephisto:i18n:bootstrap                      # Bootstrap translations / Bootstrap translations
rake mephisto:i18n:set_plugin_order               # Modify config.plugins order in environment.rb to add this plugin last
rake mephisto:i18n:ui:modify_mephisto_resources   # Modify mephisto resources as needed for i18n UI
rake mephisto:i18n:ui:rename_index_file           # Rename the public/index.html file
rake mephisto:i18n:ui:restore_index_file          # Restore the public/index.html file renamed by mephisto:i18n:ui:rename_index_file task
rake mephisto:i18n:ui:restore_mephisto_resources  # Restore the mephisto resources modified by mephisto:i18n:ui:modify_mephisto_resources task
rake mephisto:i18n:ui:setup                       # Setup resources for i18n plugin / Setup resources for i18n UI plugin
rake mephisto:i18n:ui:setup_subroots              # Create the subroots according to the currently supported locales
rake mephisto:i18n:ui:teardown                    # Undo changes caused by the mephisto::i18n:ui:setup task
rake mephisto:i18n:ui:teardown_subroots           # Remove the subroots created by mephisto:i18n:ui:setup_subroots task
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;As you can see there are quite a few tasks there to help out with the installation process.&lt;/p&gt;


	&lt;h5&gt;Setting up your application for mephisto_i18n.&lt;/h5&gt;


	&lt;p&gt;Well, we’ve already installed globalize and created it’s tables, so let’s continue the installation with the following step which is:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;&lt;strong&gt;"Setup the plugin order in environment.rb"&lt;/strong&gt;.&lt;/code&gt;&lt;/pre&gt;


&lt;pre&gt;
&lt;code&gt;
$cat config/environment.rb | grep config.plugins
  # config.plugins= %W( exception_notification ssl_requirement )
&lt;/code&gt;
&lt;/pre&gt;

&lt;pre&gt;
&lt;code&gt;
$rake mephisto:i18n:set_plugin_order
&lt;/code&gt;
&lt;/pre&gt;

&lt;pre&gt;
&lt;code&gt;
$cat config/environment.rb | grep config.plugins
  config.plugins= %W(a_gems acts_as_paranoid acts_as_versioned attachment_fu dialog_helper filtered_column filtered_column_code_macro filtered_column_flickr_macro globalize labeled_form_helper liquid manage_fixtures mephisto mephisto_converters mocha permalink_fu request_routing simply_bdd simply_helpful white_list mephisto_i18n)
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;The “mephisto:i18n:set_plugin_order” task has modified the config/environment.rb file to ensure that the mephisto_i18n plugin is loaded after all the other plugins have loaded.&lt;/p&gt;


	&lt;p&gt;To do so it creates a list of the existing plugins in the plugins directory, sorts it and tags on the mephisto_i18n plugin at the end.&lt;/p&gt;


	&lt;p&gt;Don’t worry if you’ve already set the &lt;em&gt;config.plugins&lt;/em&gt; option, the task will not delete your current plugin order, but rather check for the mephisto_i18n and tag it on at the end.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: This task assumes you’re running mephisto trunk so it’s expecting the &lt;em&gt;config.plugins&lt;/em&gt; property to be there (either commented or uncommented)&lt;/p&gt;


	&lt;p&gt;Next step according to the &lt;span class="caps"&gt;INSTALL&lt;/span&gt; document:&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;“Define your base locale and supported locales”&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;I want to support English, Spanish, Catalan and Greek in my blog, with English being the base locale.&lt;/p&gt;


	&lt;p&gt;So edit the config/environment.rb to look something like this:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$tail -n3 config/environment.rb
include Globalize
SupportedLocales.define(['gr-GR', 'es-ES', 'ca-ES'],'en-UK')
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;We’re now ready to globalize the mephisto tables which couldn’t be easier.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;“Globalize the Mephisto tables”&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Just run:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$script/runner 'Mephisto::Plugins::MephistoI18n.install'
./script/../config/../vendor/plugins/mephisto_i18n/lib/globalize/supported_locales.rb:291:in `setup': Language for code: gr-GR doesn't exist! Check globalize tables. (RuntimeError)    from ./script/../config/../vendor/plugins/mephisto_i18n/lib/globalize/supported_locales.rb:289:in `collect'
from ./script/../config/../vendor/plugins/mephisto_i18n/lib/globalize/supported_locales.rb:289:in `setup'
    from ./script/../config/../vendor/plugins/mephisto_i18n/lib/globalize/supported_locales.rb:68:in `initialize'
    from ./script/../config/../vendor/plugins/mephisto_i18n/lib/globalize/supported_locales.rb:44:in `new'
    from ./script/../config/../vendor/plugins/mephisto_i18n/lib/globalize/supported_locales.rb:44:in `define'
    from ./script/../config/../config/environment.rb:95
    from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
    from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
    from /usr/lib/ruby/gems/1.8/gems/rails-1.2.2/lib/commands/runner.rb:39
    from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
    from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
    from script/runner:3
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Oops what happened there? Ah I see the problem. ‘gr’ is not a valid language code. The correct code is ‘el’ for greek. Quick fix and …&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$tail -n3 config/environment.rb
include Globalize
SupportedLocales.define(['el-GR', 'es-ES', 'ca-ES'],'en-UK')
&lt;/code&gt;
&lt;/pre&gt;

&lt;pre&gt;
&lt;code&gt;
$script/runner 'Mephisto::Plugins::MephistoI18n.install'
Run 'script/runner -h' for help.
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Hmm…. that didn’t work either. If you get this, this is just a typo in the &lt;span class="caps"&gt;INSTALL&lt;/span&gt; document which I’ve now corrected.&lt;/p&gt;


	&lt;p&gt;The &lt;strong&gt;correct command&lt;/strong&gt; is:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$script/runner 'Mephisto::Plugins::I18n.install'
Adding globalize columns
-- add_column(:assets, "title_el", :string)
   -&amp;gt; 0.1035s
-- add_column(:contents, "title_el", :string)
   -&amp;gt; 0.0166s
-- add_column(:contents, "excerpt_el", :text)
   -&amp;gt; 0.0284s
-- add_column(:contents, "body_el", :text)
   -&amp;gt; 0.0164s
....
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;You can rollback these changes at any time via:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$script/runner 'Mephisto::Plugins::I18n.uninstall'
-- remove_column(:assets, "title_el")
   -&amp;gt; 0.3864s
-- remove_column(:contents, "title_el")
   -&amp;gt; 0.0209s
-- remove_column(:contents, "excerpt_el")
...
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Let’s save these changes to the schema.rb file:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$rake db:schema:dump
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Have a look at the &lt;em&gt;db/schema.rb&lt;/em&gt; file to see the changes the plugin has made to the mephisto tables.&lt;/p&gt;


	&lt;p&gt;Finally, the last part of the installation has to do with setting up the different document roots for each of the virtual hosts (each representing one of the non-base locales).&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;“Setting up the Mephisto I18n resources”&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Thankfully, another rake task sets this all up for us nicely:&lt;/p&gt;


	&lt;p&gt;I’m going to show you what changes the task makes by showing you before and after snapshots of certain directories:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$ls -la public/
total 33
drwxr-xr-x  8 saimon users  488 mar 19 13:26 .
drwxr-xr-x 15 saimon users  520 mar 19 16:19 ..
-rw-r--r--  1 saimon users  619 sep 11  2006 404.html
-rw-r--r--  1 saimon users  684 sep 11  2006 500.html
drwxr-xr-x  4 saimon users   96 mar 19 13:43 assets
-rwxr-xr-x  1 saimon users  479 dic 29  2005 dispatch.cgi
-rwxr-xr-x  1 saimon users  859 jun 14  2006 dispatch.fcgi
-rwxr-xr-x  1 saimon users  479 dic 29  2005 dispatch.rb
drwxr-xr-x  5 saimon users  120 nov  6 15:08 documents
-rw-r--r--  1 saimon users    0 dic 29  2005 favicon.ico
drwxr-xr-x  4 saimon users   96 oct 11 09:27 images
-rw-r--r--  1 saimon users 3325 nov  4 18:06 install.html
drwxr-xr-x  4 saimon users   96 oct 11 09:27 javascripts
-rw-r--r--  1 saimon users   99 dic 29  2005 robots.txt
-rw-r--r--  1 saimon users  631 nov  9 14:56 sitemap.txt
drwxr-xr-x  4 saimon users   96 oct 11 09:27 stylesheets
drwxr-xr-x  7 saimon users  296 mar 19 16:19 .svn
&lt;/code&gt;
&lt;/pre&gt;

&lt;pre&gt;
&lt;code&gt;
$rake mephisto:i18n:ui:setup
&lt;/code&gt;
&lt;/pre&gt;

&lt;pre&gt;
&lt;code&gt;
$ls -la public
total 33
drwxr-xr-x 11 saimon users  560 mar 19 16:54 .
drwxr-xr-x 15 saimon users  520 mar 19 16:19 ..
-rw-r--r--  1 saimon users  619 sep 11  2006 404.html
-rw-r--r--  1 saimon users  684 sep 11  2006 500.html
drwxr-xr-x  4 saimon users   96 mar 19 13:43 assets
drwxr-xr-x  2 saimon users  280 mar 19 16:54 ca
-rwxr-xr-x  1 saimon users  479 dic 29  2005 dispatch.cgi
-rwxr-xr-x  1 saimon users  859 jun 14  2006 dispatch.fcgi
-rwxr-xr-x  1 saimon users  479 dic 29  2005 dispatch.rb
drwxr-xr-x  5 saimon users  120 nov  6 15:08 documents
drwxr-xr-x  2 saimon users  280 mar 19 16:54 el
drwxr-xr-x  2 saimon users  280 mar 19 16:54 es
-rw-r--r--  1 saimon users    0 dic 29  2005 favicon.ico
drwxr-xr-x  4 saimon users   96 oct 11 09:27 images
-rw-r--r--  1 saimon users 3325 nov  4 18:06 install.html
drwxr-xr-x  4 saimon users   96 oct 11 09:27 javascripts
-rw-r--r--  1 saimon users   99 dic 29  2005 robots.txt
-rw-r--r--  1 saimon users  631 nov  9 14:56 sitemap.txt
drwxr-xr-x  4 saimon users   96 oct 11 09:27 stylesheets
drwxr-xr-x  7 saimon users  296 mar 19 16:19 .svn
&lt;/code&gt;
&lt;/pre&gt;

&lt;pre&gt;
&lt;code&gt;
$ls -la public/es/
total 1
drwxr-xr-x  2 saimon users 280 mar 19 16:54 .
drwxr-xr-x 11 saimon users 560 mar 19 16:54 ..
lrwxrwxrwx  1 saimon users  67 mar 19 16:54 404.html-&amp;gt; /home/saimon/dev/projects/saimonmoore.net/config/../public/404.html
lrwxrwxrwx  1 saimon users  67 mar 19 16:54 500.html-&amp;gt; /home/saimon/dev/projects/saimonmoore.net/config/../public/500.html
lrwxrwxrwx  1 saimon users  70 mar 19 16:54 favicon.ico-&amp;gt; /home/saimon/dev/projects/saimonmoore.net/config/../public/favicon.ico
lrwxrwxrwx  1 saimon users  65 mar 19 16:54 images-&amp;gt; /home/saimon/dev/projects/saimonmoore.net/config/../public/images
lrwxrwxrwx  1 saimon users  71 mar 19 16:54 install.html-&amp;gt; /home/saimon/dev/projects/saimonmoore.net/config/../public/install.html
lrwxrwxrwx  1 saimon users  70 mar 19 16:54 javascripts-&amp;gt; /home/saimon/dev/projects/saimonmoore.net/config/../public/javascripts
lrwxrwxrwx  1 saimon users  69 mar 19 16:54 robots.txt-&amp;gt; /home/saimon/dev/projects/saimonmoore.net/config/../public/robots.txt
lrwxrwxrwx  1 saimon users  70 mar 19 16:54 stylesheets-&amp;gt; /home/saimon/dev/projects/saimonmoore.net/config/../public/stylesheets
&lt;/code&gt;
&lt;/pre&gt;

&lt;pre&gt;
&lt;code&gt;
$ls -la app/views/layouts/
total 8
drwxr-xr-x  3 saimon users  192 mar 19 16:54 .
drwxr-xr-x 11 saimon users  320 mar 19 16:54 ..
-rw-r--r--  1 saimon users 3683 feb 19 14:52 application.original.rhtml
lrwxrwxrwx  1 saimon users  125 mar 19 16:54 application.rhtml-&amp;gt; /home/saimon/dev/projects/saimonmoore.net/config/../vendor/plugins/mephisto_i18n/tasks/../app/views/layouts/application.rhtml
-rw-r--r--  1 saimon users 1367 nov 22 16:07 simple.rhtml
drwxr-xr-x  7 saimon users  296 mar 19 16:19 .svn
&lt;/code&gt;
&lt;/pre&gt;

&lt;pre&gt;
&lt;code&gt;
$ls -la app/views
total 1
drwxr-xr-x 11 saimon users 320 mar 19 16:54 .
drwxr-xr-x 11 saimon users 272 mar 18 20:02 ..
drwxr-xr-x  3 saimon users 136 mar 18 20:02 account
drwxr-xr-x 19 saimon users 488 mar 18 20:07 admin
drwxr-xr-x  3 saimon users  72 mar 18 20:02 assets
drwxr-xr-x  3 saimon users  72 mar 18 20:02 comments
drwxr-xr-x  3 saimon users 168 mar 18 20:02 feed
lrwxrwxrwx  1 saimon users 104 mar 19 16:54 i18n-&amp;gt; /home/saimon/dev/projects/saimonmoore.net/config/../vendor/plugins/mephisto_i18n/tasks/../app/views/i18n
drwxr-xr-x  3 saimon users 192 mar 19 16:54 layouts
drwxr-xr-x  3 saimon users 168 mar 18 20:02 mephisto
drwxr-xr-x  7 saimon users 296 mar 19 16:19 .svn
drwxr-xr-x  3 saimon users 112 mar 18 20:02 user_mailer
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;As you can see it has made a few changes including:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Creating three extra subdirectories in &lt;span class="caps"&gt;RAILS&lt;/span&gt;_ROOT/public, one for each non-base locale (Remember the base locale’s doc root is just &lt;span class="caps"&gt;RAILS&lt;/span&gt;_ROOT/public) and symlinked in common files from &lt;span class="caps"&gt;RAILS&lt;/span&gt;_ROOT/public.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Overriding the admin layout template, symlinking it to one provided with the plugin. (The original is still there just in case)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Adding an extra folder ‘i18n’ to the views directory (symlinked). This is for a custom controller that takes care of switching the current locale in the admin interface.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;If you decide that you didn’t really want to install this plugin in the first place and you want to rollback all these changes then just run:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
rake mephisto:i18n:ui:teardown
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;This will return your original files and directories to their rightfull places.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;“Modify the session domain”&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Finally, the last step in the &lt;span class="caps"&gt;INCLUDE&lt;/span&gt; document advises us to modify the &lt;em cite="s"&gt;ession_domain&lt;/em&gt; option in ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS
so that when we switch between subdomains in the same session, the session doesn’t get lost.&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$tail -n1 config/environments/development.rb
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.update(:session_domain =&amp;gt; '.saimonmoore.net')
&lt;/code&gt;
&lt;/pre&gt;

&lt;pre&gt;
&lt;code&gt;
$tail -n1 config/environments/production.rb
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.update(:session_domain =&amp;gt; '.saimonmoore.net')
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Phew…that was quite a bit of work. Let’s see what this plugin has actually bought us.&lt;/p&gt;


	&lt;h5&gt;The Final Result&lt;/h5&gt;


	&lt;p&gt;We start up mongrel:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$ mongrel_rails start
 ** Starting Mongrel listening at 0.0.0.0:3000
 ** Starting Rails with development environment...
 ** Mongrel is serving static files.
 ** Rails loaded.
 ** Loading any Rails specific GemPlugins
 ** Signals ready.  TERM =&amp;gt; stop.  USR2 =&amp;gt; restart.  INT =&amp;gt; stop (no restart).
 ** Rails signals registered.  HUP =&amp;gt; reload (without restart).  It might not work well.
 ** Mongrel available at 0.0.0.0:3000
 ** Use CTRL-C to stop.
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Let’s go to the administration interface of our globalized mephisto application.&lt;/p&gt;


	&lt;p&gt;Note: I’ve temporarily redirected the &lt;strong&gt;.saimonmoore.net domain to localhost for testing purposes.&lt;/p&gt;


	&lt;p&gt;I’ve made a &lt;a href="http://www.debugmode.com/wink"&gt;wink&lt;/a&gt; presentation out of this next part as I think it’s the quickest way to see what exactly you can do.&lt;/p&gt;


	&lt;p&gt;Click &lt;a href="http://www.webtypes.com/files/globalizing_mephisto_small.htm"&gt;here&lt;/a&gt; to see the presentation.&lt;/p&gt;


	&lt;p&gt;Next week, I’ll conclude this two-part series with the second part where I’ll be talking about the production deployment issues that arise with this plugin.&lt;/p&gt;


	&lt;p&gt;[&lt;/strong&gt;Update&lt;strong&gt;] I’ve just detected a slight problem with the symlinking in the  mephisto:i18n:ui:setup rake task. It creates absolute symlinks which isn’t very handy for deployment. I’ll be fixing this asap.&lt;/p&gt;


	&lt;p&gt;[&lt;/strong&gt;Update&lt;strong&gt;] This is now fixed so you’ll want at least revision 26 of the plugin&lt;/p&gt;


	&lt;p&gt;[&lt;/strong&gt;Update&lt;strong&gt;] Currently there is a requirement to install the ‘unicode’ gem. I’m working to remove this dependency from the plugin.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://webtypes.com/2007/3/21/globalizing-mephisto-part-2"&gt;Ready to deploy? Read *Part 2&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
          </content>  <feedburner:origLink>http://webtypes.com/2007/3/18/globalizing-mephisto</feedburner:origLink></entry>
  <entry xml:base="http://webtypes.com/">
    <author>
      <name>webtypes</name>
    </author>
    <id>tag:webtypes.com,2007-03-15:1692</id>
    <published>2007-03-15T19:13:00Z</published>
    <updated>2007-05-16T14:36:21Z</updated>
    <category term="sysadmin" />
    <link href="http://feeds.feedburner.com/~r/webtypes/~3/120269301/announcing-capistrano-server-extensions" rel="alternate" type="text/html" />
    <title>Announcing Capistrano Server Extensions</title>
<summary type="html">&lt;p&gt;Maybe you’ve heard of &lt;a href="http://manuals.rubyonrails.com/read/book/17"&gt;Capistrano&lt;/a&gt; a tool written by &lt;a href="http://weblog.jamisbuck.org"&gt;Jamis Buck&lt;/a&gt; in Ruby that helps you automate deployment to multiple servers. 
&lt;a href="http://codemode.blogspot.com"&gt;Mike Bailey&lt;/a&gt; wrote the &lt;a href="http://deprec.rubyforge.org/"&gt;deprec gem&lt;/a&gt; based on capistrano to automate setting up of ubuntu servers with &lt;a href="http://httpd.apache.org/"&gt;Apache&lt;/a&gt; and &lt;a href="http://www.mysql.com/"&gt;MySQL&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I needed a slightly different setup (&lt;a href="http://sysoev.ru/en/"&gt;nginx&lt;/a&gt; &amp; &lt;a href="http://www.postgresql.org/"&gt;postgres&lt;/a&gt;). Read on for how to easily setup any combination of rails/mongrel/apache/nginx/mysql/postgres.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Maybe you’ve heard of &lt;a href="http://manuals.rubyonrails.com/read/book/17"&gt;Capistrano&lt;/a&gt; a tool written by &lt;a href="http://weblog.jamisbuck.org"&gt;Jamis Buck&lt;/a&gt; in Ruby that helps you automate deployment to multiple servers. 
&lt;a href="http://codemode.blogspot.com"&gt;Mike Bailey&lt;/a&gt; wrote the &lt;a href="http://deprec.rubyforge.org/"&gt;deprec gem&lt;/a&gt; based on capistrano to automate setting up of ubuntu servers with &lt;a href="http://httpd.apache.org/"&gt;Apache&lt;/a&gt; and &lt;a href="http://www.mysql.com/"&gt;MySQL&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I needed a slightly different setup (&lt;a href="http://sysoev.ru/en/"&gt;nginx&lt;/a&gt; &amp; &lt;a href="http://www.postgresql.org/"&gt;postgres&lt;/a&gt;). Read on for how to easily setup any combination of rails/mongrel/apache/nginx/mysql/postgres.&lt;/p&gt;
&lt;p&gt;Maybe you’ve heard of &lt;a href="http://manuals.rubyonrails.com/read/book/17"&gt;Capistrano&lt;/a&gt; a tool written by &lt;a href="http://weblog.jamisbuck.org"&gt;Jamis Buck&lt;/a&gt; in Ruby that helps you automate deployment to multiple servers.&lt;/p&gt;


	&lt;h4&gt;Capistrano &amp; Deprec&lt;/h4&gt;


	&lt;p&gt;This ‘gem’  of a gem is huge time saver. Believe me, anyone who has used it has surely reaped the benefits of&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$ cap --apply-to .
$ cap setup
$ cap deploy
$ cap rollback
$ cap update_current
$ cap watch_load
$ cap uptime
$ cap disable/enable_web
$ cap some_long_complex_task_that_would_normally_take_more_than_a_couple_of_hours_if_done_manually

etc....
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;This beauty is such a versatile beast (pun intended) that you can easily automate tasks for a range of use cases (app deployment, system administration, backups, profiling, benchmarking etc etc)&lt;/p&gt;


	&lt;p&gt;And many people have gone ahead and extended capistrano to do  their bidding with evermore complex tasks.&lt;/p&gt;


	&lt;p&gt;One such person is &lt;a href="http://codemode.blogspot.com"&gt;Mike Bailey&lt;/a&gt; who was obviously really pissed off at having to setup the same old software on every new &lt;span class="caps"&gt;VPS&lt;/span&gt; he was configuring for his clients. (Please note that this is pure speculation and the real reason may in fact be very different). In any case, he decided to remedy the situation and wrote the &lt;a href="http://deprec.rubyforge.org/"&gt;deprec gem&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;What does deprec do?&lt;/p&gt;


	&lt;p&gt;It basically augments capistrano to allow you to do things like:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$ cap setup_ssh_keys   # copy out your public keys
$ cap install_rails_stack # install apache, ruby &amp; rubygems, mongrel, rails on the hosts defined in your capistrano recipe etc.
$ deprec --apply-to . --name bailey --domain bailey.net.au
$ cap deprec_setup #setup your application to allow easy server setups
$ cap deploy_with_migrations #deploy your application
$ cap restart_mongrel_cluster #start app server
$ cap restart_apache #start web server
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;i.e with this gem you can very easily setup a brand new &lt;span class="caps"&gt;VPS&lt;/span&gt; with a full rails stack including the MySQL database and Apache 2 web server.&lt;/p&gt;


	&lt;h4&gt;Customizing Deprec&lt;/h4&gt;


	&lt;p&gt;When I first discovered deprec, I immediately realised that this was going to be saving me a lot of time when setting up our own clients &lt;span class="caps"&gt;VPS&lt;/span&gt;’, but I wasn’t really enamoured of the choices of web server or database. Furthermore I wanted to be able to select the right tools for the job. For one client I may use MySQL but for another I’d use postgres (Well actually I prefer using postgres always but maybe you’d like to do that :).&lt;/p&gt;


	&lt;p&gt;My current preference for a rails stack is the following very lightweight setup:&lt;/p&gt;


	&lt;p&gt;Nginx =&amp;gt; Mongrel =&amp;gt; Rails =&amp;gt; Postgres&lt;/p&gt;


	&lt;p&gt;So as we had a couple of small new clients whose servers needed setting up I spent a couple of days and wrote my own extensions to deprec that added support for &lt;a href="http://sysoev.ru/en/"&gt;nginx&lt;/a&gt; (see &lt;a href="http://wiki.codemongers.com/Nginx"&gt;this&lt;/a&gt; for details) and &lt;a href="http://www.postgresql.org/"&gt;PostgreSQL&lt;/a&gt;.
I also added a few other bits and pieces that allowed me to do things that I like to do with every new &lt;span class="caps"&gt;VPS I&lt;/span&gt; setup.&lt;/p&gt;


	&lt;h4&gt;Exploring Capistrano Server Extensions&lt;/h4&gt;


	&lt;p&gt;So first off we install the &lt;a href="http://rubyforge.org/projects/capserverext/"&gt;Capistrano Server Extensions&lt;/a&gt; gem (very lame name I know) via:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
sudo gem install -y capserverext
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;That’ll bring down all required dependencies including capistrano and deprec if you don’t already have them.&lt;/p&gt;


&lt;div&gt;
&lt;em&gt;Side Note&lt;/em&gt;

	&lt;p&gt;I’m unashamedly assuming I’m talking to a &lt;strong&gt;Ruby&lt;/strong&gt; crowd and that you have at least ruby 1.8.4 installed but let me say one thing to the other crowds out there:&lt;/p&gt;


	&lt;p&gt;“Get ruby installed and try this out”&lt;/p&gt;


	&lt;p&gt;It doesn’t matter whether your setting up &lt;span class="caps"&gt;LAMP&lt;/span&gt; servers, or j2ee servers, this stuff kicks real ass and will save the day for you on many occasions, seriously.  (I’m a converted java programmer myself so I know this would come in really handily for setting up something like the jdk, Tomcat/Jetty/Resin, JBoss/Geronimo)&lt;/p&gt;


	&lt;p&gt;Heck we could even spiff it up to install Oracle. Now  that’s a great idea. Imagine being able to preselect a type of Oracle setup and just typing: $ cap install oracle_cluster
and go away for a cuppa.&lt;/p&gt;


	&lt;p&gt;Anyway I’m diverging a lot I know…sorry.&lt;/p&gt;


&lt;/div&gt;

	&lt;p&gt;So once capserverext has been installed your first action is to&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$ cap show_tasks
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Which will show you a bewildering &lt;a href="http://pastie.caboo.se/47330"&gt;list&lt;/a&gt; of possible tasks to perform.&lt;/p&gt;


	&lt;p&gt;From this list you can pick and choose, mix and match different tasks for every occasion.&lt;/p&gt;


	&lt;p&gt;But let’s run through what you’d need to do to get a rails stack setup with nginx and postgres (currently only on a Ubuntu server but I’m working on supporting debian and Gentoo).&lt;/p&gt;


	&lt;p&gt;First let’s ask capistrano to tell us what we should do to use this thing. Type:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$ cap capserverext_usage
 * executing task capserverext_usage
      * rails myproject
      * cd /path/to/myproject
      * deprec --apply-to . --name user --domain myprojectsdomain.com
      * Add following entries to deploy.rb:
          require 'capserverext/recipes'
          require 'capistrano/ext/monitor'

      * Edit deploy.rb appropriately:
        * set deprec_combination to either (:nginx_postgres, :nginx_mysql, :apache_mysql, :apache_postgres)
          for a combination other than the default: ':nginx_postgres'
        * set ssh_security_port for an ssh port other than the default 22 (Defaults to: '8888')
        * set mongrel options (best to accept the defaults)
        * set repository
        * any other custom options

      * run: "cap prepare_ssh" 
      * set ssh_options[:port] to the value of ssh_security_port in deploy.rb
      * run: "cap prepare_host" 
&lt;/code&gt;
&lt;/pre&gt;

	&lt;h4&gt;Using Capistrano Server Extensions&lt;/h4&gt;


	&lt;p&gt;Thanks, that was handy. Now let me type the following:&lt;/p&gt;


	&lt;p&gt;On my local machine:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$ cd ~/dev/freelance
$ rails amicmuseuprecolombi.org   #A domain for one of my apps
$ cd amicsmuseuprecolombi.org
$ deprec --apply-to . --name saimon --domain amicsmuseuprecolombi.org
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;This’ll create a deploy.rb capistrano recipe for us in ./config/deploy.rb.&lt;/p&gt;


	&lt;p&gt;Quickly edit it to add:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
  require 'capserverext/recipes'
  set :deprec_combination, :nginx_postgres
  set :repository, "http://www.webtypes.com/svn/projects/#{application}/trunk" 

  set :mongrel_servers, nginx_proxy_servers
  set :mongrel_port, nginx_proxy_port
  set :mongrel_address, nginx_proxy_address
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Now type:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
  $ cap prepare_ssh
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;And set the secure_ssh_port in deploy.rb to 8888 like so:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
set ssh_options[:port], 8888
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;Now finally type:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
  $ cap prepare_host
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;When that’s done type:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
  $ cap deploy_with_migrations
  $ cap restart_mongrel_cluster
  $ cap restart_nginx
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;That takes about a total of 10 minutes from start to finish!&lt;/p&gt;


	&lt;p&gt;And visit http://amicsmuseuprecolombi.org (Our latest creation based on a &lt;a href="http://www.globalize-rails.org/globalize/"&gt;globalized&lt;/a&gt; version of &lt;a href="http://mephistoblog.com"&gt;Mephisto&lt;/a&gt;) to see the result of having typed in those few commands. Well we also wrote the code for the site but you get the gist :)&lt;/p&gt;


	&lt;p&gt;Yep that’s all it takes to get a lean rails stack setup on your server .&lt;/p&gt;


	&lt;h4&gt;Variations on the same theme&lt;/h4&gt;


	&lt;p&gt;“I haven’t heard of nginx before. Can’t I use Apache?” someone says.&lt;/p&gt;


	&lt;p&gt;No problem. Set:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
  set :deprec_combination, :apache_postgres

  $ cap prepare_host
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;“I prefer MySQL.” another says.&lt;/p&gt;


	&lt;p&gt;No problem. Set:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
  set :deprec_combination, :nginx_mysql

  $ cap prepare_host
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;“No I meant with Apache.” they say again.&lt;/p&gt;


	&lt;p&gt;No problem. Set:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
  set :deprec_combination, :apache_mysql

  $ cap prepare_host
&lt;/code&gt;
&lt;/pre&gt;

	&lt;h4&gt;Under the cover&lt;/h4&gt;


	&lt;p&gt;Some of you will be asking what do these commands do exactly and I’ll point those of you to the very readable source code of the &lt;a href="http://rubyforge.org/projects/capserverext/"&gt;capserverext&lt;/a&gt; gem and the &lt;a href="http://deprec.rubyforge.org/"&gt;deprec&lt;/a&gt; gem. (&lt;a href="http://svn.rubyonrails.org/rails/tags/capistrano_1-4-1"&gt;Capistrano&lt;/a&gt; code is also very readable but you don’t need to go that far.)&lt;/p&gt;


	&lt;p&gt;So what will capserverext do remotely:&lt;/p&gt;


	&lt;p&gt;The prepare_ssh task will:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Connect via root and set root’s password&lt;/li&gt;
		&lt;li&gt;Change ssh port for security reasons&lt;/li&gt;
		&lt;li&gt;Create a deployment user, add it to the ‘deploy’ group&lt;/li&gt;
	&lt;/ul&gt;


The prepare_host task will:
	&lt;ul&gt;
	&lt;li&gt;Connect with the deployment user and copy over your local machines public ssh keys.&lt;/li&gt;
		&lt;li&gt;Reconnect without asking for passwords anymore (apart from the first time it uses sudo)&lt;/li&gt;
		&lt;li&gt;Give the deployment user sudo privileges.&lt;/li&gt;
		&lt;li&gt;enable the ubuntu ‘universe’ repository&lt;/li&gt;
		&lt;li&gt;Install requisites allowing compilation of other packages, ruby, subversion, openssl&lt;/li&gt;
		&lt;li&gt;Install the PostgreSQL database server (8.1)&lt;/li&gt;
		&lt;li&gt;Install rubygems&lt;/li&gt;
		&lt;li&gt;Install rails, mongrel, mongrel_cluster and builder&lt;/li&gt;
		&lt;li&gt;Install nginx&lt;/li&gt;
		&lt;li&gt;setup generic deployment paths&lt;/li&gt;
		&lt;li&gt;setup app specific deployment paths&lt;/li&gt;
		&lt;li&gt;Configure nginx for production&lt;/li&gt;
		&lt;li&gt;Configure postgres for production (Creates a new database according to the name given for the production environment in database.yml, a database user and gives access privileges to that user)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;That’s it. And you can do this again and again, over and over, on any number of hosts.&lt;/p&gt;


	&lt;p&gt;The beauty of this is that many tasks are composed of other smaller tasks so you can execute a specific task without having to run the whole lot.&lt;/p&gt;


	&lt;p&gt;Say you want to just install and configure nginx:&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$ cap install_nginx
$ cap setup_web_for_nginx
&lt;/code&gt;
&lt;/pre&gt;

	&lt;p&gt;or just apache&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
$ cap install_apache
$ cap setup_web  (deprec task)
&lt;/code&gt;
&lt;/pre&gt;

	&lt;h4&gt;Conclusion&lt;/h4&gt;


	&lt;p&gt;Let me conclude by saying that I hope this article has shown you the flexibility and usefullness that Capistrano can be put to and how easily you can now setup your &lt;span class="caps"&gt;VPS&lt;/span&gt; servers for most combinations of setup.&lt;/p&gt;


	&lt;p&gt;Of course there’ll be a lot of you that need to tweak things for their own purposes, just create a ~/.caprc file and customize away (That’s how I did it)&lt;/p&gt;


	&lt;p&gt;I’m going to continue working on this to add support for more linux distributions. Mac server users will have to wait until I decide to make the jump (It’ll inevitably come but I’m not sure when yet).&lt;/p&gt;


	&lt;p&gt;If you found this handy or useful please provide feedback and also let &lt;a href="http://codemode.blogspot.com"&gt;Mike Bailey&lt;/a&gt; know and then we can perhaps integrate this stuff into &lt;a href="http://deprec.rubyforge.org"&gt;deprec&lt;/a&gt; (so you don’t need to be installing two separate gems).&lt;/p&gt;


	&lt;p&gt;Thanks for reading,&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://saimonmoore.net"&gt;Saimon Moore&lt;/a&gt;&lt;/p&gt;
          </content>  <feedburner:origLink>http://webtypes.com/2007/3/15/announcing-capistrano-server-extensions</feedburner:origLink></entry>
  <entry xml:base="http://webtypes.com/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:webtypes.com,2007-01-15:1691</id>
    <published>2007-01-15T18:59:00Z</published>
    <updated>2008-08-11T10:46:39Z</updated>
    <category term="design" />
    <link href="http://feeds.feedburner.com/~r/webtypes/~3/120269302/ie7-finally-an-excuse-to-use-ie7js" rel="alternate" type="text/html" />
    <title>IE7. Finally an excuse to use IE7.js</title>
<content type="html">
            &lt;p&gt;Before the launch of Internet Explorer 7(IE7), using the &lt;a href="http://dean.edwards.name/IE7/"&gt;&lt;span class="caps"&gt;IE7&lt;/span&gt; javascript library&lt;/a&gt; from genius &lt;a href="http://dean.edwards.name/"&gt;Dean Edwards&lt;/a&gt; to make Internet Explorer 6(IE6) behave, just wasn’t a real option most of the time. It’s hard to motivate your client to accept that most of their visitors would have to wait a considerable amount of extra seconds before their page would look like it’s supposed to look&lt;/p&gt;


	&lt;p&gt;Since the release of &lt;span class="caps"&gt;IE7&lt;/span&gt; (as a semi-automatic update of &lt;span class="caps"&gt;IE6&lt;/span&gt;), this has changed. Or at least it feels like it has.&lt;/p&gt;


	&lt;p&gt;Suddenly &lt;span class="caps"&gt;IE6&lt;/span&gt; has become an old browser for which it no longer seems worthwhile to sacrifice new design possibilities. And even though there are still &lt;a href="http://blogs.msdn.com/ie/archive/2007/01/12/100-million-ie7-installations.aspx"&gt;lots of people out there using &lt;span class="caps"&gt;IE6&lt;/span&gt;&lt;/a&gt;, they now do have an alternative which is almost harder not to install than to install.&lt;/p&gt;


	&lt;p&gt;So yes, somehow it feels right to let &lt;span class="caps"&gt;IE6&lt;/span&gt; people wait a little longer  and give them a less than optimal experience in 2007. Of course it helps when your client is using &lt;span class="caps"&gt;IE7&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Now, if only &lt;span class="caps"&gt;IE7&lt;/span&gt;.js made alpha transparent css background images possible…&lt;/p&gt;
          </content>  <feedburner:origLink>http://webtypes.com/2007/1/15/ie7-finally-an-excuse-to-use-ie7js</feedburner:origLink></entry>
  <entry xml:base="http://webtypes.com/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:webtypes.com,2006-06-02:1690</id>
    <published>2006-06-02T09:11:00Z</published>
    <updated>2007-05-16T14:36:51Z</updated>
    <category term="business" />
    <link href="http://feeds.feedburner.com/~r/webtypes/~3/120269303/do-you-mean-wetlips" rel="alternate" type="text/html" />
    <title>Did you mean wetlips?</title>
<content type="html">
            &lt;p&gt;&lt;img title="searching for webtypes in Googleâ„¢" src="/images/2.png" alt="searching for webtypes in Googleâ„¢" /&gt; The day &lt;a href="http://www.google.com/search?q=webtypes"&gt;this search suggestion&lt;/a&gt; disappears we will know we exist.&lt;/p&gt;


	&lt;p&gt;The day Googleâ„¢ will ask me ‘did you mean webtypes’ while doing my weekly &lt;a href="http://www.google.com/search?q=wetlips"&gt;search for wetlips&lt;/a&gt;, we will know we ruleâ€¦&lt;/p&gt;
          </content>  <feedburner:origLink>http://webtypes.com/2006/6/2/do-you-mean-wetlips</feedburner:origLink></entry>
  <entry xml:base="http://webtypes.com/">
    <author>
      <name>saimon</name>
    </author>
    <id>tag:webtypes.com,2006-03-31:1688</id>
    <published>2006-03-31T16:03:00Z</published>
    <updated>2007-05-16T14:37:35Z</updated>
    <category term="ruby" />
    <link href="http://feeds.feedburner.com/~r/webtypes/~3/120269305/rake-completion-script-that-handles-namespaces" rel="alternate" type="text/html" />
    <title>Rake-completion script that handles namespaces</title>
<content type="html">
            &lt;p&gt;Thanks to &lt;a href="http://wiki.rubyonrails.com/rails/pages/NicholasSeckar"&gt;Nicholas Seckar&lt;/a&gt; for the &lt;a href="http://i.conio.net/rake-completion.rb"&gt;rake-completion&lt;/a&gt; script.&lt;/p&gt;


	&lt;p&gt;It’s real time saver. But now that rake 0.7.0 has arrived it’s introduced namespaces which are very handy.&lt;/p&gt;


	&lt;p&gt;When I recently &lt;a href="http://manuals.rubyonrails.com/read/book/17"&gt;capped&lt;/a&gt; our latest app I added some custom recipes to the remote: namespace and added a couple of new namespaces as well.&lt;/p&gt;


	&lt;p&gt;Namespaces however broke rake-completion and I was getting a bit annoyed at that so I looked into it and here you have a version of &lt;a href="http://www.webtypes.com/files/rake-completion.rb"&gt;rake-completion.rb&lt;/a&gt; which correctly handles rake namespaces.&lt;/p&gt;


	&lt;p&gt;Enjoy….&lt;/p&gt;


	&lt;p&gt;[Update] &lt;a href="http://onrails.org/articles/2006/08/30/namespaces-and-rake-command-completion"&gt;Lee Marlow&lt;/a&gt;
has produced a new and improved version of this which is recommended over this.&lt;/p&gt;
          </content>  <feedburner:origLink>http://webtypes.com/2006/3/31/rake-completion-script-that-handles-namespaces</feedburner:origLink></entry>
  <entry xml:base="http://webtypes.com/">
    <author>
      <name>saimon</name>
    </author>
    <id>tag:webtypes.com,2006-03-31:1686</id>
    <published>2006-03-31T14:55:00Z</published>
    <updated>2007-05-16T14:38:08Z</updated>
    <category term="ruby" />
    <category term="web-services" />
    <link href="http://feeds.feedburner.com/~r/webtypes/~3/120269306/subversion-post-commit-hook-using-basecamp-api" rel="alternate" type="text/html" />
    <title>Subversion post commit hook using basecamp api</title>
<content type="html">
            &lt;p&gt;The &lt;a href="http://www.basecamphq.com/api/"&gt;&lt;strong&gt;Basecamp &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/strong&gt;&lt;/a&gt; was released last week.&lt;/p&gt;


	&lt;p&gt;We’ve created a subversion &lt;a href="http://www.webtypes.com/files/bc-post-commit.rb"&gt;post-commit hook&lt;/a&gt; that posts nicely formatted messages to a specific category for all of our clients basecamp projects. &lt;img title="svn post in Basecamp" src="/images/1.png" alt="svn post in Basecamp" /&gt;&lt;/p&gt;


	&lt;h4&gt;Continous communication&lt;/h4&gt;


	&lt;p&gt;This way our clients are continuously informed about the project status and the added benefit is that it forces us to write decent, coherent and descriptive log messages.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;


	&lt;h4&gt;Some conventions&lt;/h4&gt;


	&lt;h5&gt;svn/projects/client-name/project-name&lt;/h5&gt;


	&lt;p&gt;We have our svn repository setup so that the first level is a reference to the client’s company and the second level is the name of the client’s project (svn/projects/client-name/project-name).&lt;/p&gt;


	&lt;h5&gt;‘SCM Commits’ category exists in project&lt;/h5&gt;


	&lt;p&gt;&lt;a href="http://www.webtypes.com/files/bc-post-commit.rb"&gt;The script&lt;/a&gt; uses the path of the &lt;em&gt;changed&lt;/em&gt; files to select the correct basecamp project and then posts to the &lt;em&gt;‘SCM Commits’&lt;/em&gt; category if it exists for that project. It also only posts a message if the post was to the main trunk branch.&lt;/p&gt;


	&lt;h4&gt;Use itâ€¦&lt;/h4&gt;


	&lt;p&gt;&lt;strong&gt;Feel free to refactor, rewrite or otherwise modify  &lt;a href="http://www.webtypes.com/files/bc-post-commit.rb"&gt;the script&lt;/a&gt;. (Make sure to rename it to “post-commit” (no extension) before sticking it in your subversion repository’s ‘hooks’ directory.&lt;/strong&gt;&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;em&gt;Tip for textdrive users&lt;/em&gt;: Make sure the shebang line points to the actual path to the ruby executable and don’t use ”/usr/bin/env ruby” because when this is executed by the apache user the environment isn’t set.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;em&gt;2nd tip for textdrive users&lt;/em&gt;: Make sure all call to external system files have a full absolute path.&lt;/li&gt;
	&lt;/ul&gt;
          </content>  <feedburner:origLink>http://webtypes.com/2006/3/31/subversion-post-commit-hook-using-basecamp-api</feedburner:origLink></entry>
</feed>
