Find missing translations in your Rails application

Journal entry
August 10, 2009

I am currently wrapping up a client-project where I am preparing a Rails application for internationalization. The application is currently in English and I am translating it to Danish as a proof of concept.

I am using the I18n::Simple backend and the resulting Danish locale file is now at 2100 lines. That’s a bit much for me to keep in my head at once, so I created a small Rake task that takes all locales in your Rails application and reports back all the keys that are missing from one or more locales. Works wonders for finding those typos or oversights that would otherwise result in ‘missing translation data’ messages.

Example output

$ rake i18n:missing_keys 
2 locales available: en and da
1474 unique keys found.
139 keys are missing from one or more locales:
'activerecord.attributes.category.description': Missing from en
'activerecord.attributes.person.last_name': Missing from en
'countries.Albania': Missing from en
'countries.Algeria': Missing from en

The Rake task

Just put the following in a .rake file in your lib/tasks directory and Rake should pick it up automagically:

namespace :i18n do

  desc "Find and list translation keys that do not exist in all locales"
  task :missing_keys => :environment do

    def collect_keys(scope, translations)
      full_keys = []
      translations.to_a.each do |key, translations|
        new_scope = scope.dup << key
        if translations.is_a?(Hash)
          full_keys += collect_keys(new_scope, translations)
        else
          full_keys << new_scope.join('.')
        end
      end
      return full_keys
    end

    # Make sure we've loaded the translations
    I18n.backend.send(:init_translations)
    puts "#{I18n.available_locales.size} #{I18n.available_locales.size == 1 ? 'locale' : 'locales'} available: #{I18n.available_locales.to_sentence}"

    # Get all keys from all locales
    all_keys = I18n.backend.send(:translations).collect do |check_locale, translations|
      collect_keys([], translations).sort
    end.flatten.uniq
    puts "#{all_keys.size} #{all_keys.size == 1 ? 'unique key' : 'unique keys'} found."

    missing_keys = {}
    all_keys.each do |key|

      I18n.available_locales.each do |locale|
        I18n.locale = locale
        begin
          result = I18n.translate(key, :raise => true)
        rescue I18n::MissingInterpolationArgument
          # noop
        rescue I18n::MissingTranslationData
          if missing_keys[key]
            missing_keys[key] << locale
          else
            missing_keys[key] = [locale]
          end
        end
      end
    end

    puts "#{missing_keys.size} #{missing_keys.size == 1 ? 'key is missing' : 'keys are missing'} from one or more locales:"
    missing_keys.keys.sort.each do |key|
      puts "'#{key}': Missing from #{missing_keys[key].join(', ')}"
    end

  end
end

Update: This is now available on Github at http://github.com/koppen/i18n_missing_keys.

Categories
Selling out
Did you know?
Jakob is an independent web application developer who builds awesome stuff for the web. You can hire him to build awesome stuff for you.

Comments and Trackbacks

Morgan Roderick August 10, 2009

Very interesting.

There is also a very nice and simple plugin by Peter Marklund to assist you in making translations easier.

http://github.com/newsdesk/translate/tree/master

Jakob S August 11, 2009

I didn't know about that plugin, looks interesting. Looks like the above rake task supplements the tasks from the Translate plugin quite nicely.

Hans October 7, 2009

I am using your code to get all locales. However, it seems that som keys are missing. The yml file looks like (part of it)
messages:
inclusion: "is not included in the list"
exclusion: "is reserved"
models:
user:
email: "should look like an email addres"
login: "use only letters, numbers, and .-_@ "
name: "avoid non-printing characters"
label_messages:
validates_acceptance_of: 'Must be accepted'
validates_confirmation_of: 'Must be confirmed'
It doe not find the keys sv activerecord errors messages models user email
and not any of the keys for label messages
I have tried with the models part deleted but the result is the same
Any help would be appriciated

Jakob S October 19, 2009

Hans, I can't seem to replicate that issue.

I have pushed the above Rake task to Github at http://github.com/koppen/i18n_missing_keys and added some basic tests. I would definitely appreciate a patch or at least a failing test case in order to fix the issue.

Commenting on this entry has been closed.