Module: GetText

Extended by:
GetText
Included in:
GetText, GladeParser, RGetText, RMsgMerge, RMsgfmt
Defined in:
lib/gettext/version.rb,
lib/gettext.rb,
lib/gettext/cgi.rb,
lib/gettext/tools.rb,
lib/gettext/utils.rb,
lib/gettext/mofile.rb,
lib/gettext/poparser.rb,
lib/gettext/class_info.rb,
lib/gettext/parser/erb.rb,
lib/gettext/textdomain.rb,
lib/gettext/locale_path.rb,
lib/gettext/parser/ruby.rb,
lib/gettext/parser/glade.rb,
lib/gettext/tools/rmsgfmt.rb,
lib/gettext/tools/rgettext.rb,
lib/gettext/tools/rmsgmerge.rb,
lib/gettext/tools/rmsgmerge.rb,
lib/gettext/tools/rmsgmerge.rb,
lib/gettext/textdomain_group.rb,
lib/gettext/textdomain_manager.rb

Overview

gettext/textdomain_group - GetText::TextDomainGroup class

Copyright (C) 2009  Masao Mutoh

You may redistribute it and/or modify it under the same
license terms as Ruby.

Defined Under Namespace

Modules: ClassInfo, ErbParser, GladeParser, RGetText, RMsgMerge, RMsgfmt, RubyParser, TextDomainManager Classes: LocalePath, MOFile, NoboundTextDomainError, PoParser, TextDomain, TextDomainGroup

Constant Summary collapse

BOM_UTF8 =
[0xef, 0xbb, 0xbf].pack("c3")
VERSION =
"2.0.1"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(mod) ⇒ Object

:nodoc:



46
47
48
# File 'lib/gettext.rb', line 46

def self.included(mod)  #:nodoc:
  mod.extend self
end

Instance Method Details

#bindtextdomain(domainname, *options) ⇒ Object

bindtextdomain(domainname, options = {})

Bind a textdomain(%path/%#locale/LC_MESSAGES/%domainname.mo) to your program. Normally, the texdomain scope becomes the class/module(and parent classes/included modules).

  • domainname: the textdomain name.

  • options: options as an Hash.

    • :path - the path to the mo-files. When the value is nil, it will search default paths such as /usr/share/locale, /usr/local/share/locale)

    • :supported_language_tags - an Array of the supported language tags for this textdomain.

    • :output_charset - The output charset. Same with GetText.set_output_charset. Usually, L10n library doesn’t use this option. Application may use this once.

  • Returns: the GetText::TextDomainManager.



66
67
68
# File 'lib/gettext.rb', line 66

def bindtextdomain(domainname, *options)
  bindtextdomain_to(self, domainname, *options)
end

#bindtextdomain_to(klass, domainname, *options) ⇒ Object

Includes GetText module and bind a textdomain to a class.

  • klass: the target ruby class.

  • domainname: the textdomain name.

  • options: options as an Hash. See GetText.bindtextdomain.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/gettext.rb', line 74

def bindtextdomain_to(klass, domainname, *options) 
  if options[0].kind_of? Hash
    opts = options[0]
  else
    # for backward compatibility.
    opts = {}
    opts[:path] = options[0] if options[0]
    opts[:output_charset] = options[2] if options[2]
  end
  unless (klass.kind_of? GetText or klass.include? GetText)
    klass.__send__(:include, GetText)
  end
  TextDomainManager.bind_to(klass, domainname, opts)
end

#cgiObject

Gets the CGI object. If it is nil, returns new CGI object.

  • Returns: the CGI object



36
37
38
# File 'lib/gettext/cgi.rb', line 36

def cgi
  Locale.cgi
end

#cgi=(cgi_) ⇒ Object

Same as GetText.set_cgi.

  • cgi_: CGI object

  • Returns: cgi_



29
30
31
32
# File 'lib/gettext/cgi.rb', line 29

def cgi=(cgi_)
  set_cgi(cgi_)
  cgi_
end

#create_mofiles(verbose = false, podir = "./po", targetdir = "./data/locale", targetpath_rule = "%s/LC_MESSAGES") ⇒ Object

Deprecated. Use gettext/tools instead.



89
90
91
92
93
94
95
96
97
98
99
# File 'lib/gettext/tools.rb', line 89

