1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 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
|