lastobelus-merb_global 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/activerecord_generators/translations_migration/USAGE +4 -0
  2. data/activerecord_generators/translations_migration/templates/translations_migration.erb +30 -0
  3. data/activerecord_generators/translations_migration/translations_migration_generator.rb +31 -0
  4. data/examples/active_record_example/README.txt +9 -0
  5. data/examples/active_record_example/application.rb +5 -0
  6. data/examples/active_record_example/config/database.yml +9 -0
  7. data/examples/active_record_example/config/framework.rb +5 -0
  8. data/examples/active_record_example/config/init.rb +24 -0
  9. data/examples/active_record_example/config/plugins.yml +3 -0
  10. data/examples/data_mapper_example/README.txt +9 -0
  11. data/examples/data_mapper_example/application.rb +5 -0
  12. data/examples/data_mapper_example/config/database.yml +9 -0
  13. data/examples/data_mapper_example/config/framework.rb +5 -0
  14. data/examples/data_mapper_example/config/init.rb +24 -0
  15. data/examples/data_mapper_example/config/plugins.yml +3 -0
  16. data/examples/database.sql +28 -0
  17. data/examples/gettext_example/README.txt +9 -0
  18. data/examples/gettext_example/application.rb +8 -0
  19. data/examples/gettext_example/config/framework.rb +5 -0
  20. data/examples/gettext_example/config/init.rb +24 -0
  21. data/examples/gettext_example/config/plugins.yml +4 -0
  22. data/examples/gettext_example/locale/merbapp.pot +21 -0
  23. data/examples/gettext_example/locale/pl/LC_MESSAGES/merbapp.mo +0 -0
  24. data/examples/gettext_example/locale/pl.po +23 -0
  25. data/examples/mock_example/README.txt +9 -0
  26. data/examples/mock_example/application.rb +5 -0
  27. data/examples/mock_example/config/framework.rb +5 -0
  28. data/examples/mock_example/config/init.rb +23 -0
  29. data/examples/mock_example/config/plugins.yml +3 -0
  30. data/examples/sequel_example/README.txt +9 -0
  31. data/examples/sequel_example/application.rb +5 -0
  32. data/examples/sequel_example/config/database.yml +9 -0
  33. data/examples/sequel_example/config/framework.rb +5 -0
  34. data/examples/sequel_example/config/init.rb +24 -0
  35. data/examples/sequel_example/config/plugins.yml +3 -0
  36. data/examples/yaml_example/README.txt +9 -0
  37. data/examples/yaml_example/application.rb +5 -0
  38. data/examples/yaml_example/config/framework.rb +5 -0
  39. data/examples/yaml_example/config/init.rb +24 -0
  40. data/examples/yaml_example/config/plugins.yml +4 -0
  41. data/examples/yaml_example/locale/en.yaml +2 -0
  42. data/examples/yaml_example/locale/pl.yaml +2 -0
  43. data/lib/merb_global/base.rb +105 -0
  44. data/lib/merb_global/config.rb +36 -0
  45. data/lib/merb_global/controller.rb +38 -0
  46. data/lib/merb_global/date_providers/fork.rb +35 -0
  47. data/lib/merb_global/date_providers.rb +47 -0
  48. data/lib/merb_global/locale.rb +139 -0
  49. data/lib/merb_global/merbrake.rb +37 -0
  50. data/lib/merb_global/message_providers/active_record.rb +113 -0
  51. data/lib/merb_global/message_providers/data_mapper.rb +113 -0
  52. data/lib/merb_global/message_providers/gettext.rb +123 -0
  53. data/lib/merb_global/message_providers/gettext.treetop +60 -0
  54. data/lib/merb_global/message_providers/mock.rb +17 -0
  55. data/lib/merb_global/message_providers/sequel.rb +99 -0
  56. data/lib/merb_global/message_providers/yaml.rb +92 -0
  57. data/lib/merb_global/message_providers.rb +146 -0
  58. data/lib/merb_global/numeric_providers/fork.rb +35 -0
  59. data/lib/merb_global/numeric_providers/java.rb +15 -0
  60. data/lib/merb_global/numeric_providers.rb +48 -0
  61. data/lib/merb_global/plural.rb +20 -0
  62. data/lib/merb_global/plural.treetop +267 -0
  63. data/lib/merb_global/providers.rb +40 -0
  64. data/lib/merb_global.rb +8 -0
  65. data/sequel_generators/translations_migration/USAGE +4 -0
  66. data/sequel_generators/translations_migration/templates/translations_migration.erb +28 -0
  67. data/sequel_generators/translations_migration/translations_migration_generator.rb +32 -0
  68. metadata +92 -1