def create_mofiles(options = {})
  options = {:po_root => "./po"}.merge(options)

  Dir.glob(File.join(options[:po_root], "*/*.po")) do |po_file|
    mo_file = mo_file_from_po_file(po_file,options)
    $stderr.print %Q[#{po_file} -> #{mo_file} ... ] if options[:verbose]
    FileUtils.mkdir_p(File.dirname(mo_file))
    rmsgfmt(po_file, mo_file)
    $stderr.puts "Done." if options[:verbose]
  end
end

#create_mofiles_orgObject

Creates mo-files using #po_root/#lang/*.po an put them to #targetdir/#targetdir_rule/.

This is a convenience function of GetText.rmsgfmt for multiple target files.

  • options: options as a Hash.

    • verbose: true if verbose mode, otherwise false

    • po_root: the root directory of po-files.

    • mo_root: the target root directory where the mo-files are stored.

    • mo_path_rule: the target directory for each mo-files.



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/gettext/utils.rb', line 16

def create_mofiles(options = {})
  options = {:po_root => "./po"}.merge(options)

  Dir.glob(File.join(options[:po_root], "*/*.po")) do |po_file|
    mo_file = mo_file_from_po_file(po_file,options)
    $stderr.print %Q[#{po_file} -> #{mo_file} ... ] if options[:verbose]
    FileUtils.mkdir_p(File.dirname(mo_file))
    rmsgfmt(po_file, mo_file)
    $stderr.puts "Done." if options[:verbose]
  end
end

#gettext(msgid) ⇒ Object Also known as: _

call-seq:

gettext(msgid)
_(msgid)

Translates msgid and return the message. This doesn’t make a copy of the message.

You need to use String#dup if you want to modify the return value with destructive functions.

(e.g.1) _(“Hello ”).dup << “world”

But e.g.1 should be rewrite to:

(e.g.2) _(“Hello %val”) % => “world”

Because the translator may want to change the position of “world”.

  • msgid: the message id.

  • Returns: localized text by msgid. If there are not binded mo-file, it will return msgid.



130
131
132
# File 'lib/gettext.rb', line 130

def gettext(msgid)
  TextDomainManager.translate_singluar_message(self, msgid)
end

#localeObject



282
283
284
# File 'lib/gettext.rb', line 282

def locale
  Locale.current[0]
end

#msgmerge(defpo, refpo, app_version, options = {}) ⇒ Object

Merges two Uniforum style .po files together.

Note This function requires “msgmerge” tool included in GNU GetText. So you need to install GNU GetText.

The def.po file is an existing PO file with translations which will be taken over to the newly created file as long as they still match; comments will be preserved, but extracted comments and file positions will be discarded.

The ref.pot file is the last created PO file with up-to-date source references but old translations, or a PO Template file (generally created by rgettext); any translations or comments in the file will be discarded, however dot comments and file positions will be preserved. Where an exact match cannot be found, fuzzy matching is used to produce better results.

Usually you don’t need to call this function directly. Use GetText.update_pofiles instead.

  • defpo: a po-file. translations referring to old sources

  • refpo: a po-file. references to new sources

  • app_version: the application information which appears “Project-Id-Version: #app_version” in the pot/po-files.

  • Returns: self



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/gettext/tools.rb', line 57

def msgmerge(defpo, refpo, app_version, options={})
  verbose = options.delete(:verbose)
  puts "msgmerge called" if verbose
  $stderr.print defpo + " "

  content = merge_po_files(defpo,refpo,options.delete(:msgmerge),verbose)
  
  if content.empty?
    # report failure
    failed_filename = refpo + "~"
    FileUtils.cp(refpo, failed_filename)
    $stderr.puts _("Failed to merge with %{defpo}") % {:defpo => defpo}
    $stderr.puts _("New .pot was copied to %{failed_filename}") %{:failed_filename => failed_filename}
    raise _("Check these po/pot-files. It may have syntax errors or something wrong.")
  else
    # update version and save merged data
    content.sub!(/(Project-Id-Version\:).*$/, "\\1 #{app_version}\\n\"")
    File.open(defpo, "w") {|f|f.write(content)}
  end
  
  self
end

#N_(msgid) ⇒ Object

makes dynamic translation messages readable for the gettext parser. _(fruit) cannot be understood by the gettext parser. To help the parser find all your translations, you can add fruit = N_("Apple") which does not translate, but tells the parser: “Apple” needs translation.

  • msgid: the message id.

  • Returns: msgid.



247
248
249
# File 'lib/gettext.rb', line 247

def N_(msgid)
  msgid
end

#ngettext(msgid, msgid_plural, n = nil) ⇒ Object Also known as: n_

call-seq:

ngettext(msgid, msgid_plural, n)
ngettext(msgids, n)  # msgids = [msgid, msgid_plural]
n_(msgid, msgid_plural, n)
n_(msgids, n)  # msgids = [msgid, msgid_plural]

The ngettext is similar to the gettext function as it finds the message catalogs in the same way. But it takes two extra arguments for plural form.

  • msgid: the singular form.

  • msgid_plural: the plural form.

  • n: a number used to determine the plural form.

  • Returns: the localized text which key is msgid_plural if n is plural(follow plural-rule) or msgid. “plural-rule” is defined in po-file.



182
183
184
# File 'lib/gettext.rb', line 182

def ngettext(msgid, msgid_plural, n = nil)
  TextDomainManager.translate_plural_message(self, msgid, msgid_plural, n)
end

#Nn_(msgid, msgid_plural) ⇒ Object

This is same function as N_ but for ngettext.

  • msgid: the message id.

  • msgid_plural: the plural message id.

  • Returns: msgid.



255
256
257
# File 'lib/gettext.rb', line 255

def Nn_(msgid, msgid_plural)
  [msgid, msgid_plural]
end

#npgettext(msgctxt, msgids, arg2 = nil, arg3 = nil) ⇒ Object Also known as: np_

call-seq:

npgettext(msgctxt, msgid, msgid_plural, n)
npgettext(msgctxt, msgids, n)  # msgids = [msgid, msgid_plural]
np_(msgctxt, msgid, msgid_plural, n)
np_(msgctxt, msgids, n)  # msgids = [msgid, msgid_plural]

The npgettext is similar to the nsgettext function.

e.g.) np_("Special", "An apple", "%{num} Apples", num) == ns_("Special|An apple", "%{num} Apples", num)
  • msgctxt: the message context.

  • msgid: the singular form.

  • msgid_plural: the plural form.

  • n: a number used to determine the plural form.

  • Returns: the localized text which key is msgid_plural if n is plural(follow plural-rule) or msgid. “plural-rule” is defined in po-file.



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/gettext.rb', line 219

def npgettext(msgctxt, msgids, arg2 = nil, arg3 = nil)
   if msgids.kind_of?(Array)
    msgid = msgids[0]
    msgid_ctxt = "#{msgctxt}\004#{msgid}"
    msgid_plural = msgids[1]
    opt1 = arg2
    opt2 = arg3
  else
    msgid = msgids
    msgid_ctxt = "#{msgctxt}\004#{msgid}"
    msgid_plural = arg2
    opt1 = arg3
    opt2 = nil
  end
  
  msgstr = TextDomainManager.translate_plural_message(self, msgid_ctxt, msgid_plural, opt1, opt2)
  if msgstr == msgid_ctxt
    msgid
  else
    msgstr
  end
end

#nsgettext(msgid, msgid_plural, n = "|", seperator = "|") ⇒ Object Also known as: ns_

call-seq:

nsgettext(msgid, msgid_plural, n, div = "|")
nsgettext(msgids, n, div = "|")  # msgids = [msgid, msgid_plural]
ns_(msgid, msgid_plural, n, div = "|")
ns_(msgids, n, div = "|")  # msgids = [msgid, msgid_plural]

The nsgettext is similar to the ngettext. But if there are no localized text, it returns a last part of msgid separeted “div”.

  • msgid: the singular form with “div”. (e.g. “Special|An apple”)

  • msgid_plural: the plural form. (e.g. “%num Apples”)

  • n: a number used to determine the plural form.

  • Returns: the localized text which key is msgid_plural if n is plural(follow plural-rule) or msgid. “plural-rule” is defined in po-file.



201
202
203
# File 'lib/gettext.rb', line 201

def nsgettext(msgid, msgid_plural, n="|", seperator = "|")
  TextDomainManager.translate_plural_message(self, msgid, msgid_plural, n, seperator)
end

#output_charsetObject

Gets the current output_charset which is set using GetText.set_output_charset.

  • Returns: output_charset.



270
271
272
# File 'lib/gettext.rb', line 270

def output_charset
  TextDomainManager.output_charset
end

#pgettext(msgctxt, msgid) ⇒ Object Also known as: p_

call-seq:

pgettext(msgctxt, msgid)
p_(msgctxt, msgid)

Translates msgid with msgctxt. This methods is similer with s_().

e.g.) p_("File", "New")   == s_("File|New")
      p_("File", "Open")  == s_("File|Open")
  • msgctxt: the message context.

  • msgid: the message id.

  • Returns: the localized text by msgid. If there are no localized text, it returns msgid.

