1 # encoding: utf-8
2
3 require 'i18n/gettext'
4 require 'i18n/gettext/po_parser'
5
6 # Experimental support for using Gettext po files to store translations.
7 #
8 # To use this you can simply include the module to the Simple backend - or
9 # whatever other backend you are using.
10 #
11 # I18n::Backend::Simple.send(:include, I18n::Backend::Gettext)
12 #
13 # Now you should be able to include your Gettext translation (*.po) files to
14 # the I18n.load_path so they're loaded to the backend and you can use them as
15 # usual:
16 #
17 # I18n.load_path += Dir["path/to/locales/*.po"]
18 #
19 # Following the Gettext convention this implementation expects that your
20 # translation files are named by their locales. E.g. the file en.po would
21 # contain the translations for the English locale.
22 module I18n
23 module Backend
24 module Gettext
25 class PoData < Hash
26 def set_comment(msgid_or_sym, comment)
27 # ignore
28 end
29 end
30
31 protected
32 def load_po(filename)
33 locale = ::File.basename(filename, '.po').to_sym
34 data = normalize(locale, parse(filename))
35 { locale => data }
36 end
37
38 def parse(filename)
39 GetText::PoParser.new.parse(::File.read(filename), PoData.new)
40 end
41
42 def normalize(locale, data)
43 data.inject({}) do |result, (key, value)|
44 unless key.nil? || key.empty?
45 key, value = normalize_pluralization(locale, key, value) if key.index("\000")
46
47 parts = key.split('|').reverse
48 normalized = parts.inject({}) do |normalized, part|
49 normalized = { part => normalized.empty? ? value : normalized }
50 end
51
52 # deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
53 merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
54 result.merge!(normalized, &merger)
55 end
56 result
57 end
58 end
59
60 def normalize_pluralization(locale, key, value)
61 # FIXME po_parser includes \000 chars that can not be turned into Symbols
62 key = key.gsub("\000", I18n::Gettext::PLURAL_SEPARATOR).split(I18n::Gettext::PLURAL_SEPARATOR).first
63
64 keys = I18n::Gettext.plural_keys(locale)
65 values = value.split("\000")
66 raise "invalid number of plurals: #{values.size}, keys: #{keys.inspect}" if values.size != keys.size
67
68 result = {}
69 values.each_with_index { |value, ix| result[keys[ix]] = value }
70 [key, result]
71 end
72
73 end
74 end
75 end