@@ -0,0 +1,38 @@
1
+ require 'merb_global/base'
2
+
3
+ module Merb
4
+ class Controller
5
+ include Merb::Global
6
+
7
+ class_inheritable_accessor :_mg_locale
8
+
9
+ before do
10
+ # Set up the language
11
+ accept_language = self.request.env['HTTP_ACCEPT_LANGUAGE']
12
+ Merb::Global::Locale.current =
13
+ Merb::Global::Locale.new(params[:locale]) ||
14
+ (self._mg_locale &&
15
+ Merb::Global::Locale.new(self.instance_eval(&self._mg_locale))) ||
16
+ Merb::Global::Locale.from_accept_language(accept_language) ||
17
+ Merb::Global::Locale.new('en')
18
+ end
19
+
20
+ # Sets the language of block.
21
+ #
22
+ # The block should return language or nil if other method should be used
23
+ # to determine the language
24
+ #
25
+ # Please note that this method is deprecated and the preferred method is
26
+ # locale.
27
+ def self.language(&block)
28
+ self._mg_locale = block
29
+ end
30
+ # Sets the language of block.
31
+ #
32
+ # The block should return language or nil if other method should be used
33
+ # to determine the language
34
+ def self.locale(&block)
35
+ self._mg_locale = block
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ require 'inline'
2
+
3
+ module Merb
4
+ module Global
5
+ module DateProviders
6
+ class Fork
7
+ include Merb::Global::DateProviders::Base
8
+
9
+ def localize(lang, date, format)
10
+ pipe_rd, pipe_wr = IO.pipe
11
+ pid = fork do
12
+ pipe_rd.close
13
+ setlocale(lang.to_s)
14
+ pipe_wr.write(date.strftime(format))
15
+ pipe_wr.flush
16
+ end
17
+ pipe_wr.close
18
+ Process.wait(pid)
19
+ pipe_rd.read
20
+ end
21
+
22
+ inline do |builder|
23
+ builder.include '<locale.h>'
24
+ builder.c <<C
25
+ void set_locale(const char *locale)
26
+ {
27
+ setlocale(LC_ALL, locale);
28
+ }
29
+ C
30
+ end
31
+ private :set_locale
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,47 @@
1
+ require 'merb_global/providers'
2
+
3
+ module Merb
4
+ module Global
5
+ module DateProviders
6
+ include Providers
7
+ # call-seq:
8
+ # provider => provider
9
+ #
10
+ # Returns the provider of required type
11
+ #
12
+ # ==== Returns
13
+ # provider<Provider>:: Returns provider
14
+ def self.provider
15
+ @@provider ||= self[Merb::Global.config(:date_provider, 'fork')]
16
+ end
17
+ # Merb-global is able to handle localization in different ways.
18
+ # Providers are the interface.
19
+ #
20
+ # Please note that it is not required to include this module - despite it
21
+ # is recomended both as a documentation part and the more customized
22
+ # error messages.
23
+ module Base
24
+ ##
25
+ #
26
+ # Localize date using format as in strftime
27
+ def localize(lang, date, format)
28
+ raise NoMethodError.new('method localize has not been implemented')
29
+ end
30
+ end
31
+ end
32
+ # Perform the registration
33
+ #
34
+ # ==== Parameters
35
+ # name<~to_sym>:: Name under which it is registered
36
+ def self.DateProvider(provider_name)
37
+ Module.new do
38
+ @@rb_date_provider_name = provider_name
39
+ include Merb::Global::DateProviders::Base
40
+
41
+ def self.included(klass)
42
+ Merb::Global::DateProviders.register @@rb_date_provider_name, klass
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,139 @@
1
+ require 'merb_global/base'
2
+ require 'thread'
3
+ require 'weakref'
4
+
5
+ class Thread
6
+ attr_accessor :mg_locale
7
+ end
8
+
9
+ module Merb
10
+ module Global
11
+ class Locale
12
+ attr_reader :language, :country
13
+
14
+ def initialize(name)
15
+ # TODO: Understand RFC 1766 fully
16
+ @language, @country = name.split('-')
17
+ end
18
+
19
+ def any?
20
+ language == '*' && country.nil?
21
+ end
22
+
23
+ def base_locale
24
+ if not @country.nil?
25
+ Locale.new(@language)
26
+ else
27
+ nil
28
+ end
29
+ end
30
+
31
+ def to_s
32
+ if country.nil?
33
+ "#{@language.downcase}"
34
+ else
35
+ "#{@language.downcase}_#{@country.upcase}"
36
+ end
37
+ end
38
+
39
+ if defined? RUBY_ENGINE and RUBY_ENGINE == "jruby"
40
+ def java_locale
41
+ require 'java'
42
+ @java_locale ||=
43
+ if @country.nil?
44
+ java.util.Locale.new(@language.downcase)
45
+ else
46
+ java.util.Locale.new(@language.downcase, @country.upcase)
47
+ end
48
+ end
49
+ else
50
+ def java_locale
51
+ nil
52
+ end
53
+ end
54
+
55
+ def self.parse(header)
56
+ header = header.split(',')
57
+ header.collect! {|lang| lang.delete ' ' "\n" "\r" "\t"}
58
+ header.reject! {|lang| lang.empty?}
59
+ header.collect! {|lang| lang.split ';q='}
60
+ header.collect! do |lang|
61
+ if lang.size == 1
62
+ [lang[0], 1.0]
63
+ else
64
+ [lang[0], lang[1].to_f]
65
+ end
66
+ end
67
+ header.sort! {|lang_a, lang_b| lang_b[1] <=> lang_a[1]} # sorting by decreasing quality
68
+ header.collect! {|lang| Locale.new(lang[0])}
69
+ end
70
+
71
+ def self.from_accept_language(accept_language)
72
+ unless accept_language.nil?
73
+ accept_language = Merb::Global::Locale.parse(accept_language)
74
+ accept_language.each_with_index do |lang, i|
75
+ if lang.any?
76
+ # In this case we need to choose a locale that is not in accept_language[i+1..-1]
77
+ return Merb::Global::Locale.choose(accept_language[i+1..-1])
78
+ elsif Merb::Global::Locale.support? lang
79
+ return lang
80
+ end
81
+ lang = lang.base_locale
82
+ return lang if lang && Merb::Global::Locale.support?(lang)
83
+ end
84
+ end
85
+ end
86
+
87
+ def self.current
88
+ Thread.current.mg_locale
89
+ end
90
+
91
+ def self.current=(new_locale)
92
+ Thread.current.mg_locale = new_locale
93
+ end
94
+
95
+ class << self
96
+ alias_method :pure_new, :new
97
+ private :pure_new
98
+ end
99
+
100
+ @@current = {}
101
+ @@current_mutex = Mutex.new
102
+ # Create new locale object and returns it.
103
+ #
104
+ # Please note that this method is cached.
105
+ def self.new(name)
106
+ return nil if name.nil?
107
+ return name if name.is_a? Locale
108
+ @@current_mutex.synchronize do
109
+ begin
110
+ n = @@current[name]
111
+ if n.nil?
112
+ n = pure_new(name)
113
+ @@current[name] = WeakRef.new(n)
114
+ else
115
+ n = n.__getobj__
116
+ end
117
+ n
118
+ rescue WeakRef::RefError
119
+ n = pure_new(name)
120
+ @@current[name] = WeakRef.new(n)
121
+ n
122
+ end
123
+ end
124
+ end
125
+
126
+ def self.support?(locale)
127
+ supported_locales.include? locale.to_s
128
+ end
129
+
130
+ def self.supported_locales
131
+ Merb::Global::config('locales', ['en'])
132
+ end
133
+
134
+ def self.choose(except)
135
+ new((supported_locales - except.map{|e| e.to_s}).first)
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,37 @@
1
+ require 'fileutils'
2
+
3
+ namespace :merb_global do
4
+
5
+ task :merb_start do
6
+ Merb.start_environment :adapter => 'runner',
7
+ :environment => ENV['MERB_ENV'] || 'development'
8
+ end
9
+
10
+ desc 'Create migration'
11
+ task :migration => :merb_start do
12
+ Merb::Global::MessageProviders.provider.create!
13
+ end
14
+
15
+ desc 'Transfer the translations from one provider to another'
16
+ task :transfer => :merb_start do
17
+ from = Merb::Global.config 'source', 'gettext'
18
+ into = Merb::Global.config 'provider', 'gettext'
19
+ if from == 'gettext' and into == 'gettext'
20
+ Dir[Merb::Global::MessageProviders.localedir + '/*.po'].each do |file|
21
+ lang = File.basename file, '.po'
22
+ lang_dir = File.join(Merb::Global::MessageProviders.localedir,
23
+ lang, 'LC_MESSAGES')
24
+ FileUtils.mkdir_p lang_dir
25
+ domain = Merb::Global.config([:gettext, :domain], 'merbapp')
26
+ `msgfmt #{file} -o #{lang_dir}/#{domain}.mo`
27
+ end
28
+ elsif from == into
29
+ Merb.logger.error 'Tried transfer from and into the same provider'
30
+ else
31
+ from = Merb::Global::MessageProviders[from]
32
+ into = Merb::Global::MessageProviders[into]
33
+ Merb::Global::Provider.transfer from, into
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,113 @@
1
+ require 'activerecord'
2
+ # As far as I understand, we need it to have composite keys.
3
+ # However it may be better idea to drop them.
4
+ # So far I implement it in this way - then we will see
5
+ require 'composite_primary_keys' # As far as I understand we need
6
+ require 'merb_global/plural'
7
+
8
+ module Merb
9
+ module Global
10
+ module MessageProviders
11
+ class ActiveRecord #:nodoc: all
12
+ include Merb::Global::MessageProviders::Base
13
+ include Merb::Global::MessageProviders::Base::Importer
14
+ include Merb::Global::MessageProviders::Base::Exporter
15
+
16
+ def localize(singular, plural, n, locale)
17
+ language = Language.find :first,
18
+ :conditions => {:name => locale.to_s}
19
+ unless language.nil?
20
+ unless plural.nil?
21
+ pn = Plural.which_form n, language.plural
22
+ translation = Translation.find [language.id, singular, pn]
23
+ else
24
+ # Bug of composite_primary_keys?
25
+ conditions = {
26
+ :language_id => language.id,
27
+ :msgid => singular,
28
+ :msgstr_index => nil
29
+ }
30
+ translation = Translation.find(:first, conditions)
31
+ end
32
+ return translation.msgstr
33
+ end rescue nil
34
+ return n > 1 ? plural : singular # Fallback if not in database
35
+ end
36
+
37
+ def create!
38
+ migration_exists = Dir[File.join(Merb.root, 'schema',
39
+ 'migrations', '*.rb')].detect do |f|
40
+ f =~ /translations\.rb/
41
+ end
42
+ if migration_exists
43
+ puts "\nThe Translation Migration File already exists\n\n"
44
+ else
45
+ sh %{merb-gen translations_migration}
46
+ end
47
+ end
48
+
49
+ def import
50
+ data = {}
51
+ Language.transaction do
52
+ Translation.transaction do
53
+ Language.find(:all).each do |lang|
54
+ data[lang.name] = lang_hash = {
55
+ :plural => lang.plural,
56
+ :nplural => lang.nplural
57
+ }
58
+ lang.translations.each do |translation|
59
+ lang_hash[translation.msgid] ||= {
60
+ :plural => translation.msgid_plural
61
+ }
62
+ lang_hash[translation.msgid][translation.msgstr_index] =
63
+ translation.msgstr
64
+ end
65
+ end
66
+ end
67
+ end
68
+ data
69
+ end
70
+
71
+ def export(data)
72
+ Language.transaction do
73
+ Translation.transaction do
74
+ Translation.delete_all
75
+ Language.delete_all
76
+ data.each do |lang_name, lang|
77
+ lang_id = Language.create!(:name => lang_name,
78
+ :plural => lang[:plural],
79
+ :nplural => lang[:nplural]).id
80
+ lang.each do |msgid, msgstrs|
81
+ if msgid.is_a? String
82
+ plural = msgstrs[:plural]
83
+ msgstrs.each do |index, msgstr|
84
+ if index.nil? or index.is_a? Fixnum
85
+ Translation.create! :language_id => lang_id,
86
+ :msgid => msgid,
87
+ :msgid_plural => plural,
88
+ :msgstr => msgstr,
89
+ :msgstr_index => index
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ class Language < ::ActiveRecord::Base
100
+ set_table_name :merb_global_languages
101
+ has_many :translations,
102
+ :class_name =>
103
+ "::Merb::Global::MessageProviders::ActiveRecord::Translation"
104
+ end
105
+
106
+ class Translation < ::ActiveRecord::Base
107
+ set_table_name :merb_global_translations
108
+ set_primary_keys :language_id, :msgid, :msgstr_index
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,113 @@
1
+ require 'dm-core'
2
+ require 'dm-aggregates'
3
+ require 'merb_global/plural'
4
+
5
+ module Merb
6
+ module Global
7
+ module MessageProviders
8
+ class DataMapper #:nodoc: all
9
+ include Merb::Global::MessageProviders
10
+ include Merb::Global::MessageProviders::Base::Importer
11
+ include Merb::Global::MessageProviders::Base::Exporter
12
+
13
+ def localize(singular, plural, n, locale)
14
+ # I hope it's from MemCache
15
+ language = Language.first :name => locale.to_s
16
+ unless language.nil?
17
+ unless plural.nil?
18
+ pn = Plural.which_form n, language.plural
19
+ translation = Translation.first :language_id => language.id,
20
+ :msgid => singular,
21
+ :msgstr_index => pn
22
+ else
23
+ translation = Translation.first :language_id => language.id,
24
+ :msgid => singular,
25
+ :msgstr_index => nil
26
+ end
27
+ return translation.msgstr unless translation.nil?
28
+ end
29
+ # Fallback if not in database
30
+ return n != 1 ? plural : singular
31
+ end
32
+
33
+ def create!
34
+ Language.auto_migrate!
35
+ Translation.auto_migrate!
36
+ end
37
+
38
+ def import
39
+ data = {}
40
+ ::DataMapper::Transaction.new(Language, Translation) do
41
+ Language.all.each do |language|
42
+ data[language.name] = lang_hash = {
43
+ :plural => language.plural,
44
+ :nplural => language.nplural
45
+ }
46
+ language.translations(:fields => Translation.properties.to_a).
47
+ each do |translation|
48
+ lang_hash[translation.msgid] ||= {
49
+ :plural => translation.msgid_plural
50
+ }
51
+ lang_hash[translation.msgid][translation.msgstr_index] =
52
+ translation.msgstr
53
+ end
54
+ end
55
+ end
56
+ data
57
+ end
58
+
59
+ def export(data)
60
+ ::DataMapper::Transaction.new(Language, Translation) do
61
+ Translation.all.each {|translation| translation.destroy}
62
+ Language.all.each {|language| language.destroy}
63
+ data.each do |lang_name, lang|
64
+ lang_obj = Language.create!(:name => lang_name,
65
+ :plural => lang[:plural],
66
+ :nplural => lang[:nplural])
67
+ lang.each do |msgid, msgstr_hash|
68
+ if msgstr_hash.is_a? Hash
69
+ plural = msgstr_hash[:plural]
70
+ msgstr_hash.each do |msgstr_index, msgstr|
71
+ if msgstr_index.nil? or msgstr_index.is_a? Fixnum
72
+ Translation.create!(:language_id => lang_obj.id,
73
+ :msgid => msgid,
74
+ :msgid_plural => plural,
75
+ :msgstr => msgstr,
76
+ :msgstr_index => msgstr_index) or
77
+ raise
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ # When table structure becomes stable it *should* be documented
87
+ class Language
88
+ include ::DataMapper::Resource
89
+ storage_names[:default] = 'merb_global_languages'
90
+ property :id, Integer, :serial => true
91
+ property :name, String, :unique_index => true
92
+ property :nplural, Integer
93
+ property :plural, Text, :lazy => false
94
+ # validates_is_unique :name
95
+ has n, :translations,
96
+ :class_name => "Merb::Global::MessageProviders::DataMapper::Translation",
97
+ :child_key => [:language_id]
98
+ end
99
+
100
+ class Translation
101
+ include ::DataMapper::Resource
102
+ storage_names[:default] = 'merb_global_translations'
103
+ property :language_id, Integer, :nullable => false, :key => true
104
+ property :msgid, Text, :nullable => false, :key => true
105
+ property :msgid_plural, Text, :lazy => true
106
+ property :msgstr, Text, :nullable => false, :lazy => false
107
+ property :msgstr_index, Integer, :nullable => true, :key => true
108
+ belongs_to :language, :class_name => Language.name
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,123 @@
1
+ require 'gettext'
2
+ require 'treetop'
3
+ require 'pathname'
4
+
5
+ class Merb::Global::Locale #:nodoc:
6
+ def _mg_gettext
7
+ @mg_gettext ||= Merb::Global::MessageProviders::Gettext::GettextContext.new
8
+ end
9
+ end
10
+
11
+ module Merb
12
+ module Global
13
+ module MessageProviders
14
+ class Gettext #:nodoc: all
15
+ include Merb::Global::MessageProviders::Base
16
+ include Merb::Global::MessageProviders::Base::Importer
17
+ include Merb::Global::MessageProviders::Base::Exporter
18
+
19
+ def localize(singular, plural, n, locale)
20
+ context = locale._mg_gettext
21
+ context.set_locale locale.to_s, true
22
+ unless plural.nil?
23
+ context.ngettext singular, plural, n
24
+ else
25
+ context.gettext singular
26
+ end
27
+ end
28
+
29
+ def create!
30
+ File.mkdirs Merb::Global::MessageProviders.localedir
31
+ end
32
+
33
+ def import
34
+ Treetop.load(Pathname(__FILE__).dirname.expand_path.to_s +
35
+ '/gettext')
36
+ parser = Merb::Global::MessageProviders::GetTextParser.new
37
+ data = {}
38
+ Dir[Merb::Global::MessageProviders.localedir +
39
+ '/*.po'].each do |file|
40
+ lang_name = File.basename file, '.po'
41
+ lang_tree = nil
42
+ open file do |f|
43
+ lang_tree = parser.parse f.read
44
+ end
45
+ # Put the parsed file in data
46
+ data[lang_name] = lang_tree.to_hash
47
+ # Remove the metadata to futher managing
48
+ opts = data[lang_name].delete('')[nil].split("\n")
49
+ # Find the line about plural line
50
+ plural_line = nil
51
+ for l in opts
52
+ if l[0..."Plural-Forms:".length] == "Plural-Forms:"
53
+ plural_line = l
54
+ break
55
+ end
56
+ end
57
+ # Remove the "Plural-Forms:" from the beginning...
58
+ plural_line =
59
+ plural_line["Plural-Forms:".length...plural_line.length]
60
+ # and ; from end
61
+ plural_line = plural_line[0...plural_line.length-1]
62
+ # Split the line and build the hash
63
+ plural_line = plural_line.gsub(/[[:space:]]/, '').split(/[=;]/, 4)
64
+ # And change the plural and nplurals into :plural and :nplurals
65
+ plural_line[2] = :plural
66
+ plural_line[0] = :nplural
67
+ # Adn the nplural value into integer
68
+ plural_line[1] = plural_line[1].to_i
69
+ data[lang_name].merge! Hash[*plural_line]
70
+ end
71
+ data
72
+ end
73
+
74
+ def export(data)
75
+ data.each do |lang_name, lang|
76
+ lang_file = File.join(Merb::Global::MessageProviders.localedir,
77
+ lang_name + '.po')
78
+ open(lang_file, 'w') do |po|
79
+ po.puts <<EOF
80
+ msgid ""
81
+ msgstr ""
82
+ "Project-Id-Version: 0.0.1\\n"
83
+ "POT-Creation-Date: #{Time.now.strftime('%Y-%m-%d %H:%M%z')}\\n"
84
+ "PO-Revision-Date: #{Time.now.strftime('%Y-%m-%d %H:%M%z')}\\n"
85
+ "Last-Translator: <user@example.com>\\n"
86
+ "Language-Team: Language type\\n"
87
+ "MIME-Version: 1.0\\n"
88
+ "Content-Type: text/plain; charset=UTF-8\\n"
89
+ "Content-Transfer-Encoding: 8bit\\n"
90
+ "Plural-Forms: nplurals=#{lang[:nplurals]}; plural=#{lang[:plural]}\\n"
91
+ EOF
92
+
93
+ lang.each do |msgid, msgstr_hash|
94
+ po.puts ""
95
+ po.puts "msgid \"#{msgid}\""
96
+ if msgstr_hash[:plural]
97
+ po.puts "msgid_plural \"#{msgstr_hash[:plural]}\""
98
+ msgstr_hash.each do |msgstr_index, msgstr|
99
+ po.puts "msgstr[#{msgstr_index}] \"#{msgstr}\""
100
+ end
101
+ else
102
+ po.puts "msgstr \"#{msgstr_hash[nil]}\""
103
+ end
104
+ end
105
+ end
106
+ lang_dir = File.join(Merb::Global::MessageProviders.localedir,
107
+ lang, 'LC_MESSAGES')
108
+ FileUtils.mkdir_p lang_dir
109
+ domain = Merb::Global.config([:gettext, :domain], 'merbapp')
110
+ `msgfmt #{lang_file} -o #{lang_dir}/#{domain}.mo`
111
+ end
112
+ end
113
+
114
+ class GettextContext
115
+ include ::GetText
116
+ bindtextdomain Merb::Global.config([:gettext, :domain], 'merbapp'),
117
+ Merb::Global::MessageProviders.localedir
118
+ public :set_locale, :ngettext, :gettext
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end