See: www.gnu.org/software/autoconf/manual/gettext/Contexts.html



164
165
166
# File 'lib/gettext.rb', line 164

def pgettext(msgctxt, msgid)
  TextDomainManager.translate_singluar_message(self, "#{msgctxt}\004#{msgid}", "\004")
end

#remove_bom(path) ⇒ Object

Currently, GNU msgmerge doesn’t accept BOM. This mesthod remove the UTF-8 BOM from the po-file.



29
30
31
32
33
34
35
# File 'lib/gettext/tools.rb', line 29

def remove_bom(path)  #:nodoc:
  bom = IO.read(path, 3)
  if bom == BOM_UTF8
    data = IO.read(path)[3..-1]
    File.open(path, "w") {|f| f.write(data)}
  end
end

#rgettext(targetfiles = nil, out = STDOUT) ⇒ Object

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.

  • targetfiles: An Array of po-files or nil.

  • out: output IO or output path.

  • Returns: self



262
263
264
265
# File 'lib/gettext/tools/rgettext.rb', line 262

def rgettext(targetfiles = nil, out = STDOUT)
  RGetText.run(targetfiles, out)
  self
end

#rmsgfmt(targetfile = nil, output_path = nil) ⇒ Object

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.



77
78
79
# File 'lib/gettext/tools/rmsgfmt.rb', line 77

