Butter Office Inspiration

Having been talking about how we could maximize our office's space recently, here is a site that I found inspiring:

http://wherewedesign.com

And some good examples that I picked:

Raw Design Studio


i love the mega inspiration board on the wall and they way the tables are arranged
and perhaps some typographic signage on the wall?


SelgasCano

Will this place be too cool to work at?  I feel like I am on vacation!

Tags: inspiration, design, butter

Internationalization in MODx Revolution

As our company is based in Hong Kong, our clients often require a multi-lingual site. Luckily for us, the MODx team have given us the perfect tools for internationalization, or i18n, in MODx Revolution. In this tutorial I'll show you how we handle i18n, making use of contexts and lexicons. There is two parts to achieving this. First, we create a context for each language, and set up a plugin to handle the request and load the appropriate context. Then, we'll use lexicons to handle any text in our templates, chunks and snippets.

Contexts

Lets start by creating contexts for each language. This will separate your content by language in the resource tree, keeping it nicely organised and allowing us to select content from the appropriate language simply by switching the context. To create a context, select Contexts from the System menu in the MODx manager and click create new. Enter a context key, and optionally a description and save.

The Contexts Menu

Creating a Context

The Plugin

The next step is to give each context a setting containing the Language key (or cultureKey). To add a context settings, just click on the context in the resource tree, and select the Context Settings tab. Now you can enter your content for each language in its respective context.

Context Settings

Next, we need to create a plugin to load the correct context for the selected language. To create a plugin, select the elements tab on the site tree and click the new plugin button.

Creating a Plugin

Now we give our plugin a name (we usually call it gateway, you can use whatever makes sense to you) an optional description and category, and finally the code. For those of you less experienced in writing PHP, don't be daunted, it's a simple switch statement. In our implementation, each language will require its own subdomain (eg en.example.com) except for the default language, as this will be loaded for the primary domain (eg www.example.com). We pull the domain from the http_host option and switch the context accordingly. In this example we're only using two contexts/languages, with the default being Chinese. To add an extra language you just need to add a case (and a subdomain and context to go with it).`

		//make sure our plugin does not run on the mgr context (the manager)
			if($modx->context->get('key') != "mgr"){
				//grab the current domain from the http_host option
				switch ($modx->getOption('http_host')) {
					case 'en.example.com':
						//switch the context
						$modx->switchContext('en');
						//set the cultureKey
						$modx->setOption('cultureKey', 'en');
						break;
					default:
						// Set the default language/context here
						$modx->switchContext('chinese');
						$modx->setOption('cultureKey', 'zh');
						break;
				}
			}
	

Finally, we need to set the plugin to run on the onHandleRequest event by selecting the System Events tab and checking the box for OnHandleRequest, don't forget to save.

Selecting the onHandleRequest event

Lexicons

Now lets move on to Lexicons, the core of i18n in MODx. A lexicon is simply a collection of language entries. A lexicon entry is any piece of text that will appear in your templates, chunks or snippets. In MODx the entries are separated into files by namespace, language and topic. We like to create a namespace for our lexicon entires to separate anything that we create from the core lexicon. To create a namespace, select Namespaces from the System menu and hit the Create New button. Enter a name for your namespace (we generally use the site name here) and a path to the namespace. For the path we like to use the core/components directory which is also where all the namespaces for 3PCs live but you can place it anywhere you see fit. Remember, this is a full path to the directory, so it makes sense to use the {base_path} or {core_path} options as appropriate (eg. {core_path}components/directory_of_namespace). Namespaces Menu Creating a Namespace

Before we create the entries we need to set up the directory structure. So in your filesystem, navigate to the directory of your namespace (create it if you haven't already) and create a directory called lexicon. Inside the lexicon directory we create another directory for each language. In our case one named 'en' and one named 'zh'. Inside that folder we create the lexicon files. The convention for naming these is topic.inc.php so if your topic is cart the file will be cart.inc.php. If you would like to group these further, you could create a directory (eg. store) and have your php file in there. To specify this in your lexicon call (which we'll cover a little further down) you would use directory.filename as the topic (eg. store.cart). Directory Structure

Storing an Entry

Now to create an entry. Inside your topic.inc.php file, we need to add to the $_lang array. The convention for this is $_lang[key] = value. The value can contain HTML, snippet calls or placeholders (passed in the lexicon call).

A lexicon entry where the key is store.your_cart and the value is 'Your cart':

		$_lang['store.your_cart'] = "Your cart";
	

