I stumbled across an interesting way to use I18n recently when modifying a FAQ section on a site. FAQs by their nature tend to be a constantly tweaked part of the site. Having to constantly change copy or add and remove questions can be time consuming. Fortunately the person in charge of the site, while not a developer, is technically savvy and can be trusted to modify YAML. I structured the en.yml file as follows for my own convenience but soon realized another use for it:

popup:  
  faq:
    question-1:
      question: Question 1 here
      answer: Answer 1 here
    question-2:
      question: Question 2 here
      answer: Answer 2 here
    … etc

It turns out that if you call the I18n translate method and don’t provide a leaf node like t(‘popup.faq’), you will get back a hash instead of a string. This hash will have the next level of YAML entries as keys with their associated tree as a hash of values and t(‘popup.faq’).count will tell me the number of FAQ questions in the YAML file. I realized I could include the following in the HAML file and never have to worry about updating the FAQ for copy and questions again:

- num_questions = t('popup.faq').count

#questions
  - num_questions.times do |i|
    = link_to t("popup.faq.question-#{i+1}.question"), "#question-#{i+1}"

- num_questions.times do |i|
  %p{:id => “questions-#{i}”}
    = t(“popup.faq.question-#{i+1}.question”)
  %p
    = t(“popup.faq.question-#{i+1}.answer”)
  %p
    = link_to 'Back to top', '#questions'

Now not only can the text of each question and each answer be updated, but the number of questions can be changed by adding or removing questions. As long as a simple logical pattern in the YML is followed, no additional code change is needed to update what can be a constantly tweaked part of the site due to user feedback.

Other things can be done to extend functionality. For example, if links, images, or other HTML elements were required in some answers, they could simply be a part of the en.yml string with the following change = t(“popup.faq.question-#{i+1}.answer”).html_safe. I’m always a bit nervous marking something as html_safe but if the only people modifying en.yml are developers or the person in charge of the site, I believe it should be okay here.

If you didn’t want to include your own HTML for breaking up an answer into multiple paragraphs which can be quite odd as the current code wraps the whole answer in <p> tags, you can simply write the YML as multiple paragraphs and split on a double newline like the following code shows:

- t(“popup.faq.question-#{i+1}.answer”).split(/\n\n/).each do |p|
  %p= p

—Aaron Rosenberg