grosser-gettext 2.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/ChangeLog +2014 -0
- data/README.rdoc +172 -0
- data/Rakefile +192 -0
- data/bin/rgettext +24 -0
- data/bin/rmsgfmt +24 -0
- data/bin/rmsgmerge +24 -0
- data/gettext.gemspec +39 -0
- data/lib/gettext.rb +263 -0
- data/lib/gettext/cgi.rb +40 -0
- data/lib/gettext/class_info.rb +55 -0
- data/lib/gettext/core_ext/iconv.rb +109 -0
- data/lib/gettext/core_ext/string.rb +63 -0
- data/lib/gettext/mofile.rb +320 -0
- data/lib/gettext/parser/erb.rb +50 -0
- data/lib/gettext/parser/glade.rb +99 -0
- data/lib/gettext/parser/ruby.rb +170 -0
- data/lib/gettext/poparser.rb +332 -0
- data/lib/gettext/textdomain.rb +225 -0
- data/lib/gettext/textdomain_manager.rb +218 -0
- data/lib/gettext/tools.rb +177 -0
- data/lib/gettext/tools/rgettext.rb +275 -0
- data/lib/gettext/tools/rmsgfmt.rb +84 -0
- data/lib/gettext/tools/rmsgmerge.rb +505 -0
- data/lib/gettext/utils.rb +39 -0
- data/lib/gettext/version.rb +12 -0
- data/po/bg/rgettext.po +150 -0
- data/po/bs/rgettext.po +151 -0
- data/po/ca/rgettext.po +149 -0
- data/po/cs/rgettext.po +152 -0
- data/po/de/#rails.po# +175 -0
- data/po/de/rgettext.po +157 -0
- data/po/el/rgettext.po +148 -0
- data/po/eo/rgettext.po +149 -0
- data/po/es/rgettext.po +150 -0
- data/po/et/rgettext.po +147 -0
- data/po/fr/rgettext.po +153 -0
- data/po/hr/rgettext.po +151 -0
- data/po/hu/rgettext.po +149 -0
- data/po/it/rgettext.po +150 -0
- data/po/ja/rails.po.old +150 -0
- data/po/ja/rgettext.po +149 -0
- data/po/ko/rgettext.po +149 -0
- data/po/lv/rgettext.po +150 -0
- data/po/nb/rgettext.po +151 -0
- data/po/nl/rgettext.po +150 -0
- data/po/pt_BR/rgettext.po +152 -0
- data/po/rgettext.pot +141 -0
- data/po/ru/rgettext.po +151 -0
- data/po/sr/rgettext.po +150 -0
- data/po/sv/rgettext.po +143 -0
- data/po/ua/rgettext.po +155 -0
- data/po/vi/rgettext.po +148 -0
- data/po/zh/rgettext.po +149 -0
- data/po/zh_TW/rgettext.po +148 -0
- data/samples/README +16 -0
- data/samples/cgi/README +43 -0
- data/samples/cgi/Rakefile +27 -0
- data/samples/cgi/cookie.cgi +64 -0
- data/samples/cgi/gettext.css +116 -0
- data/samples/cgi/helloerb.rhtml +28 -0
- data/samples/cgi/helloerb1.cgi +58 -0
- data/samples/cgi/helloerb2.cgi +51 -0
- data/samples/cgi/hellolib.rb +20 -0
- data/samples/cgi/http.rb +51 -0
- data/samples/cgi/index.cgi +111 -0
- data/samples/cgi/other.rhtml +20 -0
- data/samples/cgi/po/bg/helloerb1.po +59 -0
- data/samples/cgi/po/bg/helloerb2.po +51 -0
- data/samples/cgi/po/bg/hellolib.po +23 -0
- data/samples/cgi/po/bg/main.po +83 -0
- data/samples/cgi/po/bs/helloerb1.po +59 -0
- data/samples/cgi/po/bs/helloerb2.po +51 -0
- data/samples/cgi/po/bs/hellolib.po +23 -0
- data/samples/cgi/po/bs/main.po +83 -0
- data/samples/cgi/po/ca/helloerb1.po +59 -0
- data/samples/cgi/po/ca/helloerb2.po +51 -0
- data/samples/cgi/po/ca/hellolib.po +23 -0
- data/samples/cgi/po/ca/main.po +83 -0
- data/samples/cgi/po/cs/helloerb1.po +61 -0
- data/samples/cgi/po/cs/helloerb2.po +52 -0
- data/samples/cgi/po/cs/hellolib.po +25 -0
- data/samples/cgi/po/cs/main.po +85 -0
- data/samples/cgi/po/de/helloerb1.po +61 -0
- data/samples/cgi/po/de/helloerb2.po +52 -0
- data/samples/cgi/po/de/hellolib.po +24 -0
- data/samples/cgi/po/de/main.po +86 -0
- data/samples/cgi/po/el/helloerb1.po +60 -0
- data/samples/cgi/po/el/helloerb2.po +51 -0
- data/samples/cgi/po/el/hellolib.po +23 -0
- data/samples/cgi/po/el/main.po +84 -0
- data/samples/cgi/po/eo/helloerb1.po +60 -0
- data/samples/cgi/po/eo/helloerb2.po +52 -0
- data/samples/cgi/po/eo/hellolib.po +24 -0
- data/samples/cgi/po/eo/main.po +84 -0
- data/samples/cgi/po/es/helloerb1.po +59 -0
- data/samples/cgi/po/es/helloerb2.po +50 -0
- data/samples/cgi/po/es/hellolib.po +22 -0
- data/samples/cgi/po/es/main.po +83 -0
- data/samples/cgi/po/fr/helloerb1.po +59 -0
- data/samples/cgi/po/fr/helloerb2.po +51 -0
- data/samples/cgi/po/fr/hellolib.po +22 -0
- data/samples/cgi/po/fr/main.po +85 -0
- data/samples/cgi/po/helloerb1.pot +60 -0
- data/samples/cgi/po/helloerb2.pot +52 -0
- data/samples/cgi/po/hellolib.pot +24 -0
- data/samples/cgi/po/hr/helloerb1.po +59 -0
- data/samples/cgi/po/hr/helloerb2.po +51 -0
- data/samples/cgi/po/hr/hellolib.po +23 -0
- data/samples/cgi/po/hr/main.po +83 -0
- data/samples/cgi/po/hu/helloerb1.po +59 -0
- data/samples/cgi/po/hu/helloerb2.po +51 -0
- data/samples/cgi/po/hu/hellolib.po +23 -0
- data/samples/cgi/po/hu/main.po +82 -0
- data/samples/cgi/po/it/helloerb1.po +60 -0
- data/samples/cgi/po/it/helloerb2.po +52 -0
- data/samples/cgi/po/it/hellolib.po +24 -0
- data/samples/cgi/po/it/main.po +84 -0
- data/samples/cgi/po/ja/helloerb1.po +60 -0
- data/samples/cgi/po/ja/helloerb2.po +52 -0
- data/samples/cgi/po/ja/hellolib.po +24 -0
- data/samples/cgi/po/ja/main.po +85 -0
- data/samples/cgi/po/ko/helloerb1.po +59 -0
- data/samples/cgi/po/ko/helloerb2.po +51 -0
- data/samples/cgi/po/ko/hellolib.po +23 -0
- data/samples/cgi/po/ko/main.po +84 -0
- data/samples/cgi/po/lv/helloerb1.po +65 -0
- data/samples/cgi/po/lv/helloerb2.po +52 -0
- data/samples/cgi/po/lv/hellolib.po +24 -0
- data/samples/cgi/po/lv/main.po +77 -0
- data/samples/cgi/po/main.pot +80 -0
- data/samples/cgi/po/nb/helloerb1.po +60 -0
- data/samples/cgi/po/nb/helloerb2.po +52 -0
- data/samples/cgi/po/nb/hellolib.po +24 -0
- data/samples/cgi/po/nb/main.po +84 -0
- data/samples/cgi/po/nl/helloerb1.po +61 -0
- data/samples/cgi/po/nl/helloerb2.po +52 -0
- data/samples/cgi/po/nl/hellolib.po +24 -0
- data/samples/cgi/po/nl/main.po +86 -0
- data/samples/cgi/po/pt_BR/helloerb1.po +59 -0
- data/samples/cgi/po/pt_BR/helloerb2.po +51 -0
- data/samples/cgi/po/pt_BR/hellolib.po +23 -0
- data/samples/cgi/po/pt_BR/main.po +84 -0
- data/samples/cgi/po/ru/helloerb1.po +58 -0
- data/samples/cgi/po/ru/helloerb2.po +50 -0
- data/samples/cgi/po/ru/hellolib.po +22 -0
- data/samples/cgi/po/ru/main.po +82 -0
- data/samples/cgi/po/sr/helloerb1.po +60 -0
- data/samples/cgi/po/sr/helloerb2.po +52 -0
- data/samples/cgi/po/sr/hellolib.po +24 -0
- data/samples/cgi/po/sr/main.po +80 -0
- data/samples/cgi/po/ua/helloerb1.po +62 -0
- data/samples/cgi/po/ua/helloerb2.po +54 -0
- data/samples/cgi/po/ua/hellolib.po +26 -0
- data/samples/cgi/po/ua/main.po +84 -0
- data/samples/cgi/po/vi/helloerb1.po +65 -0
- data/samples/cgi/po/vi/helloerb2.po +52 -0
- data/samples/cgi/po/vi/hellolib.po +24 -0
- data/samples/cgi/po/vi/main.po +77 -0
- data/samples/cgi/po/zh/helloerb1.po +60 -0
- data/samples/cgi/po/zh/helloerb2.po +52 -0
- data/samples/cgi/po/zh/hellolib.po +24 -0
- data/samples/cgi/po/zh/main.po +80 -0
- data/samples/cgi/po/zh_TW/helloerb1.po +67 -0
- data/samples/cgi/po/zh_TW/helloerb2.po +54 -0
- data/samples/cgi/po/zh_TW/hellolib.po +26 -0
- data/samples/cgi/po/zh_TW/main.po +79 -0
- data/samples/hello.rb +36 -0
- data/samples/hello2.rb +23 -0
- data/samples/hello_glade2.glade +70 -0
- data/samples/hello_glade2.rb +25 -0
- data/samples/hello_gtk2.rb +27 -0
- data/samples/hello_noop.rb +31 -0
- data/samples/hello_plural.rb +26 -0
- data/samples/hello_tk.rb +19 -0
- data/samples/makemo.rb +4 -0
- data/samples/po/bg/hello.po +24 -0
- data/samples/po/bg/hello2.po +31 -0
- data/samples/po/bg/hello_glade2.po +31 -0
- data/samples/po/bg/hello_gtk.po +23 -0
- data/samples/po/bg/hello_noop.po +27 -0
- data/samples/po/bg/hello_plural.po +25 -0
- data/samples/po/bg/hello_tk.po +23 -0
- data/samples/po/bs/hello.po +23 -0
- data/samples/po/bs/hello2.po +31 -0
- data/samples/po/bs/hello_glade2.po +31 -0
- data/samples/po/bs/hello_gtk.po +23 -0
- data/samples/po/bs/hello_noop.po +27 -0
- data/samples/po/bs/hello_plural.po +26 -0
- data/samples/po/bs/hello_tk.po +23 -0
- data/samples/po/ca/hello.po +23 -0
- data/samples/po/ca/hello2.po +31 -0
- data/samples/po/ca/hello_glade2.po +31 -0
- data/samples/po/ca/hello_gtk.po +23 -0
- data/samples/po/ca/hello_noop.po +27 -0
- data/samples/po/ca/hello_plural.po +25 -0
- data/samples/po/ca/hello_tk.po +23 -0
- data/samples/po/cs/hello.po +23 -0
- data/samples/po/cs/hello2.po +31 -0
- data/samples/po/cs/hello_glade2.po +37 -0
- data/samples/po/cs/hello_gtk.po +23 -0
- data/samples/po/cs/hello_noop.po +27 -0
- data/samples/po/cs/hello_plural.po +26 -0
- data/samples/po/cs/hello_tk.po +23 -0
- data/samples/po/de/hello.po +20 -0
- data/samples/po/de/hello2.po +28 -0
- data/samples/po/de/hello_glade2.po +27 -0
- data/samples/po/de/hello_gtk.po +20 -0
- data/samples/po/de/hello_noop.po +24 -0
- data/samples/po/de/hello_plural.po +25 -0
- data/samples/po/de/hello_tk.po +20 -0
- data/samples/po/el/hello.po +23 -0
- data/samples/po/el/hello2.po +31 -0
- data/samples/po/el/hello_glade2.po +31 -0
- data/samples/po/el/hello_gtk.po +22 -0
- data/samples/po/el/hello_noop.po +27 -0
- data/samples/po/el/hello_plural.po +25 -0
- data/samples/po/el/hello_tk.po +23 -0
- data/samples/po/eo/hello.po +23 -0
- data/samples/po/eo/hello2.po +31 -0
- data/samples/po/eo/hello_glade2.po +32 -0
- data/samples/po/eo/hello_gtk.po +23 -0
- data/samples/po/eo/hello_noop.po +27 -0
- data/samples/po/eo/hello_plural.po +26 -0
- data/samples/po/eo/hello_tk.po +24 -0
- data/samples/po/es/hello.po +21 -0
- data/samples/po/es/hello2.po +28 -0
- data/samples/po/es/hello_glade2.po +28 -0
- data/samples/po/es/hello_gtk.po +20 -0
- data/samples/po/es/hello_noop.po +24 -0
- data/samples/po/es/hello_plural.po +23 -0
- data/samples/po/es/hello_tk.po +20 -0
- data/samples/po/fr/hello.po +18 -0
- data/samples/po/fr/hello2.po +26 -0
- data/samples/po/fr/hello_glade2.po +27 -0
- data/samples/po/fr/hello_gtk.po +18 -0
- data/samples/po/fr/hello_noop.po +22 -0
- data/samples/po/fr/hello_plural.po +21 -0
- data/samples/po/fr/hello_tk.po +18 -0
- data/samples/po/hello.pot +23 -0
- data/samples/po/hello2.pot +31 -0
- data/samples/po/hello_glade2.pot +32 -0
- data/samples/po/hello_gtk.pot +23 -0
- data/samples/po/hello_noop.pot +27 -0
- data/samples/po/hello_plural.pot +26 -0
- data/samples/po/hello_tk.pot +24 -0
- data/samples/po/hr/hello.po +23 -0
- data/samples/po/hr/hello2.po +31 -0
- data/samples/po/hr/hello_glade2.po +31 -0
- data/samples/po/hr/hello_gtk.po +23 -0
- data/samples/po/hr/hello_noop.po +27 -0
- data/samples/po/hr/hello_plural.po +26 -0
- data/samples/po/hr/hello_tk.po +23 -0
- data/samples/po/hu/hello.po +22 -0
- data/samples/po/hu/hello2.po +30 -0
- data/samples/po/hu/hello_glade2.po +31 -0
- data/samples/po/hu/hello_gtk.po +22 -0
- data/samples/po/hu/hello_noop.po +26 -0
- data/samples/po/hu/hello_plural.po +25 -0
- data/samples/po/hu/hello_tk.po +23 -0
- data/samples/po/it/hello.po +20 -0
- data/samples/po/it/hello2.po +28 -0
- data/samples/po/it/hello_glade2.po +28 -0
- data/samples/po/it/hello_gtk.po +21 -0
- data/samples/po/it/hello_noop.po +24 -0
- data/samples/po/it/hello_plural.po +23 -0
- data/samples/po/it/hello_tk.po +21 -0
- data/samples/po/ja/hello.po +20 -0
- data/samples/po/ja/hello2.po +28 -0
- data/samples/po/ja/hello_glade2.po +26 -0
- data/samples/po/ja/hello_gtk.po +19 -0
- data/samples/po/ja/hello_noop.po +23 -0
- data/samples/po/ja/hello_plural.po +21 -0
- data/samples/po/ja/hello_tk.po +19 -0
- data/samples/po/ko/hello.po +18 -0
- data/samples/po/ko/hello2.po +26 -0
- data/samples/po/ko/hello_glade2.po +29 -0
- data/samples/po/ko/hello_gtk.po +18 -0
- data/samples/po/ko/hello_noop.po +22 -0
- data/samples/po/ko/hello_plural.po +25 -0
- data/samples/po/ko/hello_tk.po +19 -0
- data/samples/po/lv/hello.po +24 -0
- data/samples/po/lv/hello2.po +32 -0
- data/samples/po/lv/hello_glade2.po +38 -0
- data/samples/po/lv/hello_gtk.po +24 -0
- data/samples/po/lv/hello_noop.po +28 -0
- data/samples/po/lv/hello_plural.po +26 -0
- data/samples/po/lv/hello_tk.po +24 -0
- data/samples/po/nb/hello.po +23 -0
- data/samples/po/nb/hello2.po +31 -0
- data/samples/po/nb/hello_glade2.po +31 -0
- data/samples/po/nb/hello_gtk.po +23 -0
- data/samples/po/nb/hello_noop.po +27 -0
- data/samples/po/nb/hello_plural.po +26 -0
- data/samples/po/nb/hello_tk.po +24 -0
- data/samples/po/nl/hello.po +24 -0
- data/samples/po/nl/hello2.po +32 -0
- data/samples/po/nl/hello_glade2.po +31 -0
- data/samples/po/nl/hello_gtk.po +24 -0
- data/samples/po/nl/hello_noop.po +28 -0
- data/samples/po/nl/hello_plural.po +25 -0
- data/samples/po/nl/hello_tk.po +24 -0
- data/samples/po/pt_BR/hello.po +21 -0
- data/samples/po/pt_BR/hello2.po +29 -0
- data/samples/po/pt_BR/hello_glade2.po +29 -0
- data/samples/po/pt_BR/hello_gtk.po +21 -0
- data/samples/po/pt_BR/hello_noop.po +25 -0
- data/samples/po/pt_BR/hello_plural.po +23 -0
- data/samples/po/pt_BR/hello_tk.po +21 -0
- data/samples/po/ru/hello.po +22 -0
- data/samples/po/ru/hello2.po +30 -0
- data/samples/po/ru/hello_glade2.po +30 -0
- data/samples/po/ru/hello_gtk.po +22 -0
- data/samples/po/ru/hello_noop.po +26 -0
- data/samples/po/ru/hello_plural.po +28 -0
- data/samples/po/ru/hello_tk.po +22 -0
- data/samples/po/sr/hello.po +22 -0
- data/samples/po/sr/hello2.po +30 -0
- data/samples/po/sr/hello_glade2.po +32 -0
- data/samples/po/sr/hello_gtk.po +22 -0
- data/samples/po/sr/hello_noop.po +26 -0
- data/samples/po/sr/hello_plural.po +26 -0
- data/samples/po/sr/hello_tk.po +24 -0
- data/samples/po/sv/hello.po +20 -0
- data/samples/po/sv/hello2.po +28 -0
- data/samples/po/sv/hello_glade2.po +28 -0
- data/samples/po/sv/hello_gtk.po +20 -0
- data/samples/po/sv/hello_noop.po +24 -0
- data/samples/po/sv/hello_plural.po +23 -0
- data/samples/po/sv/hello_tk.po +20 -0
- data/samples/po/test.rb +11 -0
- data/samples/po/ua/hello.po +22 -0
- data/samples/po/ua/hello2.po +30 -0
- data/samples/po/ua/hello_glade2.po +34 -0
- data/samples/po/ua/hello_gtk.po +22 -0
- data/samples/po/ua/hello_noop.po +26 -0
- data/samples/po/ua/hello_plural.po +29 -0
- data/samples/po/ua/hello_tk.po +26 -0
- data/samples/po/vi/hello.po +23 -0
- data/samples/po/vi/hello2.po +31 -0
- data/samples/po/vi/hello_glade2.po +38 -0
- data/samples/po/vi/hello_gtk.po +23 -0
- data/samples/po/vi/hello_noop.po +27 -0
- data/samples/po/vi/hello_plural.po +26 -0
- data/samples/po/vi/hello_tk.po +24 -0
- data/samples/po/zh/hello.po +23 -0
- data/samples/po/zh/hello2.po +31 -0
- data/samples/po/zh/hello_glade2.po +31 -0
- data/samples/po/zh/hello_gtk.po +23 -0
- data/samples/po/zh/hello_noop.po +27 -0
- data/samples/po/zh/hello_plural.po +25 -0
- data/samples/po/zh/hello_tk.po +23 -0
- data/samples/po/zh_TW/hello.po +26 -0
- data/samples/po/zh_TW/hello2.po +34 -0
- data/samples/po/zh_TW/hello_glade2.po +40 -0
- data/samples/po/zh_TW/hello_gtk.po +25 -0
- data/samples/po/zh_TW/hello_noop.po +30 -0
- data/samples/po/zh_TW/hello_plural.po +28 -0
- data/samples/po/zh_TW/hello_tk.po +26 -0
- data/src/poparser.ry +198 -0
- data/test/README +1 -0
- data/test/Rakefile +19 -0
- data/test/po/cr/plural.po +23 -0
- data/test/po/da/plural.po +22 -0
- data/test/po/da/plural_error.po +21 -0
- data/test/po/fr/plural.po +28 -0
- data/test/po/fr/plural_error.po +20 -0
- data/test/po/fr/test1.po +23 -0
- data/test/po/fr/test2.po +19 -0
- data/test/po/fr/test6.po +23 -0
- data/test/po/ir/plural.po +23 -0
- data/test/po/ja/npgettext.po +46 -0
- data/test/po/ja/nsgettext.po +65 -0
- data/test/po/ja/pgettext.po +41 -0
- data/test/po/ja/plural.po +28 -0
- data/test/po/ja/plural_error.po +20 -0
- data/test/po/ja/rubyparser.po +43 -0
- data/test/po/ja/sgettext.po +47 -0
- data/test/po/ja/test1.po +23 -0
- data/test/po/ja/test2.po +19 -0
- data/test/po/ja/test6.po +23 -0
- data/test/po/la/plural.po +23 -0
- data/test/po/la/plural_error.po +21 -0
- data/test/po/li/plural.po +23 -0
- data/test/po/po/plural.po +23 -0
- data/test/po/sl/plural.po +24 -0
- data/test/test_class_info.rb +80 -0
- data/test/test_gettext.rb +274 -0
- data/test/test_parser.rb +113 -0
- data/test/test_string.rb +14 -0
- data/test/test_textdomain.rb +25 -0
- data/test/test_textdomain_multi.rb +69 -0
- data/test/test_textdomain_toplevel.rb +42 -0
- data/test/testlib/N_.rb +66 -0
- data/test/testlib/erb.rhtml +15 -0
- data/test/testlib/erb.rxml +16 -0
- data/test/testlib/gettext.rb +96 -0
- data/test/testlib/gladeparser.glade +183 -0
- data/test/testlib/helper.rb +11 -0
- data/test/testlib/multi_textdomain.rb +119 -0
- data/test/testlib/ngettext.rb +74 -0
- data/test/testlib/npgettext.rb +31 -0
- data/test/testlib/nsgettext.rb +42 -0
- data/test/testlib/pgettext.rb +31 -0
- data/test/testlib/sgettext.rb +46 -0
- data/test/testlib/simple.rb +14 -0
- metadata +509 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
textdomain.rb - GetText::Textdomain
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2001-2009 Masao Mutoh
|
|
5
|
+
Copyright (C) 2001-2003 Masahiro Sakai
|
|
6
|
+
|
|
7
|
+
Masahiro Sakai <s01397ms@sfc.keio.ac.jp>
|
|
8
|
+
Masao Mutoh <mutoh@highway.ne.jp>
|
|
9
|
+
|
|
10
|
+
You may redistribute it and/or modify it under the same
|
|
11
|
+
license terms as Ruby.
|
|
12
|
+
|
|
13
|
+
$Id$
|
|
14
|
+
=end
|
|
15
|
+
|
|
16
|
+
require 'gettext/core_ext/string'
|
|
17
|
+
require 'gettext/mofile'
|
|
18
|
+
require 'rbconfig'
|
|
19
|
+
|
|
20
|
+
module GetText
|
|
21
|
+
# GetText::TextDomain class manages mo-files of a textdomain.
|
|
22
|
+
#
|
|
23
|
+
# Usually, you don't need to use this class directly.
|
|
24
|
+
#
|
|
25
|
+
# Notice: This class is unstable. APIs will be changed.
|
|
26
|
+
class TextDomain
|
|
27
|
+
|
|
28
|
+
attr_reader :output_charset
|
|
29
|
+
attr_reader :locale_paths
|
|
30
|
+
attr_reader :mofiles
|
|
31
|
+
attr_reader :name
|
|
32
|
+
|
|
33
|
+
@@cached = ! $DEBUG
|
|
34
|
+
# Cache the mo-file or not.
|
|
35
|
+
# Default is true. If $DEBUG is set then false.
|
|
36
|
+
def self.cached?
|
|
37
|
+
@@cached
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Set to cache the mo-file or not.
|
|
41
|
+
# * val: true if cached, otherwise false.
|
|
42
|
+
def self.cached=(val)
|
|
43
|
+
@@cached = val
|
|
44
|
+
end
|
|
45
|
+
# The default locale paths.
|
|
46
|
+
CONFIG_PREFIX = Config::CONFIG['prefix'].gsub(/\/local/, "")
|
|
47
|
+
DEFAULT_LOCALE_PATHS = [
|
|
48
|
+
"#{Config::CONFIG['datadir']}/locale/%{lang}/LC_MESSAGES/%{name}.mo",
|
|
49
|
+
"#{Config::CONFIG['datadir'].gsub(/\/local/, "")}/locale/%{lang}/LC_MESSAGES/%{name}.mo",
|
|
50
|
+
"#{CONFIG_PREFIX}/share/locale/%{lang}/LC_MESSAGES/%{name}.mo",
|
|
51
|
+
"#{CONFIG_PREFIX}/local/share/locale/%{lang}/LC_MESSAGES/%{name}.mo"
|
|
52
|
+
].uniq
|
|
53
|
+
|
|
54
|
+
# Add default locale path. Usually you should use GetText.add_default_locale_path instead.
|
|
55
|
+
# * path: a new locale path. (e.g.) "/usr/share/locale/%{lang}/LC_MESSAGES/%{name}.mo"
|
|
56
|
+
# ('locale' => "ja_JP", 'name' => "textdomain")
|
|
57
|
+
# * Returns: the new DEFAULT_LOCALE_PATHS
|
|
58
|
+
def self.add_default_locale_path(path)
|
|
59
|
+
DEFAULT_LOCALE_PATHS.unshift(path)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Creates a new GetText::TextDomain.
|
|
63
|
+
# * name: the textdomain name.
|
|
64
|
+
# * topdir: the locale path ("%{topdir}/%{lang}/LC_MESSAGES/%{name}.mo") or nil.
|
|
65
|
+
# * output_charset: output charset.
|
|
66
|
+
# * Returns: a newly created GetText::TextDomain object.
|
|
67
|
+
def initialize(name, topdir = nil, output_charset = nil)
|
|
68
|
+
@name, @topdir, @output_charset = name, topdir, output_charset
|
|
69
|
+
|
|
70
|
+
@locale_paths = []
|
|
71
|
+
if ENV["GETTEXT_PATH"]
|
|
72
|
+
ENV["GETTEXT_PATH"].split(/,/).each {|i|
|
|
73
|
+
@locale_paths += ["#{i}/%{lang}/LC_MESSAGES/%{name}.mo", "#{i}/%{lang}/%{name}.mo"]
|
|
74
|
+
}
|
|
75
|
+
elsif @topdir
|
|
76
|
+
@locale_paths += ["#{@topdir}/%{lang}/LC_MESSAGES/%{name}.mo", "#{@topdir}/%{lang}/%{name}.mo"]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
unless @topdir
|
|
80
|
+
@locale_paths += DEFAULT_LOCALE_PATHS
|
|
81
|
+
|
|
82
|
+
if defined? Gem
|
|
83
|
+
$:.each do |path|
|
|
84
|
+
if /(.*)\/lib$/ =~ path
|
|
85
|
+
@locale_paths += [
|
|
86
|
+
"#{$1}/data/locale/%{lang}/LC_MESSAGES/%{name}.mo",
|
|
87
|
+
"#{$1}/data/locale/%{lang}/%{name}.mo",
|
|
88
|
+
"#{$1}/locale/%{lang}/%{name}.mo"]
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
@mofiles = {}
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Translates the translated string.
|
|
98
|
+
# * lang: Locale::Tag::Simple's subclass.
|
|
99
|
+
# * msgid: the original message.
|
|
100
|
+
# * Returns: the translated string or nil.
|
|
101
|
+
def translate_singluar_message(lang, msgid)
|
|
102
|
+
return "" if msgid == "" or msgid.nil?
|
|
103
|
+
|
|
104
|
+
lang_key = lang.to_s
|
|
105
|
+
|
|
106
|
+
mofile = nil
|
|
107
|
+
if self.class.cached?
|
|
108
|
+
mofile = @mofiles[lang_key]
|
|
109
|
+
end
|
|
110
|
+
unless mofile
|
|
111
|
+
mofile = load_mo(lang)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
if (! mofile) or (mofile ==:empty)
|
|
115
|
+
return nil
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
msgstr = mofile[msgid]
|
|
119
|
+
if msgstr and (msgstr.size > 0)
|
|
120
|
+
msgstr
|
|
121
|
+
elsif msgid.include?("\000")
|
|
122
|
+
# Check "aaa\000bbb" and show warning but return the singluar part.
|
|
123
|
+
ret = nil
|
|
124
|
+
msgid_single = msgid.split("\000")[0]
|
|
125
|
+
mofile.each{|key, val|
|
|
126
|
+
if key =~ /^#{Regexp.quote(msgid_single)}\000/
|
|
127
|
+
# Usually, this is not caused to make po-files from rgettext.
|
|
128
|
+
warn %Q[Warning: n_("#{msgid_single}", "#{msgid.split("\000")[1]}") and n_("#{key.gsub(/\000/, '", "')}") are duplicated.]
|
|
129
|
+
ret = val
|
|
130
|
+
break
|
|
131
|
+
end
|
|
132
|
+
}
|
|
133
|
+
ret
|
|
134
|
+
else
|
|
135
|
+
ret = nil
|
|
136
|
+
mofile.each{|key, val|
|
|
137
|
+
if key =~ /^#{Regexp.quote(msgid)}\000/
|
|
138
|
+
ret = val.split("\000")[0]
|
|
139
|
+
break
|
|
140
|
+
end
|
|
141
|
+
}
|
|
142
|
+
ret
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Translates the translated string.
|
|
147
|
+
# * lang: Locale::Tag::Simple's subclass.
|
|
148
|
+
# * msgid: the original message.
|
|
149
|
+
# * msgid_plural: the original message(plural).
|
|
150
|
+
# * Returns: the translated string as an Array ([[msgstr1, msgstr2, ...], cond]) or nil.
|
|
151
|
+
def translate_plural_message(lang, msgid, msgid_plural) #:nodoc:
|
|
152
|
+
key = msgid + "\000" + msgid_plural
|
|
153
|
+
msg = translate_singluar_message(lang, key)
|
|
154
|
+
ret = nil
|
|
155
|
+
if ! msg
|
|
156
|
+
ret = nil
|
|
157
|
+
elsif msg.include?("\000")
|
|
158
|
+
# [[msgstr[0], msgstr[1], msgstr[2],...], cond]
|
|
159
|
+
mofile = @mofiles[lang.to_posix.to_s]
|
|
160
|
+
cond = (mofile and mofile != :empty) ? mofile.plural : nil
|
|
161
|
+
cond ||= "n != 1"
|
|
162
|
+
ret = [msg.split("\000"), cond]
|
|
163
|
+
else
|
|
164
|
+
ret = [[msg], "0"]
|
|
165
|
+
end
|
|
166
|
+
ret
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def clear
|
|
170
|
+
@mofiles = {}
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
private
|
|
174
|
+
# Load a mo-file from the file.
|
|
175
|
+
# lang is the subclass of Locale::Tag::Simple.
|
|
176
|
+
def load_mo(lang)
|
|
177
|
+
lang = lang.to_posix unless lang.kind_of? Locale::Tag::Posix
|
|
178
|
+
lang_key = lang.to_s
|
|
179
|
+
|
|
180
|
+
mofile = @mofiles[lang_key]
|
|
181
|
+
if mofile
|
|
182
|
+
if mofile == :empty
|
|
183
|
+
return :empty
|
|
184
|
+
elsif ! self.class.cached?
|
|
185
|
+
mofile.update!
|
|
186
|
+
end
|
|
187
|
+
return mofile
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
search_files = []
|
|
191
|
+
|
|
192
|
+
lang_candidates = lang.to_posix.candidates
|
|
193
|
+
@locale_paths.each do |dir|
|
|
194
|
+
lang_candidates.each{|tag|
|
|
195
|
+
fname = dir % {:lang => tag, :name => @name}
|
|
196
|
+
if $DEBUG
|
|
197
|
+
search_files << fname unless search_files.include?(fname)
|
|
198
|
+
end
|
|
199
|
+
if File.exist?(fname)
|
|
200
|
+
warn "GetText::TextDomain#load_mo: mo-file is #{fname}" if $DEBUG
|
|
201
|
+
|
|
202
|
+
charset = @output_charset || lang.charset || Locale.charset || "UTF-8"
|
|
203
|
+
mofile = MOFile.open(fname, charset)
|
|
204
|
+
break
|
|
205
|
+
end
|
|
206
|
+
}
|
|
207
|
+
break if mofile
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
if mofile
|
|
211
|
+
@mofiles[lang_key] = mofile
|
|
212
|
+
else
|
|
213
|
+
@mofiles[lang_key] = :empty
|
|
214
|
+
if $DEBUG
|
|
215
|
+
warn "MO file is not found in"
|
|
216
|
+
search_files.each do |v|
|
|
217
|
+
warn " #{v}"
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
mofile
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
end
|
|
225
|
+
end
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
require 'gettext/textdomain'
|
|
2
|
+
require 'gettext/class_info'
|
|
3
|
+
require 'locale/util/memoizable'
|
|
4
|
+
|
|
5
|
+
module GetText
|
|
6
|
+
class TextDomainManager
|
|
7
|
+
include Locale::Util::Memoizable
|
|
8
|
+
|
|
9
|
+
@@cached = ! $DEBUG
|
|
10
|
+
@@textdomain_pool = {}
|
|
11
|
+
@@textdomain_manager_pool = {}
|
|
12
|
+
|
|
13
|
+
@@output_charset = nil
|
|
14
|
+
@@gettext_classes = []
|
|
15
|
+
|
|
16
|
+
# Gets all textdomains.
|
|
17
|
+
def self.textdomain_pool(domainname)
|
|
18
|
+
@@textdomain_pool[domainname]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.get(obj) #:nodoc:
|
|
22
|
+
klass = ClassInfo.normalize_class(obj)
|
|
23
|
+
ret = @@textdomain_manager_pool[klass]
|
|
24
|
+
unless ret
|
|
25
|
+
ret = TextDomainManager.new
|
|
26
|
+
@@textdomain_manager_pool[klass] = ret
|
|
27
|
+
end
|
|
28
|
+
ret
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Set the value whether cache messages or not.
|
|
32
|
+
# true to cache messages, otherwise false.
|
|
33
|
+
#
|
|
34
|
+
# Default is true. If $DEBUG is false, messages are not checked even if
|
|
35
|
+
# this value is true.
|
|
36
|
+
def self.cached=(val)
|
|
37
|
+
@@cached = val
|
|
38
|
+
@@textdomain_pool.each do |key, textdomain|
|
|
39
|
+
textdomain.cached = val
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Return the cached value.
|
|
44
|
+
def self.cached?
|
|
45
|
+
@@cached
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Gets the output charset.
|
|
49
|
+
def self.output_charset
|
|
50
|
+
@@output_charset
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Sets the output charset.The program can have a output charset.
|
|
54
|
+
def self.output_charset=(charset)
|
|
55
|
+
@@output_charset = charset
|
|
56
|
+
@@textdomain_pool.each do |key, textdomain|
|
|
57
|
+
textdomain.charset = charset
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# bind textdomain to the class.
|
|
62
|
+
def self.bind_to(klass, domainname, options = {})
|
|
63
|
+
warn "Bind the domain '#{domainname}' to '#{klass}'. " if $DEBUG
|
|
64
|
+
|
|
65
|
+
path = options[:path] if options[:path]
|
|
66
|
+
charset = options[:output_charset] || self.output_charset
|
|
67
|
+
|
|
68
|
+
# Create a new textdomain into the pool.
|
|
69
|
+
textdomain = @@textdomain_pool[domainname]
|
|
70
|
+
unless textdomain
|
|
71
|
+
textdomain = TextDomain.new(domainname, path, charset)
|
|
72
|
+
end
|
|
73
|
+
@@textdomain_pool[domainname] = textdomain
|
|
74
|
+
|
|
75
|
+
target_klass = ClassInfo.normalize_class(klass)
|
|
76
|
+
|
|
77
|
+
get(target_klass).add(textdomain, options[:supported_language_tags])
|
|
78
|
+
|
|
79
|
+
@@gettext_classes << target_klass unless @@gettext_classes.include? target_klass
|
|
80
|
+
|
|
81
|
+
textdomain
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
#
|
|
85
|
+
# Instance methods
|
|
86
|
+
#
|
|
87
|
+
|
|
88
|
+
# Returns the textdoman in the instance.
|
|
89
|
+
attr_reader :textdomains, :supported_language_tags
|
|
90
|
+
|
|
91
|
+
def initialize
|
|
92
|
+
@textdomains = []
|
|
93
|
+
@supported_language_tags = nil
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def add(textdomain, supported_language_tags)
|
|
97
|
+
@textdomains.insert(0, textdomain) unless @textdomains.include? textdomain
|
|
98
|
+
@supported_language_tags = supported_language_tags if supported_language_tags
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Translates msgid, but if there are no localized text,
|
|
102
|
+
# it returns a last part of msgid separeted "div" or whole of the msgid with no "div".
|
|
103
|
+
#
|
|
104
|
+
# * msgid: the message id.
|
|
105
|
+
# * div: separator or nil.
|
|
106
|
+
# * Returns: the localized text by msgid. If there are no localized text,
|
|
107
|
+
# it returns a last part of msgid separeted "div".
|
|
108
|
+
def translate_singluar_message(klass, msgid, div = '|')
|
|
109
|
+
lang = Locale.candidates(:supported_language_tags => @supported_language_tags,
|
|
110
|
+
:type => :posix)[0]
|
|
111
|
+
translate_singluar_message_to(lang, klass, msgid, div)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def translate_singluar_message_to(lang, klass, msgid, div = '|') #:nodoc:
|
|
115
|
+
msg = nil
|
|
116
|
+
# Find messages from related classes.
|
|
117
|
+
ClassInfo.related_classes(klass, @@gettext_classes).each do |target|
|
|
118
|
+
msg = nil
|
|
119
|
+
self.class.get(target).textdomains.each do |textdomain|
|
|
120
|
+
msg = textdomain.translate_singluar_message(lang, msgid)
|
|
121
|
+
break if msg
|
|
122
|
+
end
|
|
123
|
+
break if msg
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# If not found, return msgid.
|
|
127
|
+
msg ||= msgid
|
|
128
|
+
if div and msg == msgid
|
|
129
|
+
if index = msg.rindex(div)
|
|
130
|
+
msg = msg[(index + 1)..-1]
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
msg
|
|
134
|
+
end
|
|
135
|
+
memoize :translate_singluar_message_to
|
|
136
|
+
|
|
137
|
+
# This function is similar to the get_singluar_message function
|
|
138
|
+
# as it finds the message catalogs in the same way.
|
|
139
|
+
# But it takes two extra arguments for plural form.
|
|
140
|
+
# The msgid parameter must contain the singular form of the string to be converted.
|
|
141
|
+
# It is also used as the key for the search in the catalog.
|
|
142
|
+
# The msgid_plural parameter is the plural form.
|
|
143
|
+
# The parameter n is used to determine the plural form.
|
|
144
|
+
# If no message catalog is found msgid1 is returned if n == 1, otherwise msgid2.
|
|
145
|
+
# And if msgid includes "div", it returns a last part of msgid separeted "div".
|
|
146
|
+
#
|
|
147
|
+
# * msgid: the singular form with "div". (e.g. "Special|An apple", "An apple")
|
|
148
|
+
# * msgid_plural: the plural form. (e.g. "%{num} Apples")
|
|
149
|
+
# * n: a number used to determine the plural form.
|
|
150
|
+
# * div: the separator. Default is "|".
|
|
151
|
+
# * Returns: the localized text which key is msgid_plural if n is plural(follow plural-rule) or msgid.
|
|
152
|
+
# "plural-rule" is defined in po-file.
|
|
153
|
+
#
|
|
154
|
+
# or
|
|
155
|
+
#
|
|
156
|
+
# * [msgid, msgid_plural] : msgid and msgid_plural an Array
|
|
157
|
+
# * n: a number used to determine the plural form.
|
|
158
|
+
# * div: the separator. Default is "|".
|
|
159
|
+
def translate_plural_message(klass, arg1, arg2, arg3 = "|", arg4 = "|")
|
|
160
|
+
lang = Locale.candidates(:supported_language_tags => @supported_language_tags,
|
|
161
|
+
:type => :posix)[0]
|
|
162
|
+
|
|
163
|
+
if arg1.kind_of?(Array)
|
|
164
|
+
msgid = arg1[0]
|
|
165
|
+
msgid_plural = arg1[1]
|
|
166
|
+
n = arg2
|
|
167
|
+
if arg3 and arg3.kind_of? Numeric
|
|
168
|
+
raise ArgumentError, _("3rd parmeter is wrong: value = %{number}") % {:number => arg3}
|
|
169
|
+
end
|
|
170
|
+
div = arg3
|
|
171
|
+
else
|
|
172
|
+
msgid = arg1
|
|
173
|
+
msgid_plural = arg2
|
|
174
|
+
n = arg3
|
|
175
|
+
div = arg4
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
msgs = nil
|
|
179
|
+
# Find messages from related classes.
|
|
180
|
+
ClassInfo.related_classes(klass, @@gettext_classes).each do |target|
|
|
181
|
+
msgs = nil
|
|
182
|
+
self.class.get(target).textdomains.each do |textdomain|
|
|
183
|
+
msgs = textdomain.translate_plural_message(lang, msgid, msgid_plural)
|
|
184
|
+
break if msgs
|
|
185
|
+
end
|
|
186
|
+
break if msgs
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# If not found, return msgid.
|
|
190
|
+
unless msgs
|
|
191
|
+
msgs = [[msgid, msgid_plural], "n != 1"]
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
msgstrs = msgs[0]
|
|
195
|
+
if div and msgstrs[0] == msgid
|
|
196
|
+
if index = msgstrs[0].rindex(div)
|
|
197
|
+
msgstrs[0] = msgstrs[0][(index + 1)..-1]
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Return the singular or plural message.
|
|
202
|
+
plural = eval(msgs[1])
|
|
203
|
+
if plural.kind_of?(Numeric)
|
|
204
|
+
ret = msgstrs[plural]
|
|
205
|
+
else
|
|
206
|
+
ret = plural ? msgstrs[1] : msgstrs[0]
|
|
207
|
+
end
|
|
208
|
+
ret
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# for testing.
|
|
212
|
+
def self.clear_all_textdomains
|
|
213
|
+
@@textdomain_pool = {}
|
|
214
|
+
@@textdomain_manager_pool = {}
|
|
215
|
+
@@gettext_classes = []
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
tools.rb - Utility functions
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2005-2008 Masao Mutoh
|
|
5
|
+
|
|
6
|
+
You may redistribute it and/or modify it under the same
|
|
7
|
+
license terms as Ruby.
|
|
8
|
+
=end
|
|
9
|
+
|
|
10
|
+
require 'rbconfig'
|
|
11
|
+
if /mingw|mswin|mswin32/ =~ RUBY_PLATFORM
|
|
12
|
+
ENV['PATH'] = %w(bin lib).collect{|dir|
|
|
13
|
+
"#{Config::CONFIG["prefix"]}\\lib\\GTK\\#{dir};"
|
|
14
|
+
}.join('') + ENV['PATH']
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require 'gettext/tools/rgettext'
|
|
18
|
+
require 'gettext/tools/rmsgfmt'
|
|
19
|
+
require 'gettext/mofile'
|
|
20
|
+
require 'fileutils'
|
|
21
|
+
|
|
22
|
+
module GetText
|
|
23
|
+
bindtextdomain "rgettext"
|
|
24
|
+
|
|
25
|
+
BOM_UTF8 = [0xef, 0xbb, 0xbf].pack("c3")
|
|
26
|
+
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
# Currently, GNU msgmerge doesn't accept BOM.
|
|
30
|
+
# This mesthod remove the UTF-8 BOM from the po-file.
|
|
31
|
+
def remove_bom(path) #:nodoc:
|
|
32
|
+
bom = IO.read(path, 3)
|
|
33
|
+
if bom == BOM_UTF8
|
|
34
|
+
data = IO.read(path)
|
|
35
|
+
File.open(path, "w") do |out|
|
|
36
|
+
out.write(data[3..-1])
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Merges two Uniforum style .po files together.
|
|
42
|
+
#
|
|
43
|
+
# *Note* This function requires "msgmerge" tool included in GNU GetText. So you need to install GNU GetText.
|
|
44
|
+
#
|
|
45
|
+
# The def.po file is an existing PO file with translations which will be taken
|
|
46
|
+
# over to the newly created file as long as they still match; comments will be preserved,
|
|
47
|
+
# but extracted comments and file positions will be discarded.
|
|
48
|
+
#
|
|
49
|
+
# The ref.pot file is the last created PO file with up-to-date source references but
|
|
50
|
+
# old translations, or a PO Template file (generally created by rgettext);
|
|
51
|
+
# any translations or comments in the file will be discarded, however dot
|
|
52
|
+
# comments and file positions will be preserved. Where an exact match
|
|
53
|
+
# cannot be found, fuzzy matching is used to produce better results.
|
|
54
|
+
#
|
|
55
|
+
# Usually you don't need to call this function directly. Use GetText.update_pofiles instead.
|
|
56
|
+
#
|
|
57
|
+
# * defpo: a po-file. translations referring to old sources
|
|
58
|
+
# * refpo: a po-file. references to new sources
|
|
59
|
+
# * app_version: the application information which appears "Project-Id-Version: #{app_version}" in the pot/po-files.
|
|
60
|
+
# * Returns: self
|
|
61
|
+
def msgmerge(defpo, refpo, app_version, options)
|
|
62
|
+
verbose = options.delete(:verbose) || false
|
|
63
|
+
puts "msgmerge called" if verbose
|
|
64
|
+
$stderr.print defpo + " "
|
|
65
|
+
cmd = ENV["MSGMERGE_PATH"] || "msgmerge"
|
|
66
|
+
|
|
67
|
+
cont = ""
|
|
68
|
+
if FileTest.exist? defpo
|
|
69
|
+
`#{cmd} --help`
|
|
70
|
+
unless $? && $?.success?
|
|
71
|
+
raise _("`%{cmd}' can not be found. \nInstall GNU Gettext then set PATH or MSGMERGE_PATH correctly.") % {:cmd => cmd}
|
|
72
|
+
end
|
|
73
|
+
remove_bom(defpo)
|
|
74
|
+
|
|
75
|
+
cmd_params = (options.delete(:msgmerge) || {}).map do |o|
|
|
76
|
+
o.kind_of?(Symbol) ? "--#{o}".gsub('_','-') : o.to_s
|
|
77
|
+
end.join(' ')
|
|
78
|
+
|
|
79
|
+
to_run = "#{cmd} #{cmd_params} #{defpo} #{refpo}"
|
|
80
|
+
puts "\nrunning #{to_run}" if verbose
|
|
81
|
+
cont = `#{to_run}`
|
|
82
|
+
else
|
|
83
|
+
File.open(refpo) do |io|
|
|
84
|
+
cont = io.read
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
if cont.empty?
|
|
88
|
+
failed_filename = refpo + "~"
|
|
89
|
+
FileUtils.cp(refpo, failed_filename)
|
|
90
|
+
$stderr.puts _("Failed to merge with %{defpo}") % {:defpo => defpo}
|
|
91
|
+
$stderr.puts _("New .pot was copied to %{failed_filename}") %{:failed_filename => failed_filename}
|
|
92
|
+
raise _("Check these po/pot-files. It may have syntax errors or something wrong.")
|
|
93
|
+
else
|
|
94
|
+
cont.sub!(/(Project-Id-Version\:).*$/, "\\1 #{app_version}\\n\"")
|
|
95
|
+
File.open(defpo, "w") do |out|
|
|
96
|
+
out.write(cont)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
self
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Creates mo-files using #{po_root}/#{lang}/*.po an put them to
|
|
103
|
+
# #{targetdir}/#{targetdir_rule}/.
|
|
104
|
+
#
|
|
105
|
+
# This is a convenience function of GetText.rmsgfmt for plural target files.
|
|
106
|
+
# * options: options as a Hash.
|
|
107
|
+
# * verbose: true if verbose mode, otherwise false
|
|
108
|
+
# * po_root: the root directory of po-files.
|
|
109
|
+
# * mo_root: the target root directory where the mo-files are stored.
|
|
110
|
+
# * mo_path_rule: the target directory for each mo-files.
|
|
111
|
+
def create_mofiles(options = {})
|
|
112
|
+
opts = {:verbose => false, :po_root => "./po", :mo_root => "./data/locale",
|
|
113
|
+
:mo_path_rule => "%{lang}/LC_MESSAGES"}
|
|
114
|
+
opts.merge!(options)
|
|
115
|
+
|
|
116
|
+
modir = File.join(opts[:mo_root], opts[:mo_path_rule])
|
|
117
|
+
Dir.glob(File.join(opts[:po_root], "*/*.po")) do |file|
|
|
118
|
+
lang, basename = /\/([^\/]+?)\/(.*)\.po/.match(file[opts[:po_root].size..-1]).to_a[1,2]
|
|
119
|
+
outdir = modir % {:lang => lang}
|
|
120
|
+
FileUtils.mkdir_p(outdir) unless File.directory?(outdir)
|
|
121
|
+
$stderr.print %Q[#{file} -> #{File.join(outdir, "#{basename}.mo")} ... ] if opts[:verbose]
|
|
122
|
+
begin
|
|
123
|
+
rmsgfmt(file, File.join(outdir, "#{basename}.mo"))
|
|
124
|
+
rescue Exception => e
|
|
125
|
+
$stderr.puts "Error." if opts[:verbose]
|
|
126
|
+
raise e
|
|
127
|
+
end
|
|
128
|
+
$stderr.puts "Done." if opts[:verbose]
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# At first, this creates the #{po_root}/#{domainname}.pot file using GetText.rgettext.
|
|
134
|
+
# In the second step, this updates(merges) the #{po_root}/#{domainname}.pot and all of the
|
|
135
|
+
# #{po_root}/#{lang}/#{domainname}.po files under "po_root" using "msgmerge".
|
|
136
|
+
#
|
|
137
|
+
# *Note* "msgmerge" tool is included in GNU GetText. So you need to install GNU GetText.
|
|
138
|
+
#
|
|
139
|
+
# See <HOWTO maintain po/mo files(http://www.yotabanana.com/hiki/ruby-gettext-howto-manage.html)> for more detals.
|
|
140
|
+
# * domainname: the textdomain name.
|
|
141
|
+
# * targetfiles: An Array of target files or nil (See GetText.rgettext for more details).
|
|
142
|
+
# * app_version: the application information which appears "Project-Id-Version: #{app_version}" in the pot/po-files.
|
|
143
|
+
# * options: a hash with following possible settings
|
|
144
|
+
# :lang - update files only for one language - the language specified by this option
|
|
145
|
+
# :po_root - the root directory of po-files
|
|
146
|
+
# :msgmerge - an array with the options, passed through to the gnu msgmerge tool
|
|
147
|
+
# symbols are automatically translated to options with dashes,
|
|
148
|
+
# example: [:no_wrap, :no_fuzzy_matching, :sort_output] translated to '--no-fuzzy-matching --sort-output'
|
|
149
|
+
# :verbose - true to show verbose messages. default is false.
|
|
150
|
+
#
|
|
151
|
+
# Example: GetText.update_pofiles("myapp", Dir.glob("lib/*.rb"), "myapp 1.0.0", :verbose => true)
|
|
152
|
+
def update_pofiles(textdomain, files, app_version, options = {})
|
|
153
|
+
puts options.inspect
|
|
154
|
+
po_root = options.delete(:po_root) || "po"
|
|
155
|
+
only_one_language = options.delete(:lang)
|
|
156
|
+
refpot = "tmp.pot"
|
|
157
|
+
rgettext(files, refpot)
|
|
158
|
+
|
|
159
|
+
FileUtils.mkdir_p(po_root) unless FileTest.exist? po_root
|
|
160
|
+
msgmerge("#{po_root}/#{textdomain}.pot", refpot, app_version, options.dup)
|
|
161
|
+
|
|
162
|
+
if only_one_language
|
|
163
|
+
msgmerge("#{po_root}/#{only_one_language}/#{textdomain}.po", refpot, app_version, options.dup)
|
|
164
|
+
else
|
|
165
|
+
Dir.glob("#{po_root}/*/#{textdomain}.po"){ |f|
|
|
166
|
+
lang = /#{po_root}\/(.*)\//.match(f).to_a[1]
|
|
167
|
+
msgmerge("#{po_root}/#{lang}/#{textdomain}.po", refpot, app_version, options.dup)
|
|
168
|
+
}
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
File.delete(refpot)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
if __FILE__ == $0
|
|
176
|
+
GetText.update_pofiles("foo", ARGV, "foo 1.1.0")
|
|
177
|
+
end
|