# encoding: utf-8 require 'i18n/gettext' require 'i18n/gettext/po_parser' # Experimental support for using Gettext po files to store translations. # # To use this you can simply include the module to the Simple backend - or # whatever other backend you are using. # # I18n::Backend::Simple.send(:include, I18n::Backend::Gettext) # # Now you should be able to include your Gettext translation (*.po) files to # the I18n.load_path so they're loaded to the backend and you can use them as # usual: # # I18n.load_path += Dir["path/to/locales/*.po"] # # Following the Gettext convention this implementation expects that your # translation files are named by their locales. E.g. the file en.po would # contain the translations for the English locale. module I18n module Backend module Gettext class PoData < Hash def set_comment(msgid_or_sym, comment) # ignore end end protected def load_po(filename) locale = ::File.basename(filename, '.po').to_sym data = normalize(locale, parse(filename)) { locale => data } end def parse(filename) GetText::PoParser.new.parse(::File.read(filename), PoData.new) end def normalize(locale, data) data.inject({}) do |result, (key, value)| unless key.nil? || key.empty? key, value = normalize_pluralization(locale, key, value) if key.index("\000") parts = key.split('|').reverse normalized = parts.inject({}) do |normalized, part| normalized = { part => normalized.empty? ? value : normalized } end # deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809 merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 } result.merge!(normalized, &merger) end result end end def normalize_pluralization(locale, key, value) # FIXME po_parser includes \000 chars that can not be turned into Symbols key = key.gsub("\000", I18n::Gettext::PLURAL_SEPARATOR).split(I18n::Gettext::PLURAL_SEPARATOR).first keys = I18n::Gettext.plural_keys(locale) values = value.split("\000") raise "invalid number of plurals: #{values.size}, keys: #{keys.inspect}" if values.size != keys.size result = {} values.each_with_index { |value, ix| result[keys[ix]] = value } [key, result] end end end end