def rmsgfmt(targetfile = nil, output_path = nil)
  RMsgfmt.run(targetfile, output_path)
end

#rmsgmerge(reference = nil, definition = nil, out = STDOUT) ⇒ Object

Experimental



486
487
488
# File 'lib/gettext/tools/rmsgmerge.rb', line 486

def rmsgmerge(reference = nil, definition = nil, out = STDOUT)
  RMsgMerge.run(reference, definition, out)
end

#set_cgi(cgi_) ⇒ Object

Sets a CGI object.

  • cgi_: CGI object

  • Returns: self



22
23
24
# File 'lib/gettext/cgi.rb', line 22

def set_cgi(cgi_)
  Locale.set_cgi(cgi_)
end

#set_current_locale(lang) ⇒ Object Also known as: current_locale=



278
279
280
# File 'lib/gettext.rb', line 278

def set_current_locale(lang)
  Locale.current = lang
end

#set_locale(lang) ⇒ Object Also known as: locale=, set_locale_all, setlocale



274
275
276
# File 'lib/gettext.rb', line 274

def set_locale(lang)
  Locale.default = lang
end

#set_output_charset(charset) ⇒ Object Also known as: output_charset=

Sets charset(String) such as “euc-jp”, “sjis”, “CP932”, “utf-8”, … You shouldn’t use this in your own Libraries.

  • charset: an output_charset

  • Returns: self



263
264
265
266
# File 'lib/gettext.rb', line 263

def set_output_charset(charset)
  TextDomainManager.output_charset = charset
  self
end

#sgettext(msgid, seperator = "|") ⇒ Object Also known as: s_

call-seq:

sgettext(msgid, div = '|')
s_(msgid, div = '|')

Translates msgid, but if there are no localized text, it returns a last part of msgid separeted “div”.

  • msgid: the message id.

  • separator: separator or nil for no seperation.

  • Returns: the localized text by msgid. If there are no localized text, it returns a last part of the msgid separeted by “seperator”. Movie|Location -> Location

See: www.gnu.org/software/gettext/manual/html_mono/gettext.html#SEC151



147
148
149
# File 'lib/gettext.rb', line 147

def sgettext(msgid, seperator = "|")
  TextDomainManager.translate_singluar_message(self, msgid, seperator)
end

#textdomain(domainname) ⇒ Object

