Archive for the ‘Web Applications’ Category

Merging Rails’ i18n files

Thursday, January 8th, 2009

Lately I’ve been in a hassle to translate our application Quassum into English. My collegues continously modify the german i18n file for Rails, then the old structure of the other language files are left unmodified. Doing this by hand is close to impossible.

So what I came up with was a rake task that merges a give structure (YAML source file) into an existing target structure while overwriting every key that changed and adding new keys. Old keys and values are left as they are.

I didn’t find anything on the internet doing this task, so I hope this task will save you the time I spent last saturday. Good luck!

$KCODE = 'UTF8'
require 'ya2yaml'

namespace :quassum do
  desc "Copy all missing lang identifiers from [src].yml to [dest].yml"
  task :fill_lang do

    if ENV['src'].blank? or ENV['dest'].blank?
      puts "Give all parameters: src and dest. " +
        "E.g.: rake quassum:fill_lang src='de' dest='en'"
      exit
    end
    src_path = File.join(RAILS_ROOT,'config','locales', "#{ENV['src']}.yml")
    dest_path = File.join(RAILS_ROOT,'config','locales', "#{ENV['dest']}.yml")

    unless File.readable?(src_path)
      puts "File #{src_path} not readable!"
      exit
    end

    unless File.exist?(dest_path)
      puts "File #{dest_path} does not exist. Creating it..."
      File.new(dest_path, "w")
    end

    # We assume that the src file is correct...
    yaml_src = YAML::load_file(src_path)
    struct_src = yaml_src[ENV['src']]

    # ...but the src not necessarily. So, in case, we create a new lang file:
    @yaml_dest = YAML::load_file(dest_path)
    @yaml_dest ||= Hash.new
    @struct_dest = @yaml_dest[ENV['dest']]
    @struct_dest ||= Hash.new

    # merge all unknown changes to the dest struct:
    merge_recursively struct_src

    @yaml_dest[ENV['dest']] = @struct_dest
    File.open(dest_path, "w") do |file|
      file.puts @yaml_dest.ya2yaml
    end

    puts File.new(dest_path).read
    puts "Everything done."
  end

  #
  # SOME HELPER FUNCTIONS
  #
  def merge_recursively(pairs, parents = [])
    pairs.each_pair do |k,v|
      # copy the parents path and add the current element key:
      current_path = Array.new(parents) << k
      if v.is_a?(Hash)
        merge_recursively(v, current_path)
      else
        ensure_yaml_contains(@struct_dest, current_path, v.to_s)
      end
    end
  end

  def ensure_yaml_contains(element, path, val)
    #puts "    ensure_yaml_contains(#{element}, #{path}, #{val})"

    if path.length == 1
      if element[path.first].is_a?(Hash) and not val.blank?
        puts "Hash found instead of key. In favor of '#{val}' '#{element.to_s}' will be deleted!"
        element[path.first] = val
      end
      if element[path.first].nil?
        puts "Missing key '#{path.first}'! Pre-filled for editing with: '#{val}'. element was #{element.class}"
        element[path.first] = val + " [[TODO]]  "
      end
      # if none of these replaced anything - we're fine, the key exists!
      # :-)
    elsif path.length > 1
      # walk down if possible:
      if element[path.first].is_a?(Hash) and element.has_key?(path.first)
        ensure_yaml_contains(element[path.first], path[1..-1], val)
      else
        # We don't have a hash in the dest file, so we create the hash
        # and fill in all subsequent children:
        element[path.first] = Hash.new
        ensure_yaml_contains(element[path.first], path[1..-1], val)
      end
    else
      puts "REPLACING FAILED"
      # should stop here
    end
  end

end

Benefits of working in parallel

Sunday, October 26th, 2008

There a topic that’s I’ve been observing quite a while and that’s finally worth considering in writing. Although I think that the projecting habits of every person is unique, I try to find some generic points.

Why not to

How many successful startups do we know that still have founders working as employees in other companies, do excessive consulting jobs aside or even studying at universities? Nearly none? There may be reasons:

Let me mention some things not to do. The number one thing not to do is other things. (Paul Graham)

Another reason can be if you want to get rid of a project really quickly. Spending all your time on it can accelerate your process. But there’s still the distance issue, see below:

Benefits

