gettext 2.3.9 → 3.0.0
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/.yardopts +1 -0
- data/README.rdoc +28 -23
- data/Rakefile +29 -21
- data/doc/text/news.md +57 -0
- data/gettext.gemspec +1 -1
- data/lib/gettext.rb +13 -29
- data/lib/gettext/cgi.rb +1 -1
- data/lib/gettext/{runtime/class_info.rb → class_info.rb} +1 -1
- data/lib/gettext/{runtime/locale_path.rb → locale_path.rb} +1 -2
- data/lib/gettext/{runtime/mo.rb → mo.rb} +18 -33
- data/lib/gettext/{tools/po.rb → po.rb} +1 -1
- data/lib/gettext/{tools/po_entry.rb → po_entry.rb} +8 -4
- data/lib/gettext/{tools/poparser.rb → po_parser.rb} +41 -44
- data/lib/gettext/{runtime/textdomain.rb → text_domain.rb} +6 -16
- data/lib/gettext/text_domain_group.rb +26 -0
- data/lib/gettext/{runtime/textdomain_manager.rb → text_domain_manager.rb} +40 -40
- data/lib/gettext/tools.rb +1 -182
- data/lib/gettext/tools/msgfmt.rb +1 -1
- data/lib/gettext/tools/msginit.rb +1 -1
- data/lib/gettext/tools/msgmerge.rb +2 -221
- data/lib/gettext/tools/parser/erb.rb +49 -30
- data/lib/gettext/tools/parser/glade.rb +44 -36
- data/lib/gettext/tools/parser/ruby.rb +126 -37
- data/lib/gettext/tools/task.rb +225 -0
- data/lib/gettext/tools/xgettext.rb +25 -28
- data/lib/gettext/version.rb +1 -1
- data/locale/bg/LC_MESSAGES/gettext.mo +0 -0
- data/locale/bs/LC_MESSAGES/gettext.mo +0 -0
- data/locale/ca/LC_MESSAGES/gettext.mo +0 -0
- data/locale/cs/LC_MESSAGES/gettext.mo +0 -0
- data/locale/de/LC_MESSAGES/gettext.mo +0 -0
- data/locale/el/LC_MESSAGES/gettext.mo +0 -0
- data/locale/eo/LC_MESSAGES/gettext.mo +0 -0
- data/locale/es/LC_MESSAGES/gettext.mo +0 -0
- data/locale/et/LC_MESSAGES/gettext.mo +0 -0
- data/locale/fr/LC_MESSAGES/gettext.mo +0 -0
- data/locale/hr/LC_MESSAGES/gettext.mo +0 -0
- data/locale/hu/LC_MESSAGES/gettext.mo +0 -0
- data/locale/it/LC_MESSAGES/gettext.mo +0 -0
- data/locale/ja/LC_MESSAGES/gettext.mo +0 -0
- data/locale/ko/LC_MESSAGES/gettext.mo +0 -0
- data/locale/lv/LC_MESSAGES/gettext.mo +0 -0
- data/locale/nb/LC_MESSAGES/gettext.mo +0 -0
- data/locale/nl/LC_MESSAGES/gettext.mo +0 -0
- data/locale/pt_BR/LC_MESSAGES/gettext.mo +0 -0
- data/locale/ru/LC_MESSAGES/gettext.mo +0 -0
- data/locale/sr/LC_MESSAGES/gettext.mo +0 -0
- data/locale/sv/LC_MESSAGES/gettext.mo +0 -0
- data/locale/uk/LC_MESSAGES/gettext.mo +0 -0
- data/locale/vi/LC_MESSAGES/gettext.mo +0 -0
- data/locale/zh/LC_MESSAGES/gettext.mo +0 -0
- data/locale/zh_TW/LC_MESSAGES/gettext.mo +0 -0
- data/po/gettext.pot +171 -97
- data/samples/hello.rb +3 -2
- data/samples/hello2.rb +2 -1
- data/samples/hello_gtk2.rb +4 -1
- data/samples/hello_gtk_builder.rb +32 -0
- data/samples/hello_gtk_builder.ui +46 -0
- data/samples/hello_noop.rb +2 -1
- data/samples/hello_plural.rb +2 -1
- data/samples/hello_tk.rb +2 -1
- data/src/{poparser.ry → po_parser.ry} +31 -35
- data/test/fixtures/N_.rb +1 -1
- data/test/fixtures/_/double_quote_in_double_quote.rb +32 -0
- data/test/fixtures/_/double_quote_in_single_quote.rb +32 -0
- data/test/fixtures/_/literal_concatenation_with_continuation_line.rb +36 -0
- data/test/fixtures/_/middle_new_line.rb +32 -0
- data/test/fixtures/_/multiple_lines_literal.rb +35 -0
- data/test/fixtures/_/multiple_messages_in_same_line.rb +32 -0
- data/test/fixtures/_/multiple_same_messages.rb +36 -0
- data/{lib/gettext/runtime/mofile.rb → test/fixtures/_/one_new_line.rb} +12 -6
- data/test/fixtures/{multi_textdomain.rb → multi_text_domain.rb} +1 -1
- data/test/fixtures/non_ascii.rb +1 -1
- data/test/fixtures/simple.rb +1 -1
- data/test/fixtures/untranslated.rb +1 -1
- data/test/gettext-test-utils.rb +1 -24
- data/test/po/ja/_.po +63 -13
- data/test/po/ja/non_ascii.po +2 -3
- data/test/po/ja/untranslated.po +1 -1
- data/test/test_class_info.rb +2 -2
- data/test/test_gettext.rb +11 -11
- data/test/test_mo.rb +2 -2
- data/test/test_parser.rb +93 -96
- data/test/test_po_entry.rb +237 -146
- data/test/test_po_parser.rb +107 -98
- data/test/test_string.rb +1 -1
- data/test/{test_textdomain_bind.rb → test_text_domain_bind.rb} +6 -6
- data/test/{test_textdomain_multi.rb → test_text_domain_multi.rb} +5 -5
- data/test/{test_textdomain_toplevel.rb → test_text_domain_toplevel.rb} +1 -1
- data/test/test_thread.rb +1 -1
- data/test/tools/files/simple_translation.rb +1 -1
- data/test/{parser → tools/parser}/test_ruby.rb +110 -14
- data/test/tools/test_msgmerge.rb +17 -276
- data/test/tools/test_po.rb +1 -1
- data/test/tools/test_xgettext.rb +175 -144
- metadata +59 -33
- data/lib/gettext/core_ext/iconv.rb +0 -110
- data/lib/gettext/core_ext/string.rb +0 -91
- data/lib/gettext/parser/erb.rb +0 -5
- data/lib/gettext/parser/glade.rb +0 -5
- data/lib/gettext/parser/ruby.rb +0 -172
- data/lib/gettext/runtime/textdomain_group.rb +0 -26
- data/lib/gettext/task.rb +0 -203
- data/lib/gettext/utils.rb +0 -39
- data/test/test_po_generation.rb +0 -45
- data/test/tools/test_tools.rb +0 -61
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
=begin
|
|
4
4
|
parser/glade.rb - parser for Glade-2
|
|
5
5
|
|
|
6
|
+
Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
|
|
6
7
|
Copyright (C) 2004,2005 Masao Mutoh
|
|
7
8
|
|
|
8
9
|
You may redistribute it and/or modify it under the same
|
|
@@ -13,47 +14,69 @@ require 'cgi'
|
|
|
13
14
|
require 'gettext'
|
|
14
15
|
|
|
15
16
|
module GetText
|
|
16
|
-
|
|
17
|
+
class GladeParser
|
|
17
18
|
extend GetText
|
|
18
|
-
extend self
|
|
19
19
|
|
|
20
20
|
bindtextdomain("gettext")
|
|
21
21
|
|
|
22
|
+
class << self
|
|
23
|
+
XML_RE = /<\?xml/
|
|
24
|
+
GLADE_RE = /glade-2.0.dtd/
|
|
25
|
+
|
|
26
|
+
def target?(file) # :nodoc:
|
|
27
|
+
data = IO.readlines(file)
|
|
28
|
+
if XML_RE =~ data[0] and GLADE_RE =~ data[1]
|
|
29
|
+
true
|
|
30
|
+
else
|
|
31
|
+
if File.extname(file) == '.glade'
|
|
32
|
+
raise _("`%{file}' is not glade-2.0 format.") % {:file => file}
|
|
33
|
+
end
|
|
34
|
+
false
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def parse(path, options={})
|
|
39
|
+
parser = new(path, options)
|
|
40
|
+
parser.parse
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
22
44
|
TARGET1 = /<property.*translatable="yes">(.*)/
|
|
23
45
|
TARGET2 = /(.*)<\/property>/
|
|
24
46
|
|
|
25
|
-
def
|
|
26
|
-
|
|
27
|
-
|
|
47
|
+
def initialize(path, options={})
|
|
48
|
+
@path = path
|
|
49
|
+
@options = options
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def parse # :nodoc:
|
|
53
|
+
File.open(@path) do |file|
|
|
54
|
+
parse_source(file)
|
|
55
|
+
end
|
|
28
56
|
end
|
|
29
57
|
|
|
30
|
-
|
|
31
|
-
def
|
|
58
|
+
private
|
|
59
|
+
def parse_source(input) # :nodoc:
|
|
32
60
|
targets = []
|
|
33
|
-
cnt = 0
|
|
34
61
|
target = false
|
|
35
|
-
|
|
62
|
+
start_line_no = nil
|
|
36
63
|
val = nil
|
|
37
64
|
|
|
38
|
-
|
|
39
|
-
line = lines.shift
|
|
40
|
-
break unless line
|
|
41
|
-
|
|
42
|
-
cnt += 1
|
|
65
|
+
input.each_line.with_index do |line, i|
|
|
43
66
|
if TARGET1 =~ line
|
|
44
|
-
|
|
67
|
+
start_line_no = i + 1
|
|
45
68
|
val = $1 + "\n"
|
|
46
69
|
target = true
|
|
47
70
|
if TARGET2 =~ $1
|
|
48
71
|
val = $1
|
|
49
|
-
add_target(val,
|
|
72
|
+
add_target(val, start_line_no, targets)
|
|
50
73
|
val = nil
|
|
51
74
|
target = false
|
|
52
75
|
end
|
|
53
76
|
elsif target
|
|
54
77
|
if TARGET2 =~ line
|
|
55
78
|
val << $1
|
|
56
|
-
add_target(val,
|
|
79
|
+
add_target(val, start_line_no, targets)
|
|
57
80
|
val = nil
|
|
58
81
|
target = false
|
|
59
82
|
else
|
|
@@ -64,29 +87,14 @@ module GetText
|
|
|
64
87
|
targets
|
|
65
88
|
end
|
|
66
89
|
|
|
67
|
-
|
|
68
|
-
GLADE_RE = /glade-2.0.dtd/
|
|
69
|
-
|
|
70
|
-
def target?(file) # :nodoc:
|
|
71
|
-
data = IO.readlines(file)
|
|
72
|
-
if XML_RE =~ data[0] and GLADE_RE =~ data[1]
|
|
73
|
-
true
|
|
74
|
-
else
|
|
75
|
-
if File.extname(file) == '.glade'
|
|
76
|
-
raise _("`%{file}' is not glade-2.0 format.") % {:file => file}
|
|
77
|
-
end
|
|
78
|
-
false
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def add_target(val, file, line_no, targets) # :nodoc:
|
|
90
|
+
def add_target(val, line_no, targets) # :nodoc:
|
|
83
91
|
return unless val.size > 0
|
|
84
92
|
assoc_data = targets.assoc(val)
|
|
85
93
|
val = CGI.unescapeHTML(val)
|
|
86
94
|
if assoc_data
|
|
87
|
-
targets[targets.index(assoc_data)] = assoc_data << "#{
|
|
95
|
+
targets[targets.index(assoc_data)] = assoc_data << "#{@path}:#{line_no}"
|
|
88
96
|
else
|
|
89
|
-
targets << [val.gsub(/\n/, '\n'), "#{
|
|
97
|
+
targets << [val.gsub(/\n/, '\n'), "#{@path}:#{line_no}"]
|
|
90
98
|
end
|
|
91
99
|
targets
|
|
92
100
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
=begin
|
|
3
3
|
parser/ruby.rb - parser for ruby script
|
|
4
4
|
|
|
5
|
+
Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
|
|
5
6
|
Copyright (C) 2003-2009 Masao Mutoh
|
|
6
7
|
Copyright (C) 2005 speakillof
|
|
7
8
|
Copyright (C) 2001,2002 Yasushi Shoji, Masao Mutoh
|
|
@@ -11,9 +12,9 @@
|
|
|
11
12
|
|
|
12
13
|
=end
|
|
13
14
|
|
|
14
|
-
require
|
|
15
|
-
require
|
|
16
|
-
require
|
|
15
|
+
require "irb/ruby-lex"
|
|
16
|
+
require "stringio"
|
|
17
|
+
require "gettext/po_entry"
|
|
17
18
|
|
|
18
19
|
module GetText
|
|
19
20
|
class RubyLexX < RubyLex # :nodoc: all
|
|
@@ -31,7 +32,7 @@ module GetText
|
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
if @here_header
|
|
34
|
-
s = s.sub(/\A.*?\n/,
|
|
35
|
+
s = s.sub(/\A.*?\n/, "").sub(/^.*\n\Z/, "")
|
|
35
36
|
else
|
|
36
37
|
begin
|
|
37
38
|
s = eval(s)
|
|
@@ -85,7 +86,7 @@ module GetText
|
|
|
85
86
|
# Supports parsing by setting attributes by and by.
|
|
86
87
|
def set_current_attribute(str)
|
|
87
88
|
param = @param_type[@param_number]
|
|
88
|
-
raise ParseError,
|
|
89
|
+
raise ParseError, "no more string parameters expected" unless param
|
|
89
90
|
set_value(param, str)
|
|
90
91
|
end
|
|
91
92
|
|
|
@@ -107,32 +108,116 @@ module GetText
|
|
|
107
108
|
end
|
|
108
109
|
end
|
|
109
110
|
|
|
110
|
-
|
|
111
|
-
|
|
111
|
+
class RubyParser
|
|
112
|
+
ID = ["gettext", "_", "N_", "sgettext", "s_"]
|
|
113
|
+
PLURAL_ID = ["ngettext", "n_", "Nn_", "ns_", "nsgettext"]
|
|
114
|
+
MSGCTXT_ID = ["pgettext", "p_"]
|
|
115
|
+
MSGCTXT_PLURAL_ID = ["npgettext", "np_"]
|
|
112
116
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
class << self
|
|
118
|
+
def target?(file) # :nodoc:
|
|
119
|
+
true # always true, as the default parser.
|
|
120
|
+
end
|
|
117
121
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
# Parses Ruby script located at `path`.
|
|
123
|
+
#
|
|
124
|
+
# This is a short cut method. It equals to `new(path,
|
|
125
|
+
# options).parse`.
|
|
126
|
+
#
|
|
127
|
+
# @param (see #initialize)
|
|
128
|
+
# @option (see #initialize)
|
|
129
|
+
# @return (see #parse)
|
|
130
|
+
# @see #initialize
|
|
131
|
+
# @see #parse
|
|
132
|
+
def parse(path, options={})
|
|
133
|
+
parser = new(path, options)
|
|
134
|
+
parser.parse
|
|
135
|
+
end
|
|
136
|
+
end
|
|
121
137
|
|
|
122
|
-
|
|
123
|
-
|
|
138
|
+
#
|
|
139
|
+
# @example `:comment_tag` option: String tag
|
|
140
|
+
# path = "hello.rb"
|
|
141
|
+
# # content:
|
|
142
|
+
# # # TRANSLATORS: This is a comment to translators.
|
|
143
|
+
# # _("Hello")
|
|
144
|
+
# #
|
|
145
|
+
# # # This is a comment for programmers.
|
|
146
|
+
# # # TRANSLATORS: This is a comment to translators.
|
|
147
|
+
# # # This is also a comment to translators.
|
|
148
|
+
# # _("World")
|
|
149
|
+
# #
|
|
150
|
+
# # # This is a comment for programmers.
|
|
151
|
+
# # # This is also a comment for programmers
|
|
152
|
+
# # # because all lines don't start with "TRANSRATORS:".
|
|
153
|
+
# # _("Bye")
|
|
154
|
+
# options = {:comment_tag => "TRANSLATORS:"}
|
|
155
|
+
# parser = GetText::RubyParser.new(path, options)
|
|
156
|
+
# parser.parse
|
|
157
|
+
# # => [
|
|
158
|
+
# # POEntry<
|
|
159
|
+
# # :msgid => "Hello",
|
|
160
|
+
# # :extracted_comment =>
|
|
161
|
+
# # "TRANSLATORS: This is a comment to translators.",
|
|
162
|
+
# # >,
|
|
163
|
+
# # POEntry<
|
|
164
|
+
# # :msgid => "World",
|
|
165
|
+
# # :extracted_comment =>
|
|
166
|
+
# # "TRANSLATORS: This is a comment to translators.\n" +
|
|
167
|
+
# # "This is also a comment to translators.",
|
|
168
|
+
# # >,
|
|
169
|
+
# # POEntry<
|
|
170
|
+
# # :msgid => "Bye",
|
|
171
|
+
# # :extracted_comment => nil,
|
|
172
|
+
# # >,
|
|
173
|
+
# # ]
|
|
174
|
+
#
|
|
175
|
+
# @example `:comment_tag` option: nil tag
|
|
176
|
+
# path = "hello.rb"
|
|
177
|
+
# # content:
|
|
178
|
+
# # # This is a comment to translators.
|
|
179
|
+
# # # This is also a comment for translators.
|
|
180
|
+
# # _("Hello")
|
|
181
|
+
# options = {:comment_tag => nil}
|
|
182
|
+
# parser = GetText::RubyParser.new(path, options)
|
|
183
|
+
# parser.parse
|
|
184
|
+
# # => [
|
|
185
|
+
# # POEntry<
|
|
186
|
+
# # :msgid => "Hello",
|
|
187
|
+
# # :extracted_comment =>
|
|
188
|
+
# # "This is a comment to translators.\n" +
|
|
189
|
+
# # " This is also a comment for translators.",
|
|
190
|
+
# # >,
|
|
191
|
+
# # ]
|
|
192
|
+
#
|
|
193
|
+
# @param path [String] Ruby script path to be parsed
|
|
194
|
+
# @param options [Hash] Options
|
|
195
|
+
# @option options [String, nil] :comment_tag The tag to
|
|
196
|
+
# detect comments to be extracted. The extracted comments are
|
|
197
|
+
# used to deliver messages to translators from programmers.
|
|
198
|
+
#
|
|
199
|
+
# If the tag is String and a line in a comment start with the
|
|
200
|
+
# tag, the line and the following lines are extracted.
|
|
201
|
+
#
|
|
202
|
+
# If the tag is nil, all comments are extracted.
|
|
203
|
+
def initialize(path, options={})
|
|
204
|
+
@path = path
|
|
205
|
+
@options = options
|
|
206
|
+
end
|
|
124
207
|
|
|
125
|
-
|
|
126
|
-
|
|
208
|
+
# Extracts messages from @path.
|
|
209
|
+
#
|
|
210
|
+
# @return [Array<POEntry>] Extracted messages
|
|
211
|
+
def parse
|
|
212
|
+
source = IO.read(@path)
|
|
127
213
|
|
|
128
|
-
|
|
129
|
-
|
|
214
|
+
encoding = detect_encoding(source) || source.encoding
|
|
215
|
+
source.force_encoding(encoding)
|
|
130
216
|
|
|
131
|
-
|
|
217
|
+
parse_source(source)
|
|
132
218
|
end
|
|
133
219
|
|
|
134
220
|
def detect_encoding(source)
|
|
135
|
-
return nil unless source.respond_to?(:force_encoding)
|
|
136
221
|
binary_source = source.dup.force_encoding("ASCII-8BIT")
|
|
137
222
|
if /\A.*coding\s*[=:]\s*([[:alnum:]\-_]+)/ =~ binary_source
|
|
138
223
|
$1.gsub(/-(?:unix|mac|dos)\z/, "")
|
|
@@ -141,9 +226,9 @@ module GetText
|
|
|
141
226
|
end
|
|
142
227
|
end
|
|
143
228
|
|
|
144
|
-
def
|
|
229
|
+
def parse_source(source)
|
|
145
230
|
po = []
|
|
146
|
-
file = StringIO.new(
|
|
231
|
+
file = StringIO.new(source)
|
|
147
232
|
rl = RubyLexX.new
|
|
148
233
|
rl.set_input(file)
|
|
149
234
|
rl.skip_space = true
|
|
@@ -151,7 +236,7 @@ module GetText
|
|
|
151
236
|
|
|
152
237
|
po_entry = nil
|
|
153
238
|
line_no = nil
|
|
154
|
-
last_comment =
|
|
239
|
+
last_comment = ""
|
|
155
240
|
reset_comment = false
|
|
156
241
|
ignore_next_comma = false
|
|
157
242
|
rl.parse do |tk|
|
|
@@ -160,7 +245,7 @@ module GetText
|
|
|
160
245
|
ignore_next_comma = false
|
|
161
246
|
case tk
|
|
162
247
|
when RubyToken::TkIDENTIFIER, RubyToken::TkCONSTANT
|
|
163
|
-
if store_po_entry(po, po_entry,
|
|
248
|
+
if store_po_entry(po, po_entry, line_no, last_comment)
|
|
164
249
|
last_comment = ""
|
|
165
250
|
end
|
|
166
251
|
if ID.include?(tk.name)
|
|
@@ -186,14 +271,14 @@ module GetText
|
|
|
186
271
|
po_entry.advance_to_next_attribute if po_entry
|
|
187
272
|
end
|
|
188
273
|
else
|
|
189
|
-
if store_po_entry(po, po_entry,
|
|
274
|
+
if store_po_entry(po, po_entry, line_no, last_comment)
|
|
190
275
|
po_entry = nil
|
|
191
276
|
last_comment = ""
|
|
192
277
|
end
|
|
193
278
|
end
|
|
194
279
|
rescue
|
|
195
280
|
$stderr.print "\n\nError"
|
|
196
|
-
$stderr.print " parsing #{path}:#{tk.line_no}\n\t #{lines[tk.line_no - 1]}" if tk
|
|
281
|
+
$stderr.print " parsing #{@path}:#{tk.line_no}\n\t #{source.lines.to_a[tk.line_no - 1]}" if tk
|
|
197
282
|
$stderr.print "\n #{$!.inspect} in\n"
|
|
198
283
|
$stderr.print $!.backtrace.join("\n")
|
|
199
284
|
$stderr.print "\n"
|
|
@@ -204,10 +289,9 @@ module GetText
|
|
|
204
289
|
when RubyToken::TkCOMMENT_WITH_CONTENT
|
|
205
290
|
last_comment = "" if reset_comment
|
|
206
291
|
if last_comment.empty?
|
|
207
|
-
# new comment from programmer to translator?
|
|
208
292
|
comment1 = tk.value.lstrip
|
|
209
|
-
if comment1
|
|
210
|
-
last_comment
|
|
293
|
+
if comment_to_be_extracted?(comment1)
|
|
294
|
+
last_comment << comment1
|
|
211
295
|
end
|
|
212
296
|
else
|
|
213
297
|
last_comment += "\n"
|
|
@@ -222,14 +306,10 @@ module GetText
|
|
|
222
306
|
po
|
|
223
307
|
end
|
|
224
308
|
|
|
225
|
-
def target?(file) # :nodoc:
|
|
226
|
-
true # always true, as the default parser.
|
|
227
|
-
end
|
|
228
|
-
|
|
229
309
|
private
|
|
230
|
-
def store_po_entry(po, po_entry,
|
|
310
|
+
def store_po_entry(po, po_entry, line_no, last_comment) #:nodoc:
|
|
231
311
|
if po_entry && po_entry.msgid
|
|
232
|
-
po_entry.references <<
|
|
312
|
+
po_entry.references << @path + ":" + line_no
|
|
233
313
|
po_entry.add_comment(last_comment) unless last_comment.empty?
|
|
234
314
|
po << po_entry
|
|
235
315
|
true
|
|
@@ -237,5 +317,14 @@ module GetText
|
|
|
237
317
|
false
|
|
238
318
|
end
|
|
239
319
|
end
|
|
320
|
+
|
|
321
|
+
def comment_to_be_extracted?(comment)
|
|
322
|
+
return false unless @options.has_key?(:comment_tag)
|
|
323
|
+
|
|
324
|
+
tag = @options[:comment_tag]
|
|
325
|
+
return true if tag.nil?
|
|
326
|
+
|
|
327
|
+
/\A#{Regexp.escape(tag)}/ === comment
|
|
328
|
+
end
|
|
240
329
|
end
|
|
241
330
|
end
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2012-2013 Kouhei Sutou <kou@clear-code.com>
|
|
4
|
+
#
|
|
5
|
+
# License: Ruby's or LGPL
|
|
6
|
+
#
|
|
7
|
+
# This library is free software: you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This library is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU Lesser General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
|
|
20
|
+
require "rake"
|
|
21
|
+
require "gettext/tools"
|
|
22
|
+
|
|
23
|
+
module GetText
|
|
24
|
+
module Tools
|
|
25
|
+
class Task
|
|
26
|
+
include GetText
|
|
27
|
+
include Rake::DSL
|
|
28
|
+
|
|
29
|
+
attr_accessor :locales, :po_base_directory, :mo_base_directory, :domain
|
|
30
|
+
attr_accessor :namespace_prefix, :files
|
|
31
|
+
# @return [Array<String>] Command line options for extracting messages
|
|
32
|
+
# from sources.
|
|
33
|
+
# @see GetText::Tools::XGetText
|
|
34
|
+
# @see `rxgettext --help`
|
|
35
|
+
attr_reader :xgettext_options
|
|
36
|
+
def initialize(spec)
|
|
37
|
+
@spec = spec
|
|
38
|
+
@locales = []
|
|
39
|
+
@po_base_directory = "po"
|
|
40
|
+
@mo_base_directory = "."
|
|
41
|
+
@files = target_files
|
|
42
|
+
@domain = @spec.name
|
|
43
|
+
@namespace_prefix = nil
|
|
44
|
+
@xgettext_options = []
|
|
45
|
+
yield(self) if block_given?
|
|
46
|
+
@locales = detect_locales if @locales.empty?
|
|
47
|
+
raise("must set locales: #{inspect}") if @locales.empty?
|
|
48
|
+
define
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
def define
|
|
53
|
+
define_file_tasks
|
|
54
|
+
if namespace_prefix
|
|
55
|
+
namespace_recursive namespace_prefix do
|
|
56
|
+
define_named_tasks
|
|
57
|
+
end
|
|
58
|
+
else
|
|
59
|
+
define_named_tasks
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def define_file_tasks
|
|
64
|
+
unless files.empty?
|
|
65
|
+
pot_dependencies = files.dup
|
|
66
|
+
unless File.exist?(po_base_directory)
|
|
67
|
+
directory po_base_directory
|
|
68
|
+
pot_dependencies << po_base_directory
|
|
69
|
+
end
|
|
70
|
+
file pot_file => pot_dependencies do
|
|
71
|
+
command_line = [
|
|
72
|
+
"--package-name", @spec.name,
|
|
73
|
+
"--package-version", @spec.version.to_s,
|
|
74
|
+
"--output", pot_file,
|
|
75
|
+
]
|
|
76
|
+
command_line.concat(@xgettext_options)
|
|
77
|
+
command_line.concat(files)
|
|
78
|
+
GetText::Tools::XGetText.run(*command_line)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
locales.each do |locale|
|
|
83
|
+
_po_file = po_file(locale)
|
|
84
|
+
unless files.empty?
|
|
85
|
+
po_dependencies = [pot_file]
|
|
86
|
+
_po_directory = po_directory(locale)
|
|
87
|
+
unless File.exist?(_po_directory)
|
|
88
|
+
directory _po_directory
|
|
89
|
+
po_dependencies << _po_directory
|
|
90
|
+
end
|
|
91
|
+
file _po_file => po_dependencies do
|
|
92
|
+
if File.exist?(_po_file)
|
|
93
|
+
GetText::Tools::MsgMerge.run(po_file(locale), pot_file,
|
|
94
|
+
"--output", _po_file)
|
|
95
|
+
else
|
|
96
|
+
GetText::Tools::MsgInit.run("--input", pot_file,
|
|
97
|
+
"--output", _po_file,
|
|
98
|
+
"--locale", locale.to_s)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
mo_dependencies = [_po_file]
|
|
104
|
+
_mo_directory = mo_directory(locale)
|
|
105
|
+
unless File.exist?(_mo_directory)
|
|
106
|
+
directory _mo_directory
|
|
107
|
+
mo_dependencies << _mo_directory
|
|
108
|
+
end
|
|
109
|
+
_mo_file = mo_file(locale)
|
|
110
|
+
file _mo_file => mo_dependencies do
|
|
111
|
+
GetText::Tools::MsgFmt.run(_po_file, "--output", _mo_file)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def define_named_tasks
|
|
117
|
+
namespace :gettext do
|
|
118
|
+
namespace :pot do
|
|
119
|
+
desc "Create #{pot_file}"
|
|
120
|
+
task :create => pot_file
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
namespace :po do
|
|
124
|
+
update_tasks = []
|
|
125
|
+
@locales.each do |locale|
|
|
126
|
+
namespace locale do
|
|
127
|
+
desc "Update #{po_file(locale)}"
|
|
128
|
+
task :update => po_file(locale)
|
|
129
|
+
update_tasks << (current_scope + ["update"]).join(":")
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
desc "Update *.po"
|
|
134
|
+
task :update => update_tasks
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
namespace :mo do
|
|
138
|
+
update_tasks = []
|
|
139
|
+
@locales.each do |locale|
|
|
140
|
+
namespace locale do
|
|
141
|
+
desc "Update #{mo_file(locale)}"
|
|
142
|
+
task :update => mo_file(locale)
|
|
143
|
+
update_tasks << (current_scope + ["update"]).join(":")
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
desc "Update *.mo"
|
|
148
|
+
task :update => update_tasks
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
desc "Update *.mo"
|
|
153
|
+
task :gettext => (current_scope + ["gettext", "mo", "update"]).join(":")
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def pot_file
|
|
157
|
+
File.join(po_base_directory, "#{domain}.pot")
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def po_directory(locale)
|
|
161
|
+
File.join(po_base_directory, locale.to_s)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def po_file(locale)
|
|
165
|
+
File.join(po_directory(locale), "#{domain}.po")
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def mo_directory(locale)
|
|
169
|
+
File.join(mo_base_directory, "locale", locale.to_s, "LC_MESSAGES")
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def mo_file(locale)
|
|
173
|
+
File.join(mo_directory(locale), "#{domain}.mo")
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def target_files
|
|
177
|
+
files = @spec.files.find_all do |file|
|
|
178
|
+
/\A\.(?:rb|erb|glade)\z/i =~ File.extname(file)
|
|
179
|
+
end
|
|
180
|
+
files += @spec.executables.collect do |executable|
|
|
181
|
+
"bin/#{executable}"
|
|
182
|
+
end
|
|
183
|
+
files
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def detect_locales
|
|
187
|
+
locales = []
|
|
188
|
+
return locales unless File.exist?(po_base_directory)
|
|
189
|
+
|
|
190
|
+
Dir.open(po_base_directory) do |dir|
|
|
191
|
+
dir.each do |entry|
|
|
192
|
+
next unless /\A[a-z]{2}(?:_[A-Z]{2})?\z/ =~ entry
|
|
193
|
+
next unless File.directory?(File.join(dir.path, entry))
|
|
194
|
+
locales << entry
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
locales
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def current_scope
|
|
201
|
+
scope = Rake.application.current_scope
|
|
202
|
+
if scope.is_a?(Array)
|
|
203
|
+
scope
|
|
204
|
+
else
|
|
205
|
+
if scope.empty?
|
|
206
|
+
[]
|
|
207
|
+
else
|
|
208
|
+
[scope.path]
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def namespace_recursive(namespace_spec, &block)
|
|
214
|
+
first, rest = namespace_spec.split(/:/, 2)
|
|
215
|
+
namespace first do
|
|
216
|
+
if rest.nil?
|
|
217
|
+
block.call
|
|
218
|
+
else
|
|
219
|
+
namespace_recursive(rest, &block)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|