BOM_UTF8 | = | [0xef, 0xbb, 0xbf].pack("c3") |
VERSION | = | "1.93.0" |
Add default locale path.
# File lib/gettext.rb, line 565 565: def add_default_locale_path(path) 566: TextDomain.add_default_locale_path(path) 567: end
Bind a textdomain(%{path}/%{locale}/LC_MESSAGES/%{domainname}.mo) to your program. Normally, the texdomain scope becomes a ruby-script-file. So you need to call this function each ruby-script-files. On the other hand, if you call this function under GetText::Container (gettext/container, gettext/erb, gettext/rails), the textdomain scope becomes a Class/Module.
Note: Don‘t use locale_, charset argument(not in options). They are remained for backward compatibility.
# File lib/gettext.rb, line 85 85: def bindtextdomain(domainname, options = {}, locale_ = nil, charset = nil) 86: opt = {} 87: if options.kind_of? String 88: # For backward compatibility 89: opt = {:path => options, :locale => locale_, :charset => charset} 90: elsif options 91: opt = options 92: end 93: opt[:locale] = opt[:locale] ? Locale::Object.new(opt[:locale]) : Locale.get 94: opt[:charset] = TextDomainManager.output_charset if TextDomainManager.output_charset 95: opt[:locale].charset = opt[:charset] if opt[:charset] 96: Locale.set_current(opt[:locale]) 97: target_key = bound_target 98: manager = @@__textdomainmanagers[target_key] 99: if manager 100: manager.set_locale(opt[:locale]) 101: else 102: manager = TextDomainManager.new(target_key, opt[:locale]) 103: @@__textdomainmanagers[target_key] = manager 104: end 105: manager.add_textdomain(domainname, opt) 106: manager 107: end
Includes GetText module and bind a textdomain to a class.
# File lib/gettext.rb, line 113 113: def bindtextdomain_to(klass, domainname, options = {}) 114: ret = nil 115: klass.module_eval { 116: include GetText 117: ret = bindtextdomain(domainname, options) 118: } 119: ret 120: end
Set the value whether cache messages or not. true to cache messages, otherwise false.
Default is true. If $DEBUG is false, messages are not checked even if this value is true.
# File lib/gettext.rb, line 42 42: def cached=(val) 43: @@__cached = val 44: GetText::TextDomain.check_mo = ! val 45: end
Gets the CGI object. If it is nil, returns new CGI object.
# File lib/gettext/cgi.rb, line 36 36: def cgi 37: Locale.cgi 38: end
Same as GetText.set_cgi.
# File lib/gettext/cgi.rb, line 29 29: def cgi=(cgi_) 30: set_cgi(cgi_) 31: cgi_ 32: end
Clear the cached messages.
# File lib/gettext.rb, line 53 53: def clear_cache 54: @@__cache_msgids = {} 55: @@__cache_nmsgids = {} 56: @@__cache_target_classes = {} 57: @@__cache_bound_target = {} 58: @@__cache_bound_targets = {} 59: end
Creates mo-files using #{po_root}/#{lang}/*.po an put them to #{targetdir}/#{targetpath_rule}/.
This is a convenience function of GetText.rmsgfmt for plural target files.
# File lib/gettext/utils.rb, line 110 110: def create_mofiles(verbose = false, 111: podir = "./po", targetdir = "./data/locale", 112: targetpath_rule = "%s/LC_MESSAGES") 113: 114: modir = File.join(targetdir, targetpath_rule) 115: Dir.glob(File.join(podir, "*/*.po")) do |file| 116: lang, basename = /\/([^\/]+?)\/(.*)\.po/.match(file[podir.size..-1]).to_a[1,2] 117: outdir = modir % lang 118: FileUtils.mkdir_p(outdir) unless File.directory?(outdir) 119: $stderr.print %Q[#{file} -> #{File.join(outdir, "#{basename}.mo")} ... ] if verbose 120: begin 121: rmsgfmt(file, File.join(outdir, "#{basename}.mo")) 122: rescue Exception => e 123: $stderr.puts "Error." if verbose 124: raise e 125: end 126: $stderr.puts "Done." if verbose 127: end 128: end
Show the current textdomain information. This function is for debugging.
# File lib/gettext.rb, line 574 574: def current_textdomain_info(options = {}) 575: opts = {:with_messages => false, :with_paths => false, :out => STDOUT}.merge(options) 576: ret = nil 577: each_textdomain {|textdomain| 578: opts[:out].puts "TextDomain name: \"#{textdomain.name}\"" 579: opts[:out].puts "TextDomain current locale: \"#{textdomain.current_locale}\"" 580: opts[:out].puts "TextDomain current mo filename: \"#{textdomain.current_mo.filename}\"" 581: if opts[:with_paths] 582: opts[:out].puts "TextDomain locale file paths:" 583: textdomain.locale_paths.each do |v| 584: opts[:out].puts " #{v}" 585: end 586: end 587: if opts[:with_messages] 588: opts[:out].puts "The messages in the mo file:" 589: textdomain.current_mo.each{|k, v| 590: opts[:out].puts " \"#{k}\": \"#{v}\"" 591: } 592: end 593: } 594: end
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}") % {:val => "world"}
Because the translator may want to change the position of "world".
# File lib/gettext.rb, line 263 263: def gettext(msgid) 264: sgettext(msgid, nil) 265: end
Gets the current locale.
# File lib/gettext.rb, line 557 557: def locale 558: Locale.current 559: end
Sets the default/current locale. This method haves the strongest infulence. All of the Textdomains are set the new locale.
Note that you shouldn‘t use this for your own Libraries.
# File lib/gettext.rb, line 527 527: def locale=(locale) 528: Locale.default = locale 529: set_locale_all(locale) 530: Locale.default 531: end
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.
# File lib/gettext/utils.rb, line 60 60: def msgmerge(defpo, refpo, app_version) 61: $stderr.print defpo + " " 62: cmd = ENV["MSGMERGE_PATH"] || "msgmerge" 63: 64: cont = "" 65: if FileTest.exist? defpo 66: `#{cmd} --help` 67: unless $? && $?.success? 68: raise _("`%{cmd}' may not be found. \nInstall GNU Gettext then set PATH or MSGMERGE_PATH correctly.") % {:cmd => cmd} 69: end 70: remove_bom(defpo) 71: cont = `#{cmd} #{defpo} #{refpo}` 72: else 73: File.open(refpo) do |io| 74: cont = io.read 75: end 76: end 77: if cont.empty? 78: failed_filename = refpo + "~" 79: FileUtils.cp(refpo, failed_filename) 80: $stderr.puts _("Failed to merge with %{defpo}") % {:defpo => defpo} 81: $stderr.puts _("New .pot was copied to %{failed_filename}") %{:failed_filename => failed_filename} 82: raise _("Check these po/pot-files. It may have syntax errors or something wrong.") 83: else 84: cont.sub!(/(Project-Id-Version\:).*$/, "\\1 #{app_version}\\n\"") 85: File.open(defpo, "w") do |out| 86: out.write(cont) 87: end 88: end 89: self 90: end
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.
# File lib/gettext.rb, line 340 340: def ngettext(arg1, arg2, arg3 = nil) 341: nsgettext(arg1, arg2, arg3, nil) 342: end
The npgettext is similar to the nsgettext function.
e.g.) np_("Special", "An apple", "%{num} Apples", num) == ns_("Special|An apple", "%{num} Apples", num)
# File lib/gettext.rb, line 358 358: def npgettext(msgctxt, arg1, arg2 = nil, arg3 = nil) 359: if arg1.kind_of?(Array) 360: msgid = arg1[0] 361: msgid_ctxt = "#{msgctxt}\004#{msgid}" 362: msgid_plural = arg1[1] 363: opt1 = arg2 364: opt2 = arg3 365: else 366: msgid = arg1 367: msgid_ctxt = "#{msgctxt}\004#{msgid}" 368: msgid_plural = arg2 369: opt1 = arg3 370: opt2 = nil 371: end 372: ret = nsgettext(msgid_ctxt, msgid_plural, opt1, opt2) 373: 374: if ret == msgid_ctxt 375: ret = msgid 376: end 377: ret 378: end
The nsgettext is similar to the ngettext. But if there are no localized text, it returns a last part of msgid separeted "div".
# File lib/gettext.rb, line 411 411: def nsgettext(arg1, arg2, arg3 = "|", arg4 = "|") 412: if arg1.kind_of?(Array) 413: msgid = arg1[0] 414: msgid_plural = arg1[1] 415: n = arg2 416: if arg3 and arg3.kind_of? Numeric 417: raise ArgumentError, _("3rd parmeter is wrong: value = %{number}") % {:number => arg3} 418: end 419: div = arg3 420: else 421: msgid = arg1 422: msgid_plural = arg2 423: n = arg3 424: div = arg4 425: end 426: 427: cached_key = [bound_target, Locale.current, msgid + "\000" + msgid_plural] 428: msgs = nil 429: if @@__cached 430: if @@__cache_nmsgids.has_key?(cached_key) 431: msgs = @@__cache_nmsgids[cached_key] # [msgstr, cond_as_string] 432: end 433: end 434: unless msgs 435: # Use "for"(not "each") to support JRuby 1.1.0. 436: for target in bound_targets(self) 437: manager = @@__textdomainmanagers[target] 438: for textdomain in manager.textdomains 439: msgs = textdomain[1].ngettext_data(msgid, msgid_plural) 440: break if msgs 441: end 442: break if msgs 443: end 444: msgs = [[msgid, msgid_plural], "n != 1"] unless msgs 445: @@__cache_nmsgids[cached_key] = msgs 446: end 447: msgstrs = msgs[0] 448: if div and msgstrs[0] == msgid 449: if index = msgstrs[0].rindex(div) 450: msgstrs[0] = msgstrs[0][(index + 1)..-1] 451: end 452: end 453: plural = eval(msgs[1]) 454: if plural.kind_of?(Numeric) 455: ret = msgstrs[plural] 456: else 457: ret = plural ? msgstrs[1] : msgstrs[0] 458: end 459: ret 460: end
Gets the current output_charset which is set using GetText.set_output_charset.
# File lib/gettext.rb, line 551 551: def output_charset 552: TextDomainManager.output_charset || locale.charset 553: end
Same as GetText.set_output_charset
# File lib/gettext.rb, line 545 545: def output_charset=(charset) 546: TextDomainManager.output_charset = charset 547: end
Translates msgid with msgctxt. This methods is similer with s_().
e.g.) p_("File", "New") == s_("File|New") p_("File", "Open") == s_("File|Open")
See: www.gnu.org/software/autoconf/manual/gettext/Contexts.html
# File lib/gettext.rb, line 320 320: def pgettext(msgctxt, msgid) 321: sgettext(msgctxt + "\004" + msgid, "\004") 322: end
for testing.
# File lib/gettext.rb, line 597 597: def remove_all_textdomains 598: clear_cache 599: @@__textdomainmanagers = {} 600: end
Creates a po-file from targetfiles(ruby-script-files, ActiveRecord, .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.
Note for ActiveRecord, you need to run your database server and configure the config/database.xml correctly before execute this function.
# File lib/gettext/rgettext.rb, line 265 265: def rgettext(targetfiles = nil, out = STDOUT) 266: RGetText.run(targetfiles, out) 267: self 268: 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).
# File lib/gettext/rmsgfmt.rb, line 79 79: def rmsgfmt(targetfile = nil, output_path = nil) 80: RMsgfmt.run(targetfile, output_path) 81: end
Experimental
# File lib/gettext/rmsgmerge.rb, line 489 489: def rmsgmerge(reference = nil, definition = nil, out = STDOUT) 490: RMsgMerge.run(reference, definition, out) 491: end
Sets a CGI object.
# File lib/gettext/cgi.rb, line 22 22: def set_cgi(cgi_) 23: Locale.set_cgi(cgi_) 24: end
Sets the current locale to the current class/module
Notice that you shouldn‘t use this for your own Libraries.
Otherwise, this changes the locale of the current class/module and its ancestors. Default is false.
# File lib/gettext.rb, line 470 470: def set_locale(locale, this_target_only = false) 471: ret = nil 472: if locale 473: if locale.kind_of? Locale::Object 474: ret = locale 475: else 476: ret = Locale::Object.new(locale.to_s) 477: end 478: ret.charset = TextDomainManager.output_charset if TextDomainManager.output_charset 479: Locale.set(ret) 480: else 481: Locale.set(nil) 482: ret = Locale.get 483: end 484: if this_target_only 485: manager = @@__textdomainmanagers[bound_target] 486: if manager 487: manager.set_locale(ret, ! cached?) 488: end 489: else 490: each_textdomain {|textdomain| 491: textdomain.set_locale(ret, ! cached?) 492: } 493: end 494: self 495: end
Sets current locale to the all textdomains.
Note that you shouldn‘t use this for your own Libraries.
# File lib/gettext.rb, line 502 502: def set_locale_all(locale) 503: ret = nil 504: if locale 505: if locale.kind_of? Locale::Object 506: ret = locale 507: else 508: ret = Locale::Object.new(locale.to_s) 509: end 510: else 511: ret = Locale.default 512: end 513: ret.charset = TextDomainManager.output_charset if TextDomainManager.output_charset 514: Locale.set_current(ret) 515: TextDomainManager.each_all {|textdomain| 516: textdomain.set_locale(ret, ! cached?) 517: } 518: self 519: end
Sets charset(String) such as "euc-jp", "sjis", "CP932", "utf-8", … You shouldn‘t use this in your own Libraries.
# File lib/gettext.rb, line 537 537: def set_output_charset(charset) 538: TextDomainManager.output_charset = charset 539: self 540: end
Translates msgid, but if there are no localized text, it returns a last part of msgid separeted "div".
See: www.gnu.org/software/gettext/manual/html_mono/gettext.html#SEC151
# File lib/gettext.rb, line 279 279: def sgettext(msgid, div = '|') 280: cached_key = [bound_target, Locale.current, msgid] 281: if cached? 282: if @@__cache_msgids[cached_key] 283: return @@__cache_msgids[cached_key] 284: end 285: end 286: msg = nil 287: 288: # Use "for"(not "each") to support JRuby 1.1.0. 289: for target in bound_targets(self) 290: manager = @@__textdomainmanagers[target] 291: for textdomain in manager.textdomains 292: msg = textdomain[1].gettext(msgid) 293: break if msg 294: end 295: break if msg 296: end 297: 298: msg ||= msgid 299: if div and msg == msgid 300: if index = msg.rindex(div) 301: msg = msg[(index + 1)..-1] 302: end 303: end 304: @@__cache_msgids[cached_key] = msg 305: end
Binds a existed textdomain to your program. This is the same function with GetText.bindtextdomain but simpler(and faster) than bindtextdomain. Notice that you need to call GetText.bindtextdomain first. If the domainname hasn‘t bound yet, raises GetText::NoboundTextDomainError.
# File lib/gettext.rb, line 128 128: def textdomain(domainname) 129: domain = TextDomainManager.textdomain(domainname) 130: raise NoboundTextDomainError, "#{domainname} is not bound." unless domain 131: target_key = bound_target 132: manager = @@__textdomainmanagers[target_key] 133: unless manager 134: manager = TextDomainManager.new(target_key, Locale.get) 135: @@__textdomainmanagers[target_key] = manager 136: end 137: manager.set_locale(Locale.get) 138: manager.add_textdomain(domainname) 139: manager 140: end
Includes GetText module and bind an exsited textdomain to a class. See textdomain for more detail.
# File lib/gettext.rb, line 146 146: def textdomain_to(klass, domainname) 147: ret = nil 148: klass.module_eval { 149: include GetText 150: ret = textdomain(domainname) 151: } 152: ret 153: end
At first, this creates the #{po_root}/#{domainname}.pot file using GetText.rgettext. Since 2nd time, 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.
(e.g.) GetText.update_pofiles("myapp", Dir.glob("lib/*.rb"), "myapp 1.0.0")
# File lib/gettext/utils.rb, line 145 145: def update_pofiles(textdomain, files, app_version, po_root = "po", refpot = "tmp.pot") 146: rgettext(files, refpot) 147: msgmerge_all(textdomain, app_version, po_root, refpot) 148: File.delete(refpot) 149: end