diff options
Diffstat (limited to 'vendor/gems/gettext-2.1.0/lib/gettext/tools')
8 files changed, 1737 insertions, 0 deletions
diff --git a/vendor/gems/gettext-2.1.0/lib/gettext/tools/parser/erb.rb b/vendor/gems/gettext-2.1.0/lib/gettext/tools/parser/erb.rb new file mode 100644 index 000000000..0aee9d461 --- /dev/null +++ b/vendor/gems/gettext-2.1.0/lib/gettext/tools/parser/erb.rb @@ -0,0 +1,52 @@ +=begin + parser/erb.rb - parser for ERB + + Copyright (C) 2005-2009 Masao Mutoh + + You may redistribute it and/or modify it under the same + license terms as Ruby or LGPL. +=end + +require 'erb' +require 'gettext/tools/parser/ruby' + +module GetText + module ErbParser + extend self + + @config = { + :extnames => ['.rhtml', '.erb'] + } + + # Sets some preferences to parse ERB files. + # * config: a Hash of the config. It can takes some values below: + # * :extnames: An Array of target files extension. Default is [".rhtml"]. + def init(config) + config.each{|k, v| + @config[k] = v + } + end + + def parse(file, targets = []) # :nodoc: + src = ERB.new(IO.readlines(file).join).src + # Remove magic comment prepended by erb in Ruby 1.9. + src.sub!(/\A#.*?coding[:=].*?\n/, '') if src.respond_to?(:encode) + erb = src.split(/$/) + RubyParser.parse_lines(file, erb, targets) + end + + def target?(file) # :nodoc: + @config[:extnames].each do |v| + return true if File.extname(file) == v + end + false + end + end +end + +if __FILE__ == $0 + # ex) ruby glade.rhtml foo.rhtml bar.rhtml + ARGV.each do |file| + p GetText::ErbParser.parse(file) + end +end diff --git a/vendor/gems/gettext-2.1.0/lib/gettext/tools/parser/glade.rb b/vendor/gems/gettext-2.1.0/lib/gettext/tools/parser/glade.rb new file mode 100644 index 000000000..ab77beede --- /dev/null +++ b/vendor/gems/gettext-2.1.0/lib/gettext/tools/parser/glade.rb @@ -0,0 +1,98 @@ +=begin + parser/glade.rb - parser for Glade-2 + + Copyright (C) 2004,2005 Masao Mutoh + + You may redistribute it and/or modify it under the same + license terms as Ruby or LGPL. +=end + +require 'cgi' +require 'gettext' + +module GetText + module GladeParser + extend GetText + extend self + + bindtextdomain("rgettext") + + TARGET1 = /<property.*translatable="yes">(.*)/ + TARGET2 = /(.*)<\/property>/ + + def parse(file, targets = []) # :nodoc: + lines = IO.readlines(file) + parse_lines(file, lines, targets) + end + + #from ary of lines. + def parse_lines(file, lines, targets) # :nodoc: + cnt = 0 + target = false + line_no = 0 + val = nil + + loop do + line = lines.shift + break unless line + + cnt += 1 + if TARGET1 =~ line + line_no = cnt + val = $1 + "\n" + target = true + if TARGET2 =~ $1 + val = $1 + add_target(val, file, line_no, targets) + val = nil + target = false + end + elsif target + if TARGET2 =~ line + val << $1 + add_target(val, file, line_no, targets) + val = nil + target = false + else + val << line + end + end + end + targets + end + + XML_RE = /<\?xml/ + GLADE_RE = /glade-2.0.dtd/ + + def target?(file) # :nodoc: + data = IO.readlines(file) + if XML_RE =~ data[0] and GLADE_RE =~ data[1] + true + else + if File.extname(file) == '.glade' + raise _("`%{file}' is not glade-2.0 format.") % {:file => file} + end + false + end + end + + def add_target(val, file, line_no, targets) # :nodoc: + return unless val.size > 0 + assoc_data = targets.assoc(val) + val = CGI.unescapeHTML(val) + if assoc_data + targets[targets.index(assoc_data)] = assoc_data << "#{file}:#{line_no}" + else + targets << [val.gsub(/\n/, '\n'), "#{file}:#{line_no}"] + end + targets + end + end +end + +if __FILE__ == $0 + # ex) ruby glade.rb foo.glade bar.glade + ARGV.each do |file| + p GetText::GladeParser.parse(file) + end +end diff --git a/vendor/gems/gettext-2.1.0/lib/gettext/tools/parser/ruby.rb b/vendor/gems/gettext-2.1.0/lib/gettext/tools/parser/ruby.rb new file mode 100644 index 000000000..9d16401ce --- /dev/null +++ b/vendor/gems/gettext-2.1.0/lib/gettext/tools/parser/ruby.rb @@ -0,0 +1,226 @@ +#!/usr/bin/ruby +=begin + parser/ruby.rb - parser for ruby script + + Copyright (C) 2003-2009 Masao Mutoh + Copyright (C) 2005 speakillof + Copyright (C) 2001,2002 Yasushi Shoji, Masao Mutoh + + You may redistribute it and/or modify it under the same + license terms as Ruby or LGPL. + +=end + +require 'irb/ruby-lex.rb' +require 'stringio' +require 'gettext/tools/pomessage' + +module GetText + class RubyLexX < RubyLex # :nodoc: all + # Parser#parse resemlbes RubyLex#lex + def parse + until ( (tk = token).kind_of?(RubyToken::TkEND_OF_SCRIPT) && !@continue or tk.nil? ) + s = get_readed + if RubyToken::TkSTRING === tk + def tk.value + @value + end + + def tk.value=(s) + @value = s + end + + if @here_header + s = s.sub(/\A.*?\n/, '').sub(/^.*\n\Z/, '') + else + begin + s = eval(s) + rescue Exception + # Do nothing. + end + end + + tk.value = s + end + + if $DEBUG + if tk.is_a? TkSTRING + $stderr.puts("#{tk}: #{tk.value}") + elsif tk.is_a? TkIDENTIFIER + $stderr.puts("#{tk}: #{tk.name}") + else + $stderr.puts(tk) + end + end + + yield tk + end + return nil + end + + # Original parser does not keep the content of the comments, + # so monkey patching this with new token type and extended + # identify_comment implementation + RubyToken.def_token :TkCOMMENT_WITH_CONTENT, TkVal + + def identify_comment + @ltype = "#" + get_readed # skip the hash sign itself + + while ch = getc + if ch == "\n" + @ltype = nil + ungetc + break + end + end + return Token(TkCOMMENT_WITH_CONTENT, get_readed) + end + + end + + # Extends PoMessage for RubyParser. + # Implements a sort of state machine to assist the parser. + module PoMessageForRubyParser + # Supports parsing by setting attributes by and by. + def set_current_attribute(str) + param = @param_type[@param_number] + raise ParseError, 'no more string parameters expected' unless param + set_value(param, str) + end + + def init_param + @param_number = 0 + self + end + + def advance_to_next_attribute + @param_number += 1 + end + end + class PoMessage + include PoMessageForRubyParser + alias :initialize_old :initialize + def initialize(type) + initialize_old(type) + init_param + end + end + + module RubyParser + extend self + + ID = ['gettext', '_', 'N_', 'sgettext', 's_'] + PLURAL_ID = ['ngettext', 'n_', 'Nn_', 'ns_', 'nsgettext'] + MSGCTXT_ID = ['pgettext', 'p_'] + MSGCTXT_PLURAL_ID = ['npgettext', 'np_'] + + # (Since 2.1.0) the 2nd parameter is deprecated + # (and ignored here). + # And You don't need to keep the pomessages as unique. + + def parse(path, deprecated = []) # :nodoc: + lines = IO.readlines(path) + parse_lines(path, lines, deprecated) + end + + def parse_lines(path, lines, deprecated = []) # :nodoc: + pomessages = deprecated + file = StringIO.new(lines.join + "\n") + rl = RubyLexX.new + rl.set_input(file) + rl.skip_space = true + #rl.readed_auto_clean_up = true + + pomessage = nil + line_no = nil + last_comment = '' + reset_comment = false + rl.parse do |tk| + begin + case tk + when RubyToken::TkIDENTIFIER, RubyToken::TkCONSTANT + store_pomessage(pomessages, pomessage, path, line_no, last_comment) + if ID.include?(tk.name) + pomessage = PoMessage.new(:normal) + elsif PLURAL_ID.include?(tk.name) + pomessage = PoMessage.new(:plural) + elsif MSGCTXT_ID.include?(tk.name) + pomessage = PoMessage.new(:msgctxt) + elsif MSGCTXT_PLURAL_ID.include?(tk.name) + pomessage = PoMessage.new(:msgctxt_plural) + else + pomessage = nil + end + line_no = tk.line_no.to_s + when RubyToken::TkSTRING + pomessage.set_current_attribute tk.value if pomessage + when RubyToken::TkPLUS, RubyToken::TkNL + #do nothing + when RubyToken::TkCOMMA + pomessage.advance_to_next_attribute if pomessage + else + if store_pomessage(pomessages, pomessage, path, line_no, last_comment) + pomessage = nil + end + end + rescue + $stderr.print "\n\nError" + $stderr.print " parsing #{path}:#{tk.line_no}\n\t #{lines[tk.line_no - 1]}" if tk + $stderr.print "\n #{$!.inspect} in\n" + $stderr.print $!.backtrace.join("\n") + $stderr.print "\n" + exit 1 + end + + case tk + when RubyToken::TkCOMMENT_WITH_CONTENT + last_comment = "" if reset_comment + if last_comment.empty? + # new comment from programmer to translator? + comment1 = tk.value.lstrip + if comment1 =~ /^TRANSLATORS\:/ + last_comment = $' + end + else + last_comment += "\n" + last_comment += tk.value + end + reset_comment = false + when RubyToken::TkNL + else + reset_comment = true + end + end + pomessages + end + + def target?(file) # :nodoc: + true # always true, as the default parser. + end + + private + def store_pomessage(pomessages, pomessage, file_name, line_no, last_comment) #:nodoc: + if pomessage && pomessage.msgid + pomessage.sources << file_name + ":" + line_no + pomessage.add_comment(last_comment) unless last_comment.empty? + pomessages << pomessage + true + else + false + end + end + end +end + +if __FILE__ == $0 + require 'pp' + ARGV.each do |path| + pp GetText::RubyParser.parse(path) + end + + #rl = GetText::RubyLexX.new; rl.set_input(ARGF) + #rl.parse do |tk| + #p tk + #end +end diff --git a/vendor/gems/gettext-2.1.0/lib/gettext/tools/pomessage.rb b/vendor/gems/gettext-2.1.0/lib/gettext/tools/pomessage.rb new file mode 100644 index 000000000..b5efe7221 --- /dev/null +++ b/vendor/gems/gettext-2.1.0/lib/gettext/tools/pomessage.rb @@ -0,0 +1,197 @@ +module GetText + class ParseError < StandardError + end + + # Contains data related to the expression or sentence that + # is to be translated. + class PoMessage + PARAMS = { + :normal => [:msgid], + :plural => [:msgid, :msgid_plural], + :msgctxt => [:msgctxt, :msgid], + :msgctxt_plural => [:msgctxt, :msgid, :msgid_plural] + } + + @@max_line_length = 70 + + # Sets the max line length. + def self.max_line_length=(len) + @@max_line_length = len + end + + # Gets the max line length. + def self.max_line_length + @@max_line_length + end + + # Required + attr_accessor :type # :normal, :plural, :msgctxt, :msgctxt_plural + attr_accessor :msgid + # Options + attr_accessor :msgid_plural + attr_accessor :msgctxt + attr_accessor :sources # ["file1:line1", "file2:line2", ...] + attr_accessor :comment + + # Create the object. +type+ should be :normal, :plural, :msgctxt or :msgctxt_plural. + def initialize(type) + @type = type + @sources = [] + @param_type = PARAMS[@type] + end + + # Support for extracted comments. Explanation s. + # http://www.gnu.org/software/gettext/manual/gettext.html#Names + def add_comment(new_comment) + if (new_comment and ! new_comment.empty?) + @comment ||= "" + @comment += new_comment + end + to_s + end + + # Returns a parameter representation suitable for po-files + # and other purposes. + def escaped(param_name) + orig = self.send param_name + orig.gsub(/"/, '\"').gsub(/\r/, '') + end + + # Checks if the other translation target is mergeable with + # the current one. Relevant are msgid and translation context (msgctxt). + def ==(other) + other.msgid == self.msgid && other.msgctxt == self.msgctxt + end + + # Merges two translation targets with the same msgid and returns the merged + # result. If one is declared as plural and the other not, then the one + # with the plural wins. + def merge(other) + return self unless other + raise ParseError, "Translation targets do not match: \n" \ + " self: #{self.inspect}\n other: '#{other.inspect}'" unless self == other + if other.msgid_plural && !self.msgid_plural + res = other + unless (res.sources.include? self.sources[0]) + res.sources += self.sources + res.add_comment(self.comment) + end + else + res = self + unless (res.sources.include? other.sources[0]) + res.sources += other.sources + res.add_comment(other.comment) + end + end + res + end + + # Output the po message for the po-file. + def to_po_str + raise "msgid is nil." unless @msgid + raise "sources is nil." unless @sources + + str = "" + # extracted comments + if comment + comment.split("\n").each do |comment_line| + str << "\n#. #{comment_line.strip}" + end + end + + # references + curr_pos = @@max_line_length + sources.each do |e| + if curr_pos + e.size > @@max_line_length + str << "\n#:" + curr_pos = 3 + else + curr_pos += (e.size + 1) + end + str << " " << e + end + + # msgctxt, msgid, msgstr + str << "\nmsgctxt \"" << msgctxt << "\"" if msgctxt? + str << "\nmsgid \"" << escaped(:msgid) << "\"\n" + if plural? + str << "msgid_plural \"" << escaped(:msgid_plural) << "\"\n" + str << "msgstr[0] \"\"\n" + str << "msgstr[1] \"\"\n" + else + str << "msgstr \"\"\n" + end + str + end + + # Returns true if the type is kind of msgctxt. + # And if this is a kind of msgctxt and msgctxt property + # is nil, then raise an RuntimeException. + def msgctxt? + if [:msgctxt, :msgctxt_plural].include? @type + raise "This PoMessage is a kind of msgctxt but the msgctxt property is nil. msgid: #{msgid}" unless @msgctxt + true + end + end + + # Returns true if the type is kind of plural. + # And if this is a kind of plural and msgid_plural property + # is nil, then raise an RuntimeException. + def plural? + if [:plural, :msgctxt_plural].include? @type + raise "This PoMessage is a kind of plural but the msgid_plural property is nil. msgid: #{msgid}" unless @msgid_plural + true + end + end + + private + + # sets or extends the value of a translation target params like msgid, + # msgctxt etc. + # param is symbol with the name of param + # value - new value + def set_value(param, value) + send "#{param}=", (send(param) || '') + value.gsub(/\n/, '\n') + end + + public + # For backward comatibility. This doesn't support "comment". + # ary = [msgid1, "file1:line1", "file2:line"] + def self.new_from_ary(ary) + ary = ary.dup + msgid = ary.shift + sources = ary + type = :normal + msgctxt = nil + msgid_plural = nil + + if msgid.include? "\004" + msgctxt, msgid = msgid.split(/\004/) + type = :msgctxt + end + if msgid.include? "\000" + ids = msgid.split(/\000/) + msgid = ids[0] + msgid_plural = ids[1] + if type == :msgctxt + type = :msgctxt_plural + else + type = :plural + end + end + ret = self.new(type) + ret.msgid = msgid + ret.sources = sources + ret.msgctxt = msgctxt + ret.msgid_plural = msgid_plural + ret + end + + def [](number) + param = @param_type[number] + raise ParseError, 'no more string parameters expected' unless param + send param + end + end + +end diff --git a/vendor/gems/gettext-2.1.0/lib/gettext/tools/poparser.rb b/vendor/gems/gettext-2.1.0/lib/gettext/tools/poparser.rb new file mode 100644 index 000000000..827a99c2f --- /dev/null +++ b/vendor/gems/gettext-2.1.0/lib/gettext/tools/poparser.rb @@ -0,0 +1,356 @@ +=begin + poparser.rb - Generate a .mo + + Copyright (C) 2003-2009 Masao Mutoh <mutomasa at gmail.com> + + You may redistribute it and/or modify it under the same + license terms as Ruby. +=end + +# +# DO NOT MODIFY!!!! +# This file is automatically generated by Racc 1.4.6 +# from Racc grammer file "". +# + +require 'racc/parser.rb' +module GetText + class PoParser < Racc::Parser + +module_eval(<<'...end poparser.ry/module_eval...', 'poparser.ry', 108) + include GetText + GetText.bindtextdomain("rgettext") + + def unescape(orig) + ret = orig.gsub(/\\n/, "\n") + ret.gsub!(/\\t/, "\t") + ret.gsub!(/\\r/, "\r") + ret.gsub!(/\\"/, "\"") + ret + end + + def parse(str, data, ignore_fuzzy = true) + @comments = [] + @data = data + @fuzzy = false + @msgctxt = "" + $ignore_fuzzy = ignore_fuzzy + + str.strip! + @q = [] + until str.empty? do + case str + when /\A\s+/ + str = $' + when /\Amsgctxt/ + @q.push [:MSGCTXT, $&] + str = $' + when /\Amsgid_plural/ + @q.push [:MSGID_PLURAL, $&] + str = $' + when /\Amsgid/ + @q.push [:MSGID, $&] + str = $' + when /\Amsgstr/ + @q.push [:MSGSTR, $&] + str = $' + when /\A\[(\d+)\]/ + @q.push [:PLURAL_NUM, $1] + str = $' + when /\A\#~(.*)/ + $stderr.print _("Warning: obsolete msgid exists.\n") + $stderr.print " #{$&}\n" + @q.push [:COMMENT, $&] + str = $' + when /\A\#(.*)/ + @q.push [:COMMENT, $&] + str = $' + when /\A\"(.*)\"/ + @q.push [:STRING, $1] + str = $' + else + #c = str[0,1] + #@q.push [:STRING, c] + str = str[1..-1] + end + end + @q.push [false, '$end'] + if $DEBUG + @q.each do |a,b| + puts "[#{a}, #{b}]" + end + end + @yydebug = true if $DEBUG + do_parse + + if @comments.size > 0 + @data.set_comment(:last, @comments.join("\n")) + end + @data + end + + def next_token + @q.shift + end + + def on_message(msgid, msgstr) + if msgstr.size > 0 + @data[msgid] = msgstr + @data.set_comment(msgid, @comments.join("\n")) + end + @comments.clear + @msgctxt = "" + end + + def on_comment(comment) + @fuzzy = true if (/fuzzy/ =~ comment) + @comments << comment + end + + def parse_file(po_file, data, ignore_fuzzy = true) + args = [ po_file ] + # In Ruby 1.9, we must detect proper encoding of a PO file. + if String.instance_methods.include?(:encode) + encoding = detect_file_encoding(po_file) + args << "r:#{encoding}" + end + @po_file = po_file + parse(File.open(*args) {|io| io.read }, data, ignore_fuzzy) + end + + def detect_file_encoding(po_file) + open(po_file, :encoding => 'ASCII-8BIT') do |input| + input.lines.each do |line| + return Encoding.find($1) if %r["Content-Type:.*\scharset=(.*)\\n"] =~ line + end + end + Encoding.default_external + end + private :detect_file_encoding +...end poparser.ry/module_eval... +##### State transition tables begin ### + +racc_action_table = [ + 3, 13, 5, 7, 9, 15, 16, 17, 20, 17, + 13, 17, 13, 13, 11, 17, 23, 20, 13, 17 ] + +racc_action_check = [ + 1, 16, 1, 1, 1, 12, 12, 12, 18, 18, + 7, 14, 15, 9, 3, 19, 20, 21, 23, 25 ] + +racc_action_pointer = [ + nil, 0, nil, 14, nil, nil, nil, 3, nil, 6, + nil, nil, 0, nil, 4, 5, -6, nil, 2, 8, + 8, 11, nil, 11, nil, 12 ] + +racc_action_default = [ + -1, -16, -2, -16, -3, -13, -4, -16, -6, -16, + -7, 26, -16, -15, -5, -16, -16, -14, -16, -8, + -16, -9, -11, -16, -10, -12 ] + +racc_goto_table = [ + 12, 22, 14, 4, 24, 6, 2, 8, 18, 19, + 10, 21, 1, nil, nil, nil, 25 ] + +racc_goto_check = [ + 5, 9, 5, 3, 9, 4, 2, 6, 5, 5, + 7, 8, 1, nil, nil, nil, 5 ] + +racc_goto_pointer = [ + nil, 12, 5, 2, 4, -7, 6, 9, -7, -17 ] + +racc_goto_default = [ + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ] + +racc_reduce_table = [ + 0, 0, :racc_error, + 0, 10, :_reduce_none, + 2, 10, :_reduce_none, + 2, 10, :_reduce_none, + 2, 10, :_reduce_none, + 2, 12, :_reduce_5, + 1, 13, :_reduce_none, + 1, 13, :_reduce_none, + 4, 15, :_reduce_8, + 5, 16, :_reduce_9, + 2, 17, :_reduce_10, + 1, 17, :_reduce_none, + 3, 18, :_reduce_12, + 1, 11, :_reduce_13, + 2, 14, :_reduce_14, + 1, 14, :_reduce_15 ] + +racc_reduce_n = 16 + +racc_shift_n = 26 + +racc_token_table = { + false => 0, + :error => 1, + :COMMENT => 2, + :MSGID => 3, + :MSGCTXT => 4, + :MSGID_PLURAL => 5, + :MSGSTR => 6, + :STRING => 7, + :PLURAL_NUM => 8 } + +racc_nt_base = 9 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ + "$end", + "error", + "COMMENT", + "MSGID", + "MSGCTXT", + "MSGID_PLURAL", + "MSGSTR", + "STRING", + "PLURAL_NUM", + "$start", + "msgfmt", + "comment", + "msgctxt", + "message", + "string_list", + "single_message", + "plural_message", + "msgstr_plural", + "msgstr_plural_line" ] + +Racc_debug_parser = true + +##### State transition tables end ##### + +# reduce 0 omitted + +# reduce 1 omitted + +# reduce 2 omitted + +# reduce 3 omitted + +# reduce 4 omitted + +module_eval(<<'.,.,', 'poparser.ry', 23) + def _reduce_5(val, _values, result) + @msgctxt = unescape(val[1]) + "\004" + + result + end +.,., + +# reduce 6 omitted + +# reduce 7 omitted + +module_eval(<<'.,.,', 'poparser.ry', 35) + def _reduce_8(val, _values, result) + if @fuzzy and $ignore_fuzzy + if val[1] != "" + $stderr.print _("Warning: fuzzy message was ignored.\n") + $stderr.print " #{@po_file}: msgid '#{val[1]}'\n" + else + on_message('', unescape(val[3])) + end + @fuzzy = false + else + on_message(@msgctxt + unescape(val[1]), unescape(val[3])) + end + result = "" + + result + end +.,., + +module_eval(<<'.,.,', 'poparser.ry', 52) + def _reduce_9(val, _values, result) + if @fuzzy and $ignore_fuzzy + if val[1] != "" + $stderr.print _("Warning: fuzzy message was ignored.\n") + $stderr.print "msgid = '#{val[1]}\n" + else + on_message('', unescape(val[3])) + end + @fuzzy = false + else + on_message(@msgctxt + unescape(val[1]) + "\000" + unescape(val[3]), unescape(val[4])) + end + result = "" + + result + end +.,., + +module_eval(<<'.,.,', 'poparser.ry', 70) + def _reduce_10(val, _values, result) + if val[0].size > 0 + result = val[0] + "\000" + val[1] + else + result = "" + end + + result + end +.,., + +# reduce 11 omitted + +module_eval(<<'.,.,', 'poparser.ry', 82) + def _reduce_12(val, _values, result) + result = val[2] + + result + end +.,., + +module_eval(<<'.,.,', 'poparser.ry', 89) + def _reduce_13(val, _values, result) + on_comment(val[0]) + + result + end +.,., + +module_eval(<<'.,.,', 'poparser.ry', 97) + def _reduce_14(val, _values, result) + result = val.delete_if{|item| item == ""}.join + + result + end +.,., + +module_eval(<<'.,.,', 'poparser.ry', 101) + def _reduce_15(val, _values, result) + result = val[0] + + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] +end + + end # class PoParser + end # module GetText + + diff --git a/vendor/gems/gettext-2.1.0/lib/gettext/tools/rgettext.rb b/vendor/gems/gettext-2.1.0/lib/gettext/tools/rgettext.rb new file mode 100644 index 000000000..a66ed2fe0 --- /dev/null +++ b/vendor/gems/gettext-2.1.0/lib/gettext/tools/rgettext.rb @@ -0,0 +1,226 @@ +#! /usr/bin/env ruby +=begin + rgettext.rb - Generate a .pot file. + + Copyright (C) 2003-2009 Masao Mutoh + Copyright (C) 2001,2002 Yasushi Shoji, Masao Mutoh + + Yasushi Shoji <yashi at atmark-techno.com> + Masao Mutoh <mutomasa at gmail.com> + + You may redistribute it and/or modify it under the same + license terms as Ruby or LGPL. +=end + +require 'optparse' +require 'gettext' +require 'rbconfig' + +module GetText + + module RGetText #:nodoc: + extend GetText + + bindtextdomain("rgettext") + + # constant values + VERSION = GetText::VERSION + + @ex_parsers = [] + [ + ["glade.rb", "GladeParser"], + ["erb.rb", "ErbParser"], +# ["ripper.rb", "RipperParser"], + ["ruby.rb", "RubyParser"] # Default parser. + ].each do |f, klass| + begin + require "gettext/tools/parser/#{f}" + @ex_parsers << GetText.const_get(klass) + rescue + $stderr.puts _("'%{klass}' is ignored.") % {:klass => klass} + $stderr.puts $! if $DEBUG + end + end + + module_function + + # Add an option parser + # the option parser module requires to have target?(file) and parser(file, ary) method. + # + # require 'gettext/tools/rgettext' + # module FooParser + # module_function + # def target?(file) + # File.extname(file) == '.foo' # *.foo file only. + # end + # def parse(file, ary) + # : + # return ary # [["msgid1", "foo.rb:200"], ["msgid2", "bar.rb:300", "baz.rb:400"], ...] + # end + # end + # + # GetText::RGetText.add_parser(FooParser) + def add_parser(klass) + @ex_parsers.insert(0, klass) + end + + def generate_pot_header # :nodoc: + time = Time.now.strftime("%Y-%m-%d %H:%M") + off = Time.now.utc_offset + sign = off <= 0 ? '-' : '+' + time += sprintf('%s%02d%02d', sign, *(off.abs / 60).divmod(60)) + + <<TITLE +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\\n" +"POT-Creation-Date: #{time}\\n" +"PO-Revision-Date: #{time}\\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n" +"Language-Team: LANGUAGE <LL@li.org>\\n" +"MIME-Version: 1.0\\n" +"Content-Type: text/plain; charset=UTF-8\\n" +"Content-Transfer-Encoding: 8bit\\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n" +TITLE + end + + def generate_pot(paths) # :nodoc: + pomessages = parse(paths) + str = "" + pomessages.each do |target| + str << target.to_po_str + end + str + end + + def parse(paths) # :nodoc: + pomessages = [] + paths.each do |path| + begin + @ex_parsers.each do |klass| + if klass.target?(path) + if klass.method(:parse).arity == 1 + targets = klass.parse(path) + else + # For backward compatibility. + targets = klass.parse(path, []) + end + + targets.each{|pomessage| + if pomessage.kind_of? Array + pomessage = PoMessage.new_from_ary(pomessage) + end + + # Save the previous target. + existing = pomessages.find_index {|t| t == pomessage} + if existing + pomessage = pomessages[existing].merge(pomessage) + pomessages[existing] = pomessage + else + pomessages << pomessage + end + } + break + end + end + rescue + puts _("Error parsing %{path}") % {:path => path} + raise + end + end + pomessages + end + + def check_options # :nodoc: + output = STDOUT + + opts = OptionParser.new + opts.banner = _("Usage: %s input.rb [-r parser.rb] [-o output.pot]") % $0 + opts.separator("") + opts.separator(_("Extract translatable strings from given input files.")) + opts.separator("") + opts.separator(_("Specific options:")) + + opts.on("-o", "--output=FILE", _("write output to specified file")) do |out| + unless FileTest.exist? out + output = File.new(File.expand_path(out), "w+") + else + $stderr.puts(_("File '%s' already exists.") % out) + exit 1 + end + end + + opts.on("-r", "--require=library", _("require the library before executing rgettext")) do |out| + require out + end + + opts.on("-d", "--debug", _("run in debugging mode")) do + $DEBUG = true + end + + opts.on_tail("--version", _("display version information and exit")) do + puts "#{$0} #{VERSION}" + puts "#{File.join(Config::CONFIG["bindir"], Config::CONFIG["RUBY_INSTALL_NAME"])} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" + exit + end + + opts.parse!(ARGV) + + if ARGV.size == 0 + puts opts.help + exit 1 + end + + [ARGV, output] + end + + def run(paths = nil, out = STDOUT) # :nodoc: + if paths.is_a? String + paths = [paths] + elsif ! paths + paths, out = check_options + end + + if paths.size == 0 + raise ArgumentError, _("no input files") + end + + if out.is_a? String + File.open(File.expand_path(out), "w+") do |file| + file.puts generate_pot_header + file.puts generate_pot(paths) + end + else + out.puts generate_pot_header + out.puts generate_pot(paths) + end + self + end + end + extend self + # Creates a po-file from targetfiles(ruby-script-files, .rhtml files, glade-2 XML files), + # then output the result to out. If no parameter is set, it behaves same as command line tools(rgettet). + # + # This function is a part of GetText.create_pofiles. + # Usually you don't need to call this function directly. + # + # * paths: An Array of po-file paths or nil. + # * out: output IO or output path. + # * Returns: self + def rgettext(paths = nil, out = STDOUT) + RGetText.run(paths, out) + self + end +end + +if $0 == __FILE__ + GetText.rgettext +# GetText.rgettext($0, "tmp.txt") +end diff --git a/vendor/gems/gettext-2.1.0/lib/gettext/tools/rmsgfmt.rb b/vendor/gems/gettext-2.1.0/lib/gettext/tools/rmsgfmt.rb new file mode 100644 index 000000000..2aa428c55 --- /dev/null +++ b/vendor/gems/gettext-2.1.0/lib/gettext/tools/rmsgfmt.rb @@ -0,0 +1,84 @@ +=begin + rmsgfmt.rb - Generate a .mo + + Copyright (C) 2003-2009 Masao Mutoh + + You may redistribute it and/or modify it under the same + license terms as Ruby or LGPL. +=end + +require 'optparse' +require 'fileutils' +require 'gettext' +require 'gettext/tools/poparser' +require 'rbconfig' + +module GetText + + module RMsgfmt #:nodoc: + extend GetText + extend self + + bindtextdomain "rgettext" + + def run(targetfile = nil, output_path = nil) # :nodoc: + unless targetfile + targetfile, output_path = check_options + end + unless targetfile + raise ArgumentError, _("no input files") + end + unless output_path + output_path = "messages.mo" + end + + parser = PoParser.new + data = MOFile.new + + parser.parse_file(targetfile, data) + data.save_to_file(output_path) + end + + def check_options # :nodoc: + output = nil + + opts = OptionParser.new + opts.banner = _("Usage: %s input.po [-o output.mo]" % $0) + opts.separator("") + opts.separator(_("Generate binary message catalog from textual translation description.")) + opts.separator("") + opts.separator(_("Specific options:")) + + opts.on("-o", "--output=FILE", _("write output to specified file")) do |out| + output = out + end + + opts.on_tail("--version", _("display version information and exit")) do + puts "#{$0} #{GetText::VERSION}" + puts "#{File.join(Config::CONFIG["bindir"], Config::CONFIG["RUBY_INSTALL_NAME"])} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" + exit + end + opts.parse!(ARGV) + + if ARGV.size == 0 + puts opts.help + exit 1 + end + + [ARGV[0], output] + end + end + + # Creates a mo-file from a targetfile(po-file), then output the result to out. + # If no parameter is set, it behaves same as command line tools(rmsgfmt). + # * targetfile: An Array of po-files or nil. + # * output_path: output path. + # * Returns: the MOFile object. + def rmsgfmt(targetfile = nil, output_path = nil) + RMsgfmt.run(targetfile, output_path) + end +end + +if $0 == __FILE__ then + GetText.rmsgfmt +end diff --git a/vendor/gems/gettext-2.1.0/lib/gettext/tools/rmsgmerge.rb b/vendor/gems/gettext-2.1.0/lib/gettext/tools/rmsgmerge.rb new file mode 100644 index 000000000..802ba20bc --- /dev/null +++ b/vendor/gems/gettext-2.1.0/lib/gettext/tools/rmsgmerge.rb @@ -0,0 +1,498 @@ +=begin + rmsgmerge.rb - Merge old .po to new .po + + Copyright (C) 2005-2009 Masao Mutoh + Copyright (C) 2005,2006 speakillof + + You may redistribute it and/or modify it under the same + license terms as Ruby or LGPL. +=end + +require 'optparse' +require 'gettext' +require 'gettext/tools/poparser' +require 'rbconfig' + +module GetText + + module RMsgMerge + + class PoData #:nodoc: + + attr_reader :msgids + + def initialize + @msgid2msgstr = {} + @msgid2comment = {} + @msgids = [] + end + + def set_comment(msgid_or_sym, comment) + @msgid2comment[msgid_or_sym] = comment + end + + def msgstr(msgid) + @msgid2msgstr[msgid] + end + + def comment(msgid) + @msgid2comment[msgid] + end + + def [](msgid) + @msgid2msgstr[msgid] + end + + def []=(msgid, msgstr) + # Retain the order + unless @msgid2msgstr[msgid] + @msgids << msgid + end + + @msgid2msgstr[msgid] = msgstr + end + + def each_msgid + arr = @msgids.delete_if{|i| Symbol === i or i == ''} + arr.each do |i| + yield i + end + end + + def msgid?(msgid) + !(Symbol === msgid) and @msgid2msgstr[msgid] and (msgid != '') + end + + # Is it necessary to implement this method? + def search_msgid_fuzzy(msgid, used_msgids) + nil + end + + def nplural + unless @msgid2msgstr[''] + return 0 + else + if /\s*nplural\s*=\s*(\d+)/ =~ @msgid2msgstr[''] + return $1.to_i + else + return 0 + end + + end + end + + def generate_po + str = '' + str << generate_po_header + + self.each_msgid do |id| + str << self.generate_po_entry(id) + end + + str << @msgid2comment[:last] + str + end + + def generate_po_header + str = "" + + str << @msgid2comment[''].strip << "\n" + str << 'msgid ""' << "\n" + str << 'msgstr ""' << "\n" + msgstr = @msgid2msgstr[''].gsub(/"/, '\"').gsub(/\r/, '') + msgstr = msgstr.gsub(/^(.*)$/, '"\1\n"') + str << msgstr + str << "\n" + + str + end + + def generate_po_entry(msgid) + str = "" + str << @msgid2comment[msgid] + if str[-1] != "\n"[0] + str << "\n" + end + + id = msgid.gsub(/"/, '\"').gsub(/\r/, '') + msgstr = @msgid2msgstr[msgid].gsub(/"/, '\"').gsub(/\r/, '') + + if id.include?("\000") + ids = id.split(/\000/) + str << "msgid " << __conv(ids[0]) << "\n" + ids[1..-1].each do |single_id| + str << "msgid_plural " << __conv(single_id) << "\n" + end + + msgstr.split("\000").each_with_index do |m, n| + str << "msgstr[#{n}] " << __conv(m) << "\n" + end + else + str << "msgid " << __conv(id) << "\n" + str << "msgstr " << __conv(msgstr) << "\n" + end + + str << "\n" + str + end + + def __conv(str) + s = '' + + if str.count("\n") > 1 + s << '""' << "\n" + s << str.gsub(/^(.*)$/, '"\1\n"') + else + s << '"' << str.sub("\n", "\\n") << '"' + end + + s.rstrip + end + + end + + class Merger #:nodoc: + + # From GNU gettext source. + # + # Merge the reference with the definition: take the #. and + # #: comments from the reference, take the # comments from + # the definition, take the msgstr from the definition. Add + # this merged entry to the output message list. + DOT_COMMENT_RE = /\A#\./ + SEMICOLON_COMMENT_RE = /\A#\:/ + FUZZY_RE = /\A#\,/ + NOT_SPECIAL_COMMENT_RE = /\A#([^:.,]|\z)/ + + CRLF_RE = /\r?\n/ + POT_DATE_EXTRACT_RE = /POT-Creation-Date:\s*(.*)?\s*$/ + POT_DATE_RE = /POT-Creation-Date:.*?$/ + + def merge(definition, reference) + # deep copy + result = Marshal.load( Marshal.dump(reference) ) + + used = [] + merge_header(result, definition) + + result.each_msgid do |msgid| + if definition.msgid?(msgid) + used << msgid + merge_message(msgid, result, msgid, definition) + elsif other_msgid = definition.search_msgid_fuzzy(msgid, used) + used << other_msgid + merge_fuzzy_message(msgid, result, other_msgid, definition) + elsif msgid.index("\000") and ( reference.msgstr(msgid).gsub("\000", '') == '' ) + # plural + result[msgid] = "\000" * definition.nplural + else + change_reference_comment(msgid, result) + end + end + + ################################################################### + # msgids which are not used in reference are handled as obsolete. # + ################################################################### + last_comment = result.comment(:last) || '' + definition.each_msgid do |msgid| + unless used.include?(msgid) + last_comment << "\n" + last_comment << definition.generate_po_entry(msgid).strip.gsub(/^/, '#. ') + last_comment << "\n" + end + end + result.set_comment(:last, last_comment) + + result + end + + def merge_message(msgid, target, def_msgid, definition) + merge_comment(msgid, target, def_msgid, definition) + + ############################################ + # check mismatch of msgid and msgid_plural # + ############################################ + def_msgstr = definition[def_msgid] + if msgid.index("\000") + if def_msgstr.index("\000") + # OK + target[msgid] = def_msgstr + else + # NG + s = '' + definition.nplural.times { + s << def_msgstr + s << "\000" + } + target[msgid] = s + end + else + if def_msgstr.index("\000") + # NG + target[msgid] = def_msgstr.split("\000")[0] + else + # OK + target[msgid] = def_msgstr + end + end + end + + # for the future + def merge_fuzzy_message(msgid, target, def_msgid, definition) + merge_message(msgid, target, def_msgid, definition) + end + + def merge_comment(msgid, target, def_msgid, definition) + ref_comment = target.comment(msgid) + def_comment = definition.comment(def_msgid) + + normal_comment = [] + dot_comment = [] + semi_comment = [] + is_fuzzy = false + + def_comment.split(CRLF_RE).each do |l| + if NOT_SPECIAL_COMMENT_RE =~ l + normal_comment << l + end + end + + ref_comment.split(CRLF_RE).each do |l| + if DOT_COMMENT_RE =~ l + dot_comment << l + elsif SEMICOLON_COMMENT_RE =~ l + semi_comment << l + elsif FUZZY_RE =~ l + is_fuzzy = true + end + end + + str = format_comment(normal_comment, dot_comment, semi_comment, is_fuzzy) + target.set_comment(msgid, str) + end + + def change_reference_comment(msgid, podata) + normal_comment = [] + dot_comment = [] + semi_comment = [] + is_fuzzy = false + + podata.comment(msgid).split(CRLF_RE).each do |l| + if DOT_COMMENT_RE =~ l + dot_comment << l + elsif SEMICOLON_COMMENT_RE =~ l + semi_comment << l + elsif FUZZY_RE =~ l + is_fuzzy = true + else + normal_comment << l + end + end + + str = format_comment(normal_comment, dot_comment, semi_comment, is_fuzzy) + podata.set_comment(msgid, str) + end + + def format_comment(normal_comment, dot_comment, semi_comment, is_fuzzy) + str = '' + + str << normal_comment.join("\n").gsub(/^#(\s*)/){|sss| + if $1 == "" + "# " + else + sss + end + } + if normal_comment.size > 0 + str << "\n" + end + + str << dot_comment.join("\n").gsub(/^#.(\s*)/){|sss| + if $1 == "" + "#. " + else + sss + end + } + if dot_comment.size > 0 + str << "\n" + end + + str << semi_comment.join("\n").gsub(/^#:\s*/, "#: ") + if semi_comment.size > 0 + str << "\n" + end + + if is_fuzzy + str << "#, fuzzy\n" + end + + str + end + + def merge_header(target, definition) + merge_comment('', target, '', definition) + + msg = target.msgstr('') + def_msg = definition.msgstr('') + if POT_DATE_EXTRACT_RE =~ msg + time = $1 + def_msg = def_msg.sub(POT_DATE_RE, "POT-Creation-Date: #{time}") + end + + target[''] = def_msg + end + + end + + end + +end + +module GetText::RMsgMerge #:nodoc: + + class Config #:nodoc: + + attr_accessor :defpo, :refpot, :output, :fuzzy, :update + + # update mode options + attr_accessor :backup, :suffix + +=begin +The result is written back to def.po. + --backup=CONTROL make a backup of def.po + --suffix=SUFFIX override the usual backup suffix +The version control method may be selected via the --backup option or through +the VERSION_CONTROL environment variable. Here are the values: + none, off never make backups (even if --backup is given) + numbered, t make numbered backups + existing, nil numbered if numbered backups exist, simple otherwise + simple, never always make simple backups +The backup suffix is `~', unless set with --suffix or the SIMPLE_BACKUP_SUFFIX +environment variable. +=end + + def initialize + @output = STDOUT + @fuzzy = nil + @update = nil + @backup = ENV["VERSION_CONTROL"] + @suffix= ENV["SIMPLE_BACKUP_SUFFIX"] || "~" + @input_dirs = ["."] + end + + end + +end + +module GetText + + module RMsgMerge + extend GetText + extend self + + bindtextdomain("rgettext") + + # constant values + VERSION = GetText::VERSION + DATE = %w($Date: 2007/07/21 15:03:05 $)[1] + + def check_options(config) + opts = OptionParser.new + opts.banner = _("Usage: %s def.po ref.pot [-o output.pot]") % $0 + #opts.summary_width = 80 + opts.separator("") + opts.separator(_("Merges two Uniforum style .po files together. The def.po file is an existing PO file with translations. The ref.pot file is the last created PO file with up-to-date source references. ref.pot is generally created by rgettext.")) + opts.separator("") + opts.separator(_("Specific options:")) + + opts.on("-o", "--output=FILE", _("write output to specified file")) do |out| + unless FileTest.exist? out + config.output = out + else + #$stderr.puts(_("File '%s' has already existed.") % out) + #exit 1 + end + end + + #opts.on("-F", "--fuzzy-matching") + + opts.on_tail("--version", _("display version information and exit")) do + puts "#{$0} #{VERSION} (#{DATE})" + puts "#{File.join(::Config::CONFIG["bindir"], ::Config::CONFIG["RUBY_INSTALL_NAME"])} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]" + exit + end + + opts.parse!(ARGV) + + if ARGV.size != 2 + puts opts.help + exit 1 + end + + config.defpo = ARGV[0] + config.refpot = ARGV[1] + end + + def run(reference = nil, definition = nil, out = STDOUT) + config = GetText::RMsgMerge::Config.new + config.refpot = reference + config.defpo = definition + config.output = out + + check_options(config) + + if config.defpo.nil? + raise ArgumentError, _("definition po is not given.") + elsif config.refpot.nil? + raise ArgumentError, _("reference pot is not given.") + end + + parser = PoParser.new + defpo = parser.parse_file(config.defpo, PoData.new, false) + refpot = parser.parse_file(config.refstrrefstr, PoData.new, false) + + m = Merger.new + result = m.merge(defpo, refpot) + p result if $DEBUG + print result.generate_po if $DEBUG + + begin + if out.is_a? String + File.open(File.expand_path(out), "w+") do |file| + file.write(result.generate_po) + end + else + out.puts(result.generate_po) + end + ensure + out.close + end + end + + end + +end + + + +module GetText + + # Experimental + def rmsgmerge(reference = nil, definition = nil, out = STDOUT) + RMsgMerge.run(reference, definition, out) + end + +end + + + +if $0 == __FILE__ then + require 'pp' + + #parser = GetText::RMsgMerge::PoParser.new; + #parser = GetText::PoParser.new; + #pp parser.parse(ARGF.read) + + GetText.rmsgmerge +end |