merb_global 0.0.4.2 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +6 -0
- data/Rakefile +14 -1
- data/activerecord_generators/translations_migration/templates/translations_migration.erb +1 -1
- data/lib/merb_global/base.rb +45 -14
- data/lib/merb_global/controller.rb +20 -5
- data/lib/merb_global/date_providers/fork.rb +35 -0
- data/lib/merb_global/date_providers.rb +47 -0
- data/lib/merb_global/merbrake.rb +10 -10
- data/lib/merb_global/{providers → message_providers}/active_record.rb +43 -36
- data/lib/merb_global/{providers → message_providers}/data_mapper.rb +44 -46
- data/lib/merb_global/message_providers/gettext.rb +138 -0
- data/lib/merb_global/message_providers/gettext.treetop +60 -0
- data/lib/merb_global/{providers → message_providers}/mock.rb +4 -4
- data/lib/merb_global/message_providers/sequel.rb +105 -0
- data/lib/merb_global/message_providers/yaml.rb +101 -0
- data/lib/merb_global/message_providers.rb +175 -0
- data/lib/merb_global/numeric_providers/fork.rb +35 -0
- data/lib/merb_global/numeric_providers.rb +48 -0
- data/lib/merb_global/providers.rb +32 -44
- data/sequel_generators/translations_migration/templates/translations_migration.erb +1 -1
- metadata +21 -14
- data/lib/merb_global/provider.rb +0 -73
- data/lib/merb_global/providers/gettext.rb +0 -90
- data/lib/merb_global/providers/gettext.treetop +0 -74
- data/lib/merb_global/providers/sequel.rb +0 -100
- data/lib/merb_global/providers/yaml.rb +0 -114
- data/lib/merb_global/transfer.rb +0 -79
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'gettext'
|
2
|
+
require 'treetop'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
# I'm not sure if it is the correct way of doing it.
|
6
|
+
# As far it seems to be simpler.
|
7
|
+
class Thread #:nodoc:
|
8
|
+
def gettext_context
|
9
|
+
@gettext_context ||= Merb::Global::MessageProviders::Gettext::GettextContext.new
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Merb
|
14
|
+
module Global
|
15
|
+
module MessageProviders
|
16
|
+
class Gettext #:nodoc: all
|
17
|
+
include Merb::Global::MessageProviders::Base
|
18
|
+
include Merb::Global::MessageProviders::Base::Importer
|
19
|
+
include Merb::Global::MessageProviders::Base::Exporter
|
20
|
+
|
21
|
+
def localize(singular, plural, opts)
|
22
|
+
context = Thread.current.gettext_context
|
23
|
+
context.set_locale opts[:lang], true
|
24
|
+
unless plural.nil?
|
25
|
+
context.ngettext singular, plural, opts[:n]
|
26
|
+
else
|
27
|
+
context.gettext singular
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def support?(lang)
|
32
|
+
lang == 'en' ||
|
33
|
+
File.exist?(File.join(Merb::Global::MessageProviders.localedir, lang))
|
34
|
+
end
|
35
|
+
|
36
|
+
def create!
|
37
|
+
File.mkdirs Merb::Global::MessageProviders.localedir
|
38
|
+
end
|
39
|
+
|
40
|
+
def choose(except)
|
41
|
+
dir = Dir[Merb::Global::MessageProviders.localedir + '/*/']
|
42
|
+
dir.collect! {|p| File.basename p}
|
43
|
+
dir << 'en'
|
44
|
+
dir.reject! {|lang| except.include? lang}
|
45
|
+
dir.first
|
46
|
+
end
|
47
|
+
|
48
|
+
def import
|
49
|
+
Treetop.load(Pathname(__FILE__).dirname.expand_path.to_s +
|
50
|
+
'/gettext')
|
51
|
+
parser = Merb::Global::MessageProviders::GetTextParser.new
|
52
|
+
data = {}
|
53
|
+
Dir[Merb::Global::MessageProviders.localedir +
|
54
|
+
'/*.po'].each do |file|
|
55
|
+
lang_name = File.basename file, '.po'
|
56
|
+
lang_tree = nil
|
57
|
+
open file do |f|
|
58
|
+
lang_tree = parser.parse f.read
|
59
|
+
end
|
60
|
+
# Put the parsed file in data
|
61
|
+
data[lang_name] = lang_tree.to_hash
|
62
|
+
# Remove the metadata to futher managing
|
63
|
+
opts = data[lang_name].delete('')[nil].split("\n")
|
64
|
+
# Find the line about plural line
|
65
|
+
plural_line = nil
|
66
|
+
for l in opts
|
67
|
+
if l[0..."Plural-Forms:".length] == "Plural-Forms:"
|
68
|
+
plural_line = l
|
69
|
+
break
|
70
|
+
end
|
71
|
+
end
|
72
|
+
# Remove the "Plural-Forms:" from the beginning...
|
73
|
+
plural_line =
|
74
|
+
plural_line["Plural-Forms:".length...plural_line.length]
|
75
|
+
# and ; from end
|
76
|
+
plural_line = plural_line[0...plural_line.length-1]
|
77
|
+
# Split the line and build the hash
|
78
|
+
plural_line = plural_line.gsub(/[[:space:]]/, '').split(/[=;]/, 4)
|
79
|
+
# And change the plural and nplurals into :plural and :nplurals
|
80
|
+
plural_line[2] = :plural
|
81
|
+
plural_line[0] = :nplural
|
82
|
+
# Adn the nplural value into integer
|
83
|
+
plural_line[1] = plural_line[1].to_i
|
84
|
+
data[lang_name].merge! Hash[*plural_line]
|
85
|
+
end
|
86
|
+
data
|
87
|
+
end
|
88
|
+
|
89
|
+
def export(data)
|
90
|
+
data.each do |lang_name, lang|
|
91
|
+
lang_file = File.join(Merb::Global::MessageProviders.localedir,
|
92
|
+
lang_name + '.po')
|
93
|
+
open(lang_file, 'w') do |po|
|
94
|
+
po.puts <<EOF
|
95
|
+
msgid ""
|
96
|
+
msgstr ""
|
97
|
+
"Project-Id-Version: 0.0.1\\n"
|
98
|
+
"POT-Creation-Date: #{Time.now.strftime('%Y-%m-%d %H:%M%z')}\\n"
|
99
|
+
"PO-Revision-Date: #{Time.now.strftime('%Y-%m-%d %H:%M%z')}\\n"
|
100
|
+
"Last-Translator: <user@example.com>\\n"
|
101
|
+
"Language-Team: Language type\\n"
|
102
|
+
"MIME-Version: 1.0\\n"
|
103
|
+
"Content-Type: text/plain; charset=UTF-8\\n"
|
104
|
+
"Content-Transfer-Encoding: 8bit\\n"
|
105
|
+
"Plural-Forms: nplurals=#{lang[:nplurals]}; plural=#{lang[:plural]}\\n"
|
106
|
+
EOF
|
107
|
+
|
108
|
+
lang.each do |msgid, msgstr_hash|
|
109
|
+
po.puts ""
|
110
|
+
po.puts "msgid \"#{msgid}\""
|
111
|
+
if msgstr_hash[:plural]
|
112
|
+
po.puts "msgid_plural \"#{msgstr_hash[:plural]}\""
|
113
|
+
msgstr_hash.each do |msgstr_index, msgstr|
|
114
|
+
po.puts "msgstr[#{msgstr_index}] \"#{msgstr}\""
|
115
|
+
end
|
116
|
+
else
|
117
|
+
po.puts "msgstr \"#{msgstr_hash[nil]}\""
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
lang_dir = File.join(Merb::Global::MessageProviders.localedir,
|
122
|
+
lang, 'LC_MESSAGES')
|
123
|
+
FileUtils.mkdir_p lang_dir
|
124
|
+
domain = Merb::Global.config([:gettext, :domain], 'merbapp')
|
125
|
+
`msgfmt #{lang_file} -o #{lang_dir}/#{domain}.mo`
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class GettextContext
|
130
|
+
include ::GetText
|
131
|
+
bindtextdomain Merb::Global.config([:gettext, :domain], 'merbapp'),
|
132
|
+
Merb::Global::MessageProviders.localedir
|
133
|
+
public :set_locale, :ngettext, :gettext
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Merb
|
2
|
+
module Global
|
3
|
+
module MessageProviders
|
4
|
+
grammar GetText
|
5
|
+
rule po_file
|
6
|
+
entry* {
|
7
|
+
def to_hash
|
8
|
+
hash = {}
|
9
|
+
elements.each {|entry| hash.merge! entry.to_hash}
|
10
|
+
hash
|
11
|
+
end
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
rule entry
|
16
|
+
whitespaces*
|
17
|
+
"msgid" whitespaces msgid:strings
|
18
|
+
"msgstr" whitespaces msgstr:strings {
|
19
|
+
def to_hash
|
20
|
+
{msgid.to_string => {:plural => nil, nil => msgstr.to_string}}
|
21
|
+
end
|
22
|
+
}
|
23
|
+
/
|
24
|
+
whitespaces*
|
25
|
+
"msgid" whitespaces msgid:strings
|
26
|
+
"msgid_plural" whitespaces msgid_plural:strings
|
27
|
+
msgstrs:("msgstr[" number:[0-9]+ "]" whitespaces strings)+ {
|
28
|
+
def to_hash
|
29
|
+
hash = {:plural => msgid_plural.to_string}
|
30
|
+
msgstrs.elements.each do |msgstr|
|
31
|
+
hash[msgstr.number.text_value.to_i] = msgstr.strings.to_string
|
32
|
+
end
|
33
|
+
{msgid.to_string => hash}
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
rule strings
|
39
|
+
(string whitespaces?)+ {
|
40
|
+
def to_string
|
41
|
+
elements.collect {|element| element.string.to_string}.join
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
rule string
|
47
|
+
'"' content:((!'"' ('\"' / .))*) '"' {
|
48
|
+
def to_string
|
49
|
+
content.text_value.gsub(/\\n/, "\n")
|
50
|
+
end
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
rule whitespaces
|
55
|
+
(" " / "\t" / "\n" / ('#' (!"\n" .)* "\n") )+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Merb
|
2
2
|
module Global
|
3
|
-
module
|
3
|
+
module MessageProviders
|
4
4
|
class Mock #:nodoc:
|
5
|
-
include Merb::Global::
|
6
|
-
|
7
|
-
def
|
5
|
+
include Merb::Global::MessageProviders::Base
|
6
|
+
|
7
|
+
def localize(singular, plural, opts)
|
8
8
|
opts[:n] > 1 ? plural : singular
|
9
9
|
end
|
10
10
|
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
require 'merb_global/plural'
|
3
|
+
|
4
|
+
module Merb
|
5
|
+
module Global
|
6
|
+
module MessageProviders
|
7
|
+
class Sequel #:nodoc: all
|
8
|
+
include Merb::Global::MessageProviders::Base
|
9
|
+
include Merb::Global::MessageProviders::Base::Importer
|
10
|
+
include Merb::Global::MessageProviders::Base::Exporter
|
11
|
+
|
12
|
+
def localize(singular, plural, opts)
|
13
|
+
language = Language[:name => opts[:lang]] # I hope it's from MemCache
|
14
|
+
unless language.nil?
|
15
|
+
unless plural.nil?
|
16
|
+
n = Plural.which_form opts[:n], language[:plural]
|
17
|
+
translation = Translation[language.pk, singular, n]
|
18
|
+
else
|
19
|
+
translation = Translation[language.pk, singular, nil]
|
20
|
+
end
|
21
|
+
return translation[:msgstr] unless translation.nil?
|
22
|
+
end
|
23
|
+
return opts[:n] > 1 ? plural : singular # Fallback if not in database
|
24
|
+
end
|
25
|
+
|
26
|
+
def support?(lang)
|
27
|
+
Language.filter(:name => lang).count != 0
|
28
|
+
end
|
29
|
+
|
30
|
+
def create!
|
31
|
+
migration_exists = Dir[File.join(Merb.root, 'schema',
|
32
|
+
'migrations', "*.rb")].detect do |f|
|
33
|
+
f =~ /translations\.rb/
|
34
|
+
end
|
35
|
+
if migration_exists
|
36
|
+
puts "\nThe Translation Migration File already exists\n\n"
|
37
|
+
else
|
38
|
+
sh %{merb-gen translations_migration}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def choose(except)
|
43
|
+
Language.filter(~{:name => except}).first[:name]
|
44
|
+
end
|
45
|
+
|
46
|
+
def import
|
47
|
+
data = {}
|
48
|
+
DB.transaction do
|
49
|
+
Language.each do |lang|
|
50
|
+
data[lang[:name]] = lang_hash = {
|
51
|
+
:plural => lang[:plural],
|
52
|
+
:nplural => lang[:nplural]
|
53
|
+
}
|
54
|
+
lang.translations.each do |translation|
|
55
|
+
lang_hash[translation[:msgid]] ||= {
|
56
|
+
:plural => translation[:msgid_plural]
|
57
|
+
}
|
58
|
+
lang_hash[translation[:msgid]][translation[:msgstr_index]] =
|
59
|
+
translation[:msgstr]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
data
|
64
|
+
end
|
65
|
+
|
66
|
+
def export(data)
|
67
|
+
DB.transaction do
|
68
|
+
Language.delete_all
|
69
|
+
Translation.delete_all
|
70
|
+
data.each do |lang_name, lang|
|
71
|
+
lang_obj = Language.create(:name => lang_name,
|
72
|
+
:plural => lang[:plural],
|
73
|
+
:nplural => lang[:nplural]) or raise
|
74
|
+
lang_id = lang_obj[:id]
|
75
|
+
lang.each do |msgid, msgstrs|
|
76
|
+
if msgid.is_a? String
|
77
|
+
plural = msgstrs[:plural]
|
78
|
+
msgstrs.each do |index, msgstr|
|
79
|
+
if index.nil? or index.is_a? Fixnum
|
80
|
+
Translation.create(:language_id => lang_id,
|
81
|
+
:msgid => msgid,
|
82
|
+
:msgid_plural => plural,
|
83
|
+
:msgstr => msgstr,
|
84
|
+
:msgstr_index => index) or raise
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class Language < ::Sequel::Model(:merb_global_languages)
|
94
|
+
has_many :translations,
|
95
|
+
:class => "Merb::Global::MessageProviders::Sequel::Translation",
|
96
|
+
:key => :language_id
|
97
|
+
end
|
98
|
+
|
99
|
+
class Translation < ::Sequel::Model(:merb_global_translations)
|
100
|
+
set_primary_key :language_id, :msgid, :msgstr_index
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Merb
|
5
|
+
module Global
|
6
|
+
module MessageProviders
|
7
|
+
class Yaml #:nodoc:
|
8
|
+
include Merb::Global::MessageProviders::Base
|
9
|
+
include Merb::Global::MessageProviders::Base::Importer
|
10
|
+
include Merb::Global::MessageProviders::Base::Exporter
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
# Not synchronized - make GC do it's work (may be not optimal
|
14
|
+
# but I don't think that some problem will occure).
|
15
|
+
# Shouldn't it be sort of cache with some expiration limit?
|
16
|
+
@lang = Hash.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def localize(singular, plural, opts)
|
20
|
+
unless @lang.include? opts[:lang]
|
21
|
+
file = File.join Merb::Global::MessageProviders.localedir,
|
22
|
+
opts[:lang] + '.yaml'
|
23
|
+
if File.exist? file
|
24
|
+
@lang[opts[:lang]] = YAML.load_file file
|
25
|
+
else
|
26
|
+
@lang[opts[:lang]] = nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
unless @lang[opts[:lang]].nil?
|
31
|
+
lang = @lang[opts[:lang]]
|
32
|
+
unless lang[singular].nil?
|
33
|
+
unless plural.nil?
|
34
|
+
n = Merb::Global::Plural.which_form opts[:n], lang[:plural]
|
35
|
+
return lang[singular][n] unless lang[singular][n].nil?
|
36
|
+
else
|
37
|
+
return lang[singular] unless lang[singular].nil?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
return opts[:n] > 1 ? plural : singular
|
42
|
+
end
|
43
|
+
|
44
|
+
def support?(lang)
|
45
|
+
unless @lang.include? lang
|
46
|
+
file = File.join Merb::Global::MessageProviders.localedir,
|
47
|
+
lang + '.yaml'
|
48
|
+
@lang[lang] = YAML.load_file file if File.exist? file
|
49
|
+
end
|
50
|
+
not @lang[lang].nil?
|
51
|
+
end
|
52
|
+
|
53
|
+
def create!
|
54
|
+
FileUtils.mkdir_p Merb::Global::MessageProviders.localedir
|
55
|
+
end
|
56
|
+
|
57
|
+
def choose(except)
|
58
|
+
dir = Dir[Merb::Global::MessageProviders.localedir + '/*.yaml']
|
59
|
+
dir.collect! {|p| File.basename p, '.yaml'}
|
60
|
+
dir.reject! {|lang| except.include? lang}
|
61
|
+
dir.first
|
62
|
+
end
|
63
|
+
|
64
|
+
def import
|
65
|
+
data = {}
|
66
|
+
Dir[Merb::Global::MessageProviders.localedir +
|
67
|
+
'/*.yaml'].each do |file|
|
68
|
+
lang_name = File.basename file, '.yaml'
|
69
|
+
data[lang_name] = lang = YAML.load_file(file)
|
70
|
+
lang.each do |msgid, msgstr|
|
71
|
+
if msgstr.is_a? String and msgid.is_a? String
|
72
|
+
lang[msgid] = {nil => msgstr, :plural => nil}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
data
|
77
|
+
end
|
78
|
+
|
79
|
+
def export(data)
|
80
|
+
File.unlink *Dir[Merb::Global::MessageProviders.localedir +
|
81
|
+
'/*.yaml']
|
82
|
+
data.each do |lang_name, lang_orig|
|
83
|
+
lang = {}
|
84
|
+
lang_orig.each do |msgid, msgstr_hash|
|
85
|
+
lang[msgid] = {}
|
86
|
+
msgstr_hash.each do |msgstr_index, msgstr|
|
87
|
+
if msgstr_index.nil?
|
88
|
+
lang[msgid] = msgstr
|
89
|
+
else
|
90
|
+
lang[msgid][msgstr_index] = msgstr
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
YAML.dump File.join(Merb::Global::MessageProviders.localedir,
|
95
|
+
lang_name + '.yaml')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'merb_global/providers'
|
2
|
+
|
3
|
+
module Merb
|
4
|
+
module Global
|
5
|
+
module MessageProviders
|
6
|
+
include Providers
|
7
|
+
# call-seq:
|
8
|
+
# localedir => localdir
|
9
|
+
#
|
10
|
+
# Returns the directory where locales are stored for file-backended
|
11
|
+
# providers (such as gettext or yaml)
|
12
|
+
#
|
13
|
+
# ==== Returns
|
14
|
+
# localedir<String>>:: Directory where the locales are stored
|
15
|
+
def self.localedir
|
16
|
+
localedir =
|
17
|
+
if Merb::Global.config :flat
|
18
|
+
'locale'
|
19
|
+
else
|
20
|
+
Merb::Global.config :localedir, File.join('app', 'locale')
|
21
|
+
end
|
22
|
+
File.join Merb.root, localedir
|
23
|
+
end
|
24
|
+
# call-seq:
|
25
|
+
# provider => provider
|
26
|
+
#
|
27
|
+
# Returns the provider of required type
|
28
|
+
#
|
29
|
+
# ==== Returns
|
30
|
+
# provider<Provider>:: Returns provider
|
31
|
+
def self.provider
|
32
|
+
@@provider ||= self[Merb::Global.config(:message_provider, 'gettext')]
|
33
|
+
end
|
34
|
+
# Merb-global is able to store the translations in different types of
|
35
|
+
# storage. An interface betwean merb-global and those storages are
|
36
|
+
# providers.
|
37
|
+
#
|
38
|
+
# Please note that it is not required to include this module - despite it
|
39
|
+
# is recomended both as a documentation part and the more customized
|
40
|
+
# error messages.
|
41
|
+
module Base
|
42
|
+
# call-seq:
|
43
|
+
# localize(singular, plural, opts) => translated
|
44
|
+
#
|
45
|
+
# Translate string using specific provider.
|
46
|
+
# It should be overloaded by the implementator.
|
47
|
+
#
|
48
|
+
# Do not use this method directly - use Merb::Global._ instead
|
49
|
+
#
|
50
|
+
# ==== Parameters
|
51
|
+
# singular<String>:: A string to translate
|
52
|
+
# plural<String>:: A plural form of string (nil if only singular)
|
53
|
+
# opts<Hash>:: An options hash (see below)
|
54
|
+
#
|
55
|
+
# ==== Options (opts)
|
56
|
+
# :lang<String>:: A language to translate on
|
57
|
+
# :n<Fixnum>:: A number of objects
|
58
|
+
#
|
59
|
+
# ==== Returns
|
60
|
+
# translated<String>:: A translated string
|
61
|
+
#
|
62
|
+
# ==== Raises
|
63
|
+
# NoMethodError:: Raised by default implementation. Should not be thrown.
|
64
|
+
def localize(singular, plural, opts)
|
65
|
+
raise NoMethodError.new 'method localize has not been implemented'
|
66
|
+
end
|
67
|
+
# call-seq:
|
68
|
+
# support?(lang) => supported
|
69
|
+
#
|
70
|
+
# Checks if the language is supported (i.e. if the translation exists).
|
71
|
+
#
|
72
|
+
# In normal merb app the language is checked automatically in controller
|
73
|
+
# so probably you don't have to use this method
|
74
|
+
#
|
75
|
+
# ==== Parameters
|
76
|
+
# lang<String>:: A code of language
|
77
|
+
#
|
78
|
+
# ==== Returns
|
79
|
+
# supported<Boolean>:: Is a program translated to this language
|
80
|
+
#
|
81
|
+
# ==== Raises
|
82
|
+
# NoMethodError:: Raised by default implementation.
|
83
|
+
# Should not be thrown.
|
84
|
+
def support?(lang)
|
85
|
+
raise NoMethodError.new('method support? has not been implemented')
|
86
|
+
end
|
87
|
+
# This method creates basic files and/or directory structures
|
88
|
+
# (for example it adds migration) needed for provider to work.
|
89
|
+
#
|
90
|
+
# It is called from Rakefile.
|
91
|
+
def create!
|
92
|
+
raise NoMethodError.new('method create! has not been implemented')
|
93
|
+
end
|
94
|
+
# This method choos an supported language except those form the list
|
95
|
+
# given. It may fallback to english if none language can be found
|
96
|
+
# which agree with those criteria
|
97
|
+
def choose(except)
|
98
|
+
raise NoMethodError.new('method choose has not been implemented')
|
99
|
+
end
|
100
|
+
##
|
101
|
+
# Transfer data from importer into exporter
|
102
|
+
#
|
103
|
+
# ==== Parameters
|
104
|
+
# importer<Importer>:: The provider providing the information
|
105
|
+
# exporter<Exporter>:: The provider receiving the information
|
106
|
+
def self.transfer(importer, exporter)
|
107
|
+
exporter.export importer.import
|
108
|
+
end
|
109
|
+
##
|
110
|
+
# Importer is a provider through which one can iterate.
|
111
|
+
# Therefore it is possible to import data from this source
|
112
|
+
module Importer
|
113
|
+
##
|
114
|
+
# This method import the data into a specified format from source.
|
115
|
+
# The format is nearly dump of the current YAML format.
|
116
|
+
#
|
117
|
+
# ==== Returns
|
118
|
+
# data<~each>:: Data in the specified format.
|
119
|
+
#
|
120
|
+
# ==== Raises
|
121
|
+
# NoMethodError:: Raised by default implementation.
|
122
|
+
# Should not be thrown.
|
123
|
+
def import # TODO: Describe the format
|
124
|
+
raise NoMethodError.new('method import has not been implemented')
|
125
|
+
end
|
126
|
+
end
|
127
|
+
##
|
128
|
+
# Some sources are not only read-only but one can write to them.
|
129
|
+
# The provider is exporter if it handles this sort of source.
|
130
|
+
module Exporter
|
131
|
+
##
|
132
|
+
# The method export the data from specified format into destination
|
133
|
+
# The format is nearly dump of the current YAML format.
|
134
|
+
#
|
135
|
+
# ==== Parameters
|
136
|
+
# data<~each>:: Data in the specified format.
|
137
|
+
#
|
138
|
+
# ==== Raises
|
139
|
+
# NoMethodError:: Raised by default implementation.
|
140
|
+
# Should not be thrown.
|
141
|
+
def export(data) # TODO: Describe the format
|
142
|
+
raise NoMethodError.new('method import has not been implemented')
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
# Perform the registration
|
148
|
+
#
|
149
|
+
# ==== Parameters
|
150
|
+
# provider_name<~to_sym>:: Name under which it is registred
|
151
|
+
# opts<Array[Symbol]>:: Additional imformations
|
152
|
+
#
|
153
|
+
# ==== Options
|
154
|
+
# importer:: Can perform import
|
155
|
+
# exporter:: Can perform export
|
156
|
+
def self.MessageProvider(provider_name, *opts)
|
157
|
+
Module.new do
|
158
|
+
@@mg_message_provider_name = provider_name
|
159
|
+
|
160
|
+
include Merb::Global::MessageProviders::Base
|
161
|
+
if opts.include? :importer
|
162
|
+
include Merb::Global::MessageProviders::Base::Importer
|
163
|
+
end
|
164
|
+
if opts.include? :exporter
|
165
|
+
include Merb::Global::MessageProviders::Base::Exporter
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.included(klass)
|
169
|
+
Merb::Global::MessageProviders.register @@mg_message_provider_name,
|
170
|
+
klass
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'inline'
|
2
|
+
|
3
|
+
module Merb
|
4
|
+
module Global
|
5
|
+
module NumericProviders
|
6
|
+
class Fork
|
7
|
+
include Merb::Global::DateProviders::Base
|
8
|
+
|
9
|
+
def localize(lang, number)
|
10
|
+
pipe_rd, pipe_wr = IO.pipe
|
11
|
+
pid = fork do
|
12
|
+
pipe_rd.close
|
13
|
+
setlocale(lang)
|
14
|
+
pipe_wr.write(number)
|
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,48 @@
|
|
1
|
+
require 'merb_global/providers'
|
2
|
+
|
3
|
+
module Merb
|
4
|
+
module Global
|
5
|
+
module NumericProviders
|
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(:numeric_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, number)
|
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 registred
|
36
|
+
def self.NumericProvider(provider_name)
|
37
|
+
Module.new do
|
38
|
+
@@rb_numeric_provider_name = provider_name
|
39
|
+
include Merb::Global::NumericProviders::Base
|
40
|
+
|
41
|
+
def self.included(klass)
|
42
|
+
Merb::Global::NumericProviders.register @@rb_numeric_provider_name,
|
43
|
+
klass
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|