A lexicon entry where the key is store.more_info and the value contains some text with link to more info:

		$_lang['store.more_info'] = "Click here for more info.";
	

A lexicon entry where the key is store.cart_count and the value uses a snippet call to fetch the number of items, followed by the text 'items':

		$_lang['store.cart_count'] = "[[!ShoppingCart? &action=`getCount`]] items.";
	

A lexicon entry where the key is store.hello and the value uses a placeholder containing the name:

	$_lang['store.hello'] = "Hello [[+name]]!";
	
Retrieving an Entry

Lexicon entries can be called in with a MODx tag, or with PHP code.

Here's' how to call a lexicon in template/chunk. This will call the entry with the key store.name from the file namespace_name/cart.inc.php It will use the current cultureKey by default, but if you need to specify a language you could do so by passing the 'language' parameter (eg. &language=`en`).

		[[%store.hello? &topic=`cart` &namespace=`namespace_name`]]
	

In this lexicon call we're setting a placeholder called name which will be available in the entry:

		[[%store.hello? &topic=`cart` &namespace=`namespace_name` &name='Jude']]
	

There's a little more to calling lexicon entries with PHP. First we have to make sure the lexicon service is loaded:

		$modx->getService('lexicon','modLexicon');
	

Now we select a topic. The syntax is namespace:topic so the below would load the topic 'default' from the store namespace:

		$modx->lexicon->load('store:default');
	

Finally, we can use the lexicon method to call an entry. Again this will default to the current cultureKey, but can be specified in the load method by prepending the language (eg. $modx->lexicon->load('en:store:default')). This would get an entry with the key 'store.hello':

		$modx->lexicon('store.hello');
	

This will get an entry with the key 'store.hello' and pass the placeholder 'name' with the value 'Jude':

		$modx->lexicon('store.hello', array('name' => 'Jude'));
	
Tags: MODx, MODx Revolution, MultiLingual

Friday Night Pigout Session

I should feel guilty about showing this massive pigout Jude and I had a couple of weeks back, yet somehow I don't...

Dinner for 10, eaten by 5. Hong Kong makes you fat.

Tags: ThisIsWhyWe'reFat

Douglas Young @ StartupSaturday

Douglas Young inspired everyone in the room with his version of how G.O.D has gotten to where it is now.

Tags: SUS2010, Hong Kong

A custom TV in Evo

A few months back I created a custom TV renderer for Evo that I thought was super cool, until I saw some of the things extJs will allow you to do in Revo and then forgot about it...

Still, I came back to a project I used it on and where I used the CMS as an editor (rather than developer) and really appreciated this TV so I thought I would show it and see if anyone had any ideas how this might be best employed in Revo.

It works off a very similar structure to Jeff Whitfields plugin for EvoGallery coupled with ManagerManager where jQuery is being used to improve/enhance an existing TV form field.

My requirement in this case was to have a list of resources on the homepage be displayed in a specific order, whereby the admin is supposed to be able to choose which resources are displayed as well as in which order to display them. In context, this site is an F&B portal that frequently reviews and promotes restaurants, hence the need to 'promote' certain resources on to the homepage.

I have seen a couple of tutorials now on how to promote resource to the homepage using TVs (on the actual resource itself) and applying a TV filter with Ditto. That can work, but in this case I want to order the resources too, so a simple TV on a resource isn't going to work. Plus, drag and drop reordering would be pretty neat, clients have come to expect that after all.

Long story short - here's the TV in action, I have to give most credit to the jQuery plugin developer for this one, I've simply applied his brilliant plugin to any multiple select field in the resource edit panel:

How the list box renders.

So behind all of that is a normal multiple select TV field, but with the enhancements that the jQuery plugin gives you, you're now able to actually sort the list as well as see all of the items you've selected from the list. The quick search is pretty cool too - especially when your list starts growing past the 100 mark. It's all done client side so this is only scalable to a certain extent.

Now to actually using the TV itself, I've created a custom snippet that reads the TV value and processes the ID's of the selected resources one by one *in order*. Code looks something like this, but don't hold me to it:

//assume tvValue is passed in a snippet call
$tvValue = (isset($tvValue)) ? $tvValue : '';
$resources = explode(",", $tvValue);
foreach($resources as $resourceId){
//load your resource fields here and apply templating here

Next up - applying this to revo using MODext!

- JB

Tags: MODx, MODx Evolution