Working on one thing makes your mind get stuck on this topic. A mathmatician friend of mine once pointed out that’s nearly impossible to rework a math class in some days of vacation because there’ll be a lack of distance. That’s why pair programming is so popular in these years. While one developer programs the other is able to see the big picture of the task with a lot more distance.

Concerning everyday life, people have hardly just one thing that’s bugging them. Trying to go for the one solution often ends up in forgetting about other factors. Being able to work in parallel will not only take them a step further to their goals it also makes excuses obsolete (which is, in this case, probably the main benefit).

Moreover, it’s possible to plan for that parallelization. In fact, according to a german study most of their students are able to study and have a part-time job. I consider this as a much better practice than working in advance, saving money and study eventually. Anyway, most of them will face the distance problem and stick to their full-time jobs.

Distraction and scope

We know that parallelizing work is hard. It slows us down, we don’t have to argue on this one. But what about parallelizing projects? Projects often have the nature of having gaps in between actions. That is, for example waiting for the next lecture when working on the diploma/master. Working on other projects then requires a fair amount of scope. A factor that says, how much concentration you have for a specific task. There are methods to help not getting distracted by other things.

Matt Wood states another important point:

But the trick isn’t cutting out that distraction completely, it’s acknowledging it, admitting its power over you, then drawing lines and finding its proper role in your life.

Which is probably the greatest benefit we’ll get out of working in parallel. While the uni gives me inspiration, contacts and much theory, our startup shows me what we’re learning for.

The Importance of Avatars

Wednesday, August 27th, 2008

The offline experience

There is a feature of Mac OSX that’s fairly underrated: the usage of avatars throughout the system. The benefits of maintaining those small images are become apparent subtly:

That’s just a small area of my two-screen setup but probably the part I work with the most. I configured Adium that it displays rather my own avatars than the messenger’s ones. It got much easier to figure out who’s online without even glancing on the names.

Avatars online

Let’s take a look at the web… (at my favorite social app)

Okay, apparently the benefit of recognizing contacts without reading the actual name. People change their profile as often as it causes the application to list their profiles higher than others.

What’s the deal then?

Some pages extensively use avatars (taken from mashable)

Do you see the benefit? It certainly isn’t the one I stated. When picking avatars randomly users just can’t match them with their contacts, especially if their “friends” change them hourly.

But: many avatars (and icons) can improve the impressions a basically dark page leaves. Or just look at photo pages like flickR; nothing but user generated graphical elements.

To a much greater degree, the merit is rather a psychological one: To the user the site shown above makes the impression of vividness, showing the presence of a boatload of users, just waiting to get in touch. If there’s the opportunity to get your user’s (or friends’) avatars, use them to create a better experience on your desktop or even your social network.

Accessing Community Profiles

Thursday, June 26th, 2008

When surfing, or - precisely - retrieving content from a webserver, we use URIs / URLs. The resource we want to get is located by a protocol, a hostname, sometimes a port and a path.

But as we moved from static content to dynamic pages where you can hardly distinguish the resources, we needed parameters:

http://zazazu.de/zazazu.php?sde=100&per=338

Now what does this tell us aside from the URL? Apart from the fact that someone used PHP - not much but noise. Come on, we can do better. Here’s the why:

  • If you offer your users a unique profile, these adresses are shown around. Make it most comfortable for them to do so.
  • The does better understand direction of the content. xyz.com/games/pacman is much more exact than xyz.com/games.do?gid=4711.
  • It simply looks better.

There are some simple, some profound principles in declaring your page’s URLs. Basically there’s a solution for every platform:

Ruby on Rails’ routes, django’s equivalent, Cake’s router… If nothing helps, a webserver can rewrite the URLs on its own, e.g. with mod_rewrite. So there are plenty possibilities. And then, the concept of your web application has to support the resolution of names instead of ids or other parameters.

For example, a website can link to their profiles with /profiles/id/1339 or it can dispatch them with names, like linkedIn.com (using Java, Spring and JSP):

And, unless there are reasons to “disclose” the world from mapping URL to profile names you should avoid this kind of profile URL: http://www.studivz.net/Profile/e094a153d4af2fc6 and let the users spread their profile URLs with as much eagerness business cards. Compared to the whole code in your webapp it isn’t a great change but (apart from looking more professional) your website will get a happier usage.