merb_global 0.0.4.2 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|