Binds a existed textdomain to your program. This is the same function with GetText.bindtextdomain but simpler(and faster) than bindtextdomain. Note that you need to call GetText.bindtextdomain first. If the domainname hasn’t bound yet, raises GetText::NoboundTextDomainError.

  • domainname: a textdomain name.

  • Returns: the GetText::TextDomainManager.



95
96
97
# File 'lib/gettext.rb', line 95

def textdomain(domainname) #:nodoc:
  textdomain_to(self, domainname)
end

#textdomain_to(klass, domainname) ⇒ Object

Includes GetText module and bind an exsited textdomain to a class. See textdomain for more detail.

  • klass: the target ruby class.

  • domainname: the textdomain name.



104
105
106
107
108
# File 'lib/gettext.rb', line 104

def textdomain_to(klass, domainname)  #:nodoc:
  domain = TextDomainManager.textdomain_pool(domainname)
  raise NoboundTextDomainError.new(domainname) unless domain
  bindtextdomain_to(klass, domainname)
end

#update_pofiles(textdomain, files, app_version, po_root = "po", refpot = "tmp.pot") ⇒ Object

Deprecated. Use gettext/tools instead.



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/gettext/tools.rb', line 121

def update_pofiles(textdomain, files, app_version, options = {})
  puts options.inspect if options[:verbose]

  #write found messages to tmp.pot
  temp_pot = "tmp.pot"
  rgettext(files, temp_pot)

  #merge tmp.pot and existing pot
  po_root = options.delete(:po_root) || "po"
  FileUtils.mkdir_p(po_root)
  msgmerge("#{po_root}/#{textdomain}.pot", temp_pot, app_version, options.dup)

  #update local po-files
  only_one_language = options.delete(:lang)
  if only_one_language
    msgmerge("#{po_root}/#{only_one_language}/#{textdomain}.po", temp_pot, app_version, options.dup)
  else
    Dir.glob("#{po_root}/*/#{textdomain}.po") do |po_file|
      msgmerge(po_file, temp_pot, app_version, options.dup)
    end
  end

  File.delete(temp_pot)
end

#update_pofiles_orgObject

At first, this creates the #po_root/#domainname.pot file using GetText.rgettext. In the second step, this updates(merges) the #po_root/#domainname.pot and all of the #po_root/#lang/#domainname.po files under “po_root” using “msgmerge”.

Note “msgmerge” tool is included in GNU GetText. So you need to install GNU GetText.

See <HOWTO maintain po/mo files(www.yotabanana.com/hiki/ruby-gettext-howto-manage.html)> for more detals.

  • domainname: the textdomain name.

  • targetfiles: An Array of target files, that should be parsed for messages (See GetText.rgettext for more details).

  • app_version: the application information which appears “Project-Id-Version: #app_version” in the pot/po-files.

  • options: a hash with following possible settings

    :lang    - update files only for one language - the language specified by this option
    :po_root - the root directory of po-files
    :msgmerge - an array with the options, passed through to the gnu msgmerge tool
                symbols are automatically translated to options with dashes,
                example: [:no_wrap, :no_fuzzy_matching, :sort_output] translated to '--no-fuzzy-matching --sort-output'
    :verbose - true to show verbose messages. default is false.
    

Example: GetText.update_pofiles(“myapp”, Dir.glob(“lib/*.rb”), “myapp 1.0.0”, :verbose => true)



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/gettext/utils.rb', line 17

def update_pofiles(textdomain, files, app_version, options = {})
  puts options.inspect if options[:verbose]

  #write found messages to tmp.pot
  temp_pot = "tmp.pot"
  rgettext(files, temp_pot)

  #merge tmp.pot and existing pot
  po_root = options.delete(:po_root) || "po"
  FileUtils.mkdir_p(po_root)
  msgmerge("#{po_root}/#{textdomain}.pot", temp_pot, app_version, options.dup)

  #update local po-files
  only_one_language = options.delete(:lang)
  if only_one_language
    msgmerge("#{po_root}/#{only_one_language}/#{textdomain}.po", temp_pot, app_version, options.dup)
  else
    Dir.glob("#{po_root}/*/#{textdomain}.po") do |po_file|
      msgmerge(po_file, temp_pot, app_version, options.dup)
    end
  end

  File.delete(temp_pot)
end