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,275 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
=begin
|
|
3
|
+
rgettext.rb - Generate a .pot file.
|
|
4
|
+
|
|
5
|
+
Copyright (C) 2003-2009 Masao Mutoh
|
|
6
|
+
Copyright (C) 2001,2002 Yasushi Shoji, Masao Mutoh
|
|
7
|
+
|
|
8
|
+
Yasushi Shoji <yashi at atmark-techno.com>
|
|
9
|
+
Masao Mutoh <mutoh at highway.ne.jp>
|
|
10
|
+
|
|
11
|
+
You may redistribute it and/or modify it under the same
|
|
12
|
+
license terms as Ruby.
|
|
13
|
+
=end
|
|
14
|
+
|
|
15
|
+
require 'optparse'
|
|
16
|
+
require 'gettext'
|
|
17
|
+
require 'rbconfig'
|
|
18
|
+
|
|
19
|
+
module GetText
|
|
20
|
+
|
|
21
|
+
module RGetText #:nodoc:
|
|
22
|
+
extend GetText
|
|
23
|
+
|
|
24
|
+
bindtextdomain("rgettext")
|
|
25
|
+
|
|
26
|
+
# constant values
|
|
27
|
+
VERSION = GetText::VERSION
|
|
28
|
+
DATE = %w($Date: 2008/08/06 17:35:52 $)[1]
|
|
29
|
+
MAX_LINE_LEN = 70
|
|
30
|
+
|
|
31
|
+
@ex_parsers = []
|
|
32
|
+
[
|
|
33
|
+
["glade.rb", "GladeParser"],
|
|
34
|
+
["erb.rb", "ErbParser"],
|
|
35
|
+
# ["active_record.rb", "ActiveRecordParser"],
|
|
36
|
+
# ["ripper.rb", "RipperParser"],
|
|
37
|
+
["ruby.rb", "RubyParser"] # Default parser.
|
|
38
|
+
].each do |f, klass|
|
|
39
|
+
begin
|
|
40
|
+
require "gettext/parser/#{f}"
|
|
41
|
+
@ex_parsers << GetText.const_get(klass)
|
|
42
|
+
rescue
|
|
43
|
+
$stderr.puts _("'%{klass}' is ignored.") % {:klass => klass}
|
|
44
|
+
$stderr.puts $! if $DEBUG
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module_function
|
|
49
|
+
|
|
50
|
+
# Add an option parser
|
|
51
|
+
# the option parser module requires to have target?(file) and parser(file, ary) method.
|
|
52
|
+
#
|
|
53
|
+
# require 'gettext/rgettext'
|
|
54
|
+
# module FooParser
|
|
55
|
+
# module_function
|
|
56
|
+
# def target?(file)
|
|
57
|
+
# File.extname(file) == '.foo' # *.foo file only.
|
|
58
|
+
# end
|
|
59
|
+
# def parse(file, ary)
|
|
60
|
+
# :
|
|
61
|
+
# return ary # [["msgid1", "foo.rb:200"], ["msgid2", "bar.rb:300", "baz.rb:400"], ...]
|
|
62
|
+
# end
|
|
63
|
+
# end
|
|
64
|
+
#
|
|
65
|
+
# GetText::RGetText.add_parser(FooParser)
|
|
66
|
+
def add_parser(klass)
|
|
67
|
+
@ex_parsers.insert(0, klass)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def generate_pot_header # :nodoc:
|
|
71
|
+
time = Time.now.strftime("%Y-%m-%d %H:%M")
|
|
72
|
+
off = Time.now.utc_offset
|
|
73
|
+
sign = off <= 0 ? '-' : '+'
|
|
74
|
+
time += sprintf('%s%02d%02d', sign, *(off.abs / 60).divmod(60))
|
|
75
|
+
|
|
76
|
+
<<TITLE
|
|
77
|
+
# SOME DESCRIPTIVE TITLE.
|
|
78
|
+
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
79
|
+
# This file is distributed under the same license as the PACKAGE package.
|
|
80
|
+
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
81
|
+
#
|
|
82
|
+
#, fuzzy
|
|
83
|
+
msgid ""
|
|
84
|
+
msgstr ""
|
|
85
|
+
"Project-Id-Version: PACKAGE VERSION\\n"
|
|
86
|
+
"POT-Creation-Date: #{time}\\n"
|
|
87
|
+
"PO-Revision-Date: #{time}\\n"
|
|
88
|
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n"
|
|
89
|
+
"Language-Team: LANGUAGE <LL@li.org>\\n"
|
|
90
|
+
"MIME-Version: 1.0\\n"
|
|
91
|
+
"Content-Type: text/plain; charset=UTF-8\\n"
|
|
92
|
+
"Content-Transfer-Encoding: 8bit\\n"
|
|
93
|
+
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n"
|
|
94
|
+
TITLE
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def generate_pot(ary) # :nodoc:
|
|
98
|
+
str = ""
|
|
99
|
+
ary.each do |key|
|
|
100
|
+
msgid = key.shift
|
|
101
|
+
curr_pos = MAX_LINE_LEN
|
|
102
|
+
key.each do |e|
|
|
103
|
+
if curr_pos + e.size > MAX_LINE_LEN
|
|
104
|
+
str << "\n#:"
|
|
105
|
+
curr_pos = 3
|
|
106
|
+
else
|
|
107
|
+
curr_pos += (e.size + 1)
|
|
108
|
+
end
|
|
109
|
+
str << " " << e
|
|
110
|
+
end
|
|
111
|
+
msgid.gsub!(/"/, '\"')
|
|
112
|
+
msgid.gsub!(/\r/, '')
|
|
113
|
+
if msgid.include?("\004")
|
|
114
|
+
msgctxt, msgid = msgid.split(/\004/)
|
|
115
|
+
str << "\nmsgctxt \"" << msgctxt << "\"\n"
|
|
116
|
+
else
|
|
117
|
+
str << "\n"
|
|
118
|
+
end
|
|
119
|
+
if msgid.include?("\000")
|
|
120
|
+
ids = msgid.split(/\000/)
|
|
121
|
+
str << "msgid \"" << ids[0] << "\"\n"
|
|
122
|
+
str << "msgid_plural \"" << ids[1] << "\"\n"
|
|
123
|
+
str << "msgstr[0] \"\"\n"
|
|
124
|
+
str << "msgstr[1] \"\"\n"
|
|
125
|
+
else
|
|
126
|
+
str << "msgid \"" << msgid << "\"\n"
|
|
127
|
+
str << "msgstr \"\"\n"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
str
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def normalize(ary) # :nodoc:
|
|
134
|
+
used_plural_msgs = []
|
|
135
|
+
ary.select{|item| item[0].include? "\000"}.each do |plural_msg|
|
|
136
|
+
next if used_plural_msgs.include?(plural_msg[0])
|
|
137
|
+
|
|
138
|
+
key = plural_msg[0].split("\000")[0]
|
|
139
|
+
|
|
140
|
+
ary.dup.each do |single_msg|
|
|
141
|
+
if single_msg[0] == key or
|
|
142
|
+
(single_msg[0] =~ /^#{Regexp.quote(key)}\000/ and
|
|
143
|
+
single_msg[0] != plural_msg[0])
|
|
144
|
+
if single_msg[0] != key
|
|
145
|
+
warn %Q[Warning: n_("#{plural_msg[0].gsub(/\000/, '", "')}") and n_("#{single_msg[0].gsub(/\000/, '", "')}") are duplicated. First msgid was used.]
|
|
146
|
+
used_plural_msgs << single_msg[0]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
single_msg[1..-1].each do |line_info|
|
|
150
|
+
plural_msg << line_info
|
|
151
|
+
fname = line_info.split(/:/)[0]
|
|
152
|
+
sorted = plural_msg[1..-1].select{|l| l.split(/:/)[0].include?(fname)}.collect{|l|
|
|
153
|
+
aline = l.split(/:/)
|
|
154
|
+
[aline[0], aline[1] =~ /[0-9]+/ ? aline[1].to_i : aline[1]]
|
|
155
|
+
}.sort.collect{|l| "#{l[0]}:#{l[1]}"}
|
|
156
|
+
plural_msg.delete_if{|i| sorted.include?(i)}
|
|
157
|
+
sorted.each {|i|
|
|
158
|
+
plural_msg << i
|
|
159
|
+
}
|
|
160
|
+
end
|
|
161
|
+
ary.delete(single_msg)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
ary.collect{|i| i.uniq}
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def parse(files) # :nodoc:
|
|
169
|
+
ary = []
|
|
170
|
+
files.each do |file|
|
|
171
|
+
begin
|
|
172
|
+
@ex_parsers.each do |klass|
|
|
173
|
+
if klass.target?(file)
|
|
174
|
+
ary = klass.parse(file, ary)
|
|
175
|
+
break
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
rescue
|
|
179
|
+
puts "Error occurs in " + file
|
|
180
|
+
raise
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
normalize(ary)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def check_options # :nodoc:
|
|
187
|
+
output = STDOUT
|
|
188
|
+
|
|
189
|
+
opts = OptionParser.new
|
|
190
|
+
opts.banner = _("Usage: %s input.rb [-r parser.rb] [-o output.pot]") % $0
|
|
191
|
+
opts.separator("")
|
|
192
|
+
opts.separator(_("Extract translatable strings from given input files."))
|
|
193
|
+
opts.separator("")
|
|
194
|
+
opts.separator(_("Specific options:"))
|
|
195
|
+
|
|
196
|
+
opts.on("-o", "--output=FILE", _("write output to specified file")) do |out|
|
|
197
|
+
unless FileTest.exist? out
|
|
198
|
+
output = File.new(File.expand_path(out), "w+")
|
|
199
|
+
else
|
|
200
|
+
$stderr.puts(_("File '%s' already exists.") % out)
|
|
201
|
+
exit 1
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
opts.on("-r", "--require=library", _("require the library before executing rgettext")) do |out|
|
|
206
|
+
require out
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
opts.on("-d", "--debug", _("run in debugging mode")) do
|
|
210
|
+
$DEBUG = true
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
opts.on_tail("--version", _("display version information and exit")) do
|
|
214
|
+
puts "#{$0} #{VERSION} (#{DATE})"
|
|
215
|
+
puts "#{File.join(Config::CONFIG["bindir"], Config::CONFIG["RUBY_INSTALL_NAME"])} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
|
|
216
|
+
exit
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
opts.parse!(ARGV)
|
|
220
|
+
|
|
221
|
+
if ARGV.size == 0
|
|
222
|
+
puts opts.help
|
|
223
|
+
exit 1
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
[ARGV, output]
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def run(targetfiles = nil, out = STDOUT) # :nodoc:
|
|
230
|
+
if targetfiles.is_a? String
|
|
231
|
+
targetfiles = [targetfiles]
|
|
232
|
+
elsif ! targetfiles
|
|
233
|
+
targetfiles, out = check_options
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
if targetfiles.size == 0
|
|
237
|
+
raise ArgumentError, _("no input files")
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
if out.is_a? String
|
|
241
|
+
File.open(File.expand_path(out), "w+") do |file|
|
|
242
|
+
file.puts generate_pot_header
|
|
243
|
+
file.puts generate_pot(parse(targetfiles))
|
|
244
|
+
end
|
|
245
|
+
else
|
|
246
|
+
out.puts generate_pot_header
|
|
247
|
+
out.puts generate_pot(parse(targetfiles))
|
|
248
|
+
end
|
|
249
|
+
self
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
module_function
|
|
254
|
+
# Creates a po-file from targetfiles(ruby-script-files, ActiveRecord, .rhtml files, glade-2 XML files),
|
|
255
|
+
# then output the result to out. If no parameter is set, it behaves same as command line tools(rgettet).
|
|
256
|
+
#
|
|
257
|
+
# This function is a part of GetText.create_pofiles.
|
|
258
|
+
# Usually you don't need to call this function directly.
|
|
259
|
+
#
|
|
260
|
+
# *Note* for ActiveRecord, you need to run your database server and configure the config/database.yml
|
|
261
|
+
# correctly before execute this function.
|
|
262
|
+
#
|
|
263
|
+
# * targetfiles: An Array of po-files or nil.
|
|
264
|
+
# * out: output IO or output path.
|
|
265
|
+
# * Returns: self
|
|
266
|
+
def rgettext(targetfiles = nil, out = STDOUT)
|
|
267
|
+
RGetText.run(targetfiles, out)
|
|
268
|
+
self
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
if $0 == __FILE__
|
|
273
|
+
GetText.rgettext
|
|
274
|
+
# GetText.rgettext($0, "tmp.txt")
|
|
275
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
rmsgfmt.rb - Generate a .mo
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2003-2009 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 'optparse'
|
|
11
|
+
require 'fileutils'
|
|
12
|
+
require 'gettext'
|
|
13
|
+
require 'gettext/poparser'
|
|
14
|
+
require 'rbconfig'
|
|
15
|
+
|
|
16
|
+
module GetText
|
|
17
|
+
|
|
18
|
+
module RMsgfmt #:nodoc:
|
|
19
|
+
extend GetText
|
|
20
|
+
|
|
21
|
+
bindtextdomain "rgettext"
|
|
22
|
+
|
|
23
|
+
module_function
|
|
24
|
+
def run(targetfile = nil, output_path = nil) # :nodoc:
|
|
25
|
+
unless targetfile
|
|
26
|
+
targetfile, output_path = check_options
|
|
27
|
+
end
|
|
28
|
+
unless targetfile
|
|
29
|
+
raise ArgumentError, _("no input files")
|
|
30
|
+
end
|
|
31
|
+
unless output_path
|
|
32
|
+
output_path = "messages.mo"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
parser = PoParser.new
|
|
36
|
+
data = MOFile.new
|
|
37
|
+
parser.parse(File.open(targetfile).read, data)
|
|
38
|
+
data.save_to_file(output_path)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def check_options # :nodoc:
|
|
42
|
+
output = nil
|
|
43
|
+
|
|
44
|
+
opts = OptionParser.new
|
|
45
|
+
opts.banner = _("Usage: %s input.po [-o output.mo]" % $0)
|
|
46
|
+
opts.separator("")
|
|
47
|
+
opts.separator(_("Generate binary message catalog from textual translation description."))
|
|
48
|
+
opts.separator("")
|
|
49
|
+
opts.separator(_("Specific options:"))
|
|
50
|
+
|
|
51
|
+
opts.on("-o", "--output=FILE", _("write output to specified file")) do |out|
|
|
52
|
+
output = out
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
opts.on_tail("--version", _("display version information and exit")) do
|
|
56
|
+
puts "#{$0} #{GetText::VERSION}"
|
|
57
|
+
puts "#{File.join(Config::CONFIG["bindir"], Config::CONFIG["RUBY_INSTALL_NAME"])} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
|
|
58
|
+
exit
|
|
59
|
+
end
|
|
60
|
+
opts.parse!(ARGV)
|
|
61
|
+
|
|
62
|
+
if ARGV.size == 0
|
|
63
|
+
puts opts.help
|
|
64
|
+
exit 1
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
[ARGV[0], output]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
module_function
|
|
72
|
+
# Creates a mo-file from a targetfile(po-file), then output the result to out.
|
|
73
|
+
# If no parameter is set, it behaves same as command line tools(rmsgfmt).
|
|
74
|
+
# * targetfile: An Array of po-files or nil.
|
|
75
|
+
# * output_path: output path.
|
|
76
|
+
# * Returns: the MOFile object.
|
|
77
|
+
def rmsgfmt(targetfile = nil, output_path = nil)
|
|
78
|
+
RMsgfmt.run(targetfile, output_path)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
if $0 == __FILE__ then
|
|
83
|
+
GetText.rmsgfmt
|
|
84
|
+
end
|
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
rmsgmerge.rb - Merge old .po to new .po
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2005-2009 Masao Mutoh
|
|
5
|
+
Copyright (C) 2005,2006 speakillof
|
|
6
|
+
|
|
7
|
+
You may redistribute it and/or modify it under the same
|
|
8
|
+
license terms as Ruby.
|
|
9
|
+
=end
|
|
10
|
+
|
|
11
|
+
require 'optparse'
|
|
12
|
+
require 'gettext'
|
|
13
|
+
require 'gettext/poparser'
|
|
14
|
+
require 'rbconfig'
|
|
15
|
+
|
|
16
|
+
module GetText
|
|
17
|
+
|
|
18
|
+
module RMsgMerge
|
|
19
|
+
|
|
20
|
+
class PoData #:nodoc:
|
|
21
|
+
|
|
22
|
+
attr_reader :msgids
|
|
23
|
+
|
|
24
|
+
def initialize
|
|
25
|
+
@msgid2msgstr = {}
|
|
26
|
+
@msgid2comment = {}
|
|
27
|
+
@msgids = []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def set_comment(msgid_or_sym, comment)
|
|
31
|
+
@msgid2comment[msgid_or_sym] = comment
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def msgstr(msgid)
|
|
35
|
+
@msgid2msgstr[msgid]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def comment(msgid)
|
|
39
|
+
@msgid2comment[msgid]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def [](msgid)
|
|
43
|
+
@msgid2msgstr[msgid]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def []=(msgid, msgstr)
|
|
47
|
+
# Retain the order
|
|
48
|
+
unless @msgid2msgstr[msgid]
|
|
49
|
+
@msgids << msgid
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
@msgid2msgstr[msgid] = msgstr
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def each_msgid
|
|
56
|
+
arr = @msgids.delete_if{|i| Symbol === i or i == ''}
|
|
57
|
+
arr.each do |i|
|
|
58
|
+
yield i
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def msgid?(msgid)
|
|
63
|
+
!(Symbol === msgid) and @msgid2msgstr[msgid] and (msgid != '')
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Is it necessary to implement this method?
|
|
67
|
+
def search_msgid_fuzzy(msgid, used_msgids)
|
|
68
|
+
nil
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def nplural
|
|
72
|
+
unless @msgid2msgstr['']
|
|
73
|
+
return 0
|
|
74
|
+
else
|
|
75
|
+
if /\s*nplural\s*=\s*(\d+)/ =~ @msgid2msgstr['']
|
|
76
|
+
return $1.to_i
|
|
77
|
+
else
|
|
78
|
+
return 0
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def generate_po
|
|
85
|
+
str = ''
|
|
86
|
+
str << generate_po_header
|
|
87
|
+
|
|
88
|
+
self.each_msgid do |id|
|
|
89
|
+
str << self.generate_po_entry(id)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
str << @msgid2comment[:last]
|
|
93
|
+
str
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def generate_po_header
|
|
97
|
+
str = ""
|
|
98
|
+
|
|
99
|
+
str << @msgid2comment[''].strip << "\n"
|
|
100
|
+
str << 'msgid ""' << "\n"
|
|
101
|
+
str << 'msgstr ""' << "\n"
|
|
102
|
+
msgstr = @msgid2msgstr[''].gsub(/"/, '\"').gsub(/\r/, '')
|
|
103
|
+
msgstr = msgstr.gsub(/^(.*)$/, '"\1\n"')
|
|
104
|
+
str << msgstr
|
|
105
|
+
str << "\n"
|
|
106
|
+
|
|
107
|
+
str
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def generate_po_entry(msgid)
|
|
111
|
+
str = ""
|
|
112
|
+
str << @msgid2comment[msgid]
|
|
113
|
+
if str[-1] != "\n"[0]
|
|
114
|
+
str << "\n"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
id = msgid.gsub(/"/, '\"').gsub(/\r/, '')
|
|
118
|
+
msgstr = @msgid2msgstr[msgid].gsub(/"/, '\"').gsub(/\r/, '')
|
|
119
|
+
|
|
120
|
+
if id.include?("\000")
|
|
121
|
+
ids = id.split(/\000/)
|
|
122
|
+
str << "msgid " << __conv(ids[0]) << "\n"
|
|
123
|
+
ids[1..-1].each do |single_id|
|
|
124
|
+
str << "msgid_plural " << __conv(single_id) << "\n"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
msgstr.split("\000").each_with_index do |m, n|
|
|
128
|
+
str << "msgstr[#{n}] " << __conv(m) << "\n"
|
|
129
|
+
end
|
|
130
|
+
else
|
|
131
|
+
str << "msgid " << __conv(id) << "\n"
|
|
132
|
+
str << "msgstr " << __conv(msgstr) << "\n"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
str << "\n"
|
|
136
|
+
str
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def __conv(str)
|
|
140
|
+
s = ''
|
|
141
|
+
|
|
142
|
+
if str.count("\n") > 1
|
|
143
|
+
s << '""' << "\n"
|
|
144
|
+
s << str.gsub(/^(.*)$/, '"\1\n"')
|
|
145
|
+
else
|
|
146
|
+
s << '"' << str.sub("\n", "\\n") << '"'
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
s.rstrip
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
class Merger #:nodoc:
|
|
155
|
+
|
|
156
|
+
# From GNU gettext source.
|
|
157
|
+
#
|
|
158
|
+
# Merge the reference with the definition: take the #. and
|
|
159
|
+
# #: comments from the reference, take the # comments from
|
|
160
|
+
# the definition, take the msgstr from the definition. Add
|
|
161
|
+
# this merged entry to the output message list.
|
|
162
|
+
DOT_COMMENT_RE = /\A#\./
|
|
163
|
+
SEMICOLON_COMMENT_RE = /\A#\:/
|
|
164
|
+
FUZZY_RE = /\A#\,/
|
|
165
|
+
NOT_SPECIAL_COMMENT_RE = /\A#([^:.,]|\z)/
|
|
166
|
+
|
|
167
|
+
CRLF_RE = /\r?\n/
|
|
168
|
+
POT_DATE_EXTRACT_RE = /POT-Creation-Date:\s*(.*)?\s*$/
|
|
169
|
+
POT_DATE_RE = /POT-Creation-Date:.*?$/
|
|
170
|
+
|
|
171
|
+
def merge(definition, reference)
|
|
172
|
+
# deep copy
|
|
173
|
+
result = Marshal.load( Marshal.dump(reference) )
|
|
174
|
+
|
|
175
|
+
used = []
|
|
176
|
+
merge_header(result, definition)
|
|
177
|
+
|
|
178
|
+
result.each_msgid do |msgid|
|
|
179
|
+
if definition.msgid?(msgid)
|
|
180
|
+
used << msgid
|
|
181
|
+
merge_message(msgid, result, msgid, definition)
|
|
182
|
+
elsif other_msgid = definition.search_msgid_fuzzy(msgid, used)
|
|
183
|
+
used << other_msgid
|
|
184
|
+
merge_fuzzy_message(msgid, result, other_msgid, definition)
|
|
185
|
+
elsif msgid.index("\000") and ( reference.msgstr(msgid).gsub("\000", '') == '' )
|
|
186
|
+
# plural
|
|
187
|
+
result[msgid] = "\000" * definition.nplural
|
|
188
|
+
else
|
|
189
|
+
change_reference_comment(msgid, result)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
###################################################################
|
|
194
|
+
# msgids which are not used in reference are handled as obsolete. #
|
|
195
|
+
###################################################################
|
|
196
|
+
last_comment = result.comment(:last) || ''
|
|
197
|
+
definition.each_msgid do |msgid|
|
|
198
|
+
unless used.include?(msgid)
|
|
199
|
+
last_comment << "\n"
|
|
200
|
+
last_comment << definition.generate_po_entry(msgid).strip.gsub(/^/, '#. ')
|
|
201
|
+
last_comment << "\n"
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
result.set_comment(:last, last_comment)
|
|
205
|
+
|
|
206
|
+
result
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def merge_message(msgid, target, def_msgid, definition)
|
|
210
|
+
merge_comment(msgid, target, def_msgid, definition)
|
|
211
|
+
|
|
212
|
+
############################################
|
|
213
|
+
# check mismatch of msgid and msgid_plural #
|
|
214
|
+
############################################
|
|
215
|
+
def_msgstr = definition[def_msgid]
|
|
216
|
+
if msgid.index("\000")
|
|
217
|
+
if def_msgstr.index("\000")
|
|
218
|
+
# OK
|
|
219
|
+
target[msgid] = def_msgstr
|
|
220
|
+
else
|
|
221
|
+
# NG
|
|
222
|
+
s = ''
|
|
223
|
+
definition.nplural.times {
|
|
224
|
+
s << def_msgstr
|
|
225
|
+
s << "\000"
|
|
226
|
+
}
|
|
227
|
+
target[msgid] = s
|
|
228
|
+
end
|
|
229
|
+
else
|
|
230
|
+
if def_msgstr.index("\000")
|
|
231
|
+
# NG
|
|
232
|
+
target[msgid] = def_msgstr.split("\000")[0]
|
|
233
|
+
else
|
|
234
|
+
# OK
|
|
235
|
+
target[msgid] = def_msgstr
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# for the future
|
|
241
|
+
def merge_fuzzy_message(msgid, target, def_msgid, definition)
|
|
242
|
+
merge_message(msgid, target, def_msgid, definition)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def merge_comment(msgid, target, def_msgid, definition)
|
|
246
|
+
ref_comment = target.comment(msgid)
|
|
247
|
+
def_comment = definition.comment(def_msgid)
|
|
248
|
+
|
|
249
|
+
normal_comment = []
|
|
250
|
+
dot_comment = []
|
|
251
|
+
semi_comment = []
|
|
252
|
+
is_fuzzy = false
|
|
253
|
+
|
|
254
|
+
def_comment.split(CRLF_RE).each do |l|
|
|
255
|
+
if NOT_SPECIAL_COMMENT_RE =~ l
|
|
256
|
+
normal_comment << l
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
ref_comment.split(CRLF_RE).each do |l|
|
|
261
|
+
if DOT_COMMENT_RE =~ l
|
|
262
|
+
dot_comment << l
|
|
263
|
+
elsif SEMICOLON_COMMENT_RE =~ l
|
|
264
|
+
semi_comment << l
|
|
265
|
+
elsif FUZZY_RE =~ l
|
|
266
|
+
is_fuzzy = true
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
str = format_comment(normal_comment, dot_comment, semi_comment, is_fuzzy)
|
|
271
|
+
target.set_comment(msgid, str)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def change_reference_comment(msgid, podata)
|
|
275
|
+
normal_comment = []
|
|
276
|
+
dot_comment = []
|
|
277
|
+
semi_comment = []
|
|
278
|
+
is_fuzzy = false
|
|
279
|
+
|
|
280
|
+
podata.comment(msgid).split(CRLF_RE).each do |l|
|
|
281
|
+
if DOT_COMMENT_RE =~ l
|
|
282
|
+
dot_comment << l
|
|
283
|
+
elsif SEMICOLON_COMMENT_RE =~ l
|
|
284
|
+
semi_comment << l
|
|
285
|
+
elsif FUZZY_RE =~ l
|
|
286
|
+
is_fuzzy = true
|
|
287
|
+
else
|
|
288
|
+
normal_comment << l
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
str = format_comment(normal_comment, dot_comment, semi_comment, is_fuzzy)
|
|
293
|
+
podata.set_comment(msgid, str)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def format_comment(normal_comment, dot_comment, semi_comment, is_fuzzy)
|
|
297
|
+
str = ''
|
|
298
|
+
|
|
299
|
+
str << normal_comment.join("\n").gsub(/^#(\s*)/){|sss|
|
|
300
|
+
if $1 == ""
|
|
301
|
+
"# "
|
|
302
|
+
else
|
|
303
|
+
sss
|
|
304
|
+
end
|
|
305
|
+
}
|
|
306
|
+
if normal_comment.size > 0
|
|
307
|
+
str << "\n"
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
str << dot_comment.join("\n").gsub(/^#.(\s*)/){|sss|
|
|
311
|
+
if $1 == ""
|
|
312
|
+
"#. "
|
|
313
|
+
else
|
|
314
|
+
sss
|
|
315
|
+
end
|
|
316
|
+
}
|
|
317
|
+
if dot_comment.size > 0
|
|
318
|
+
str << "\n"
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
str << semi_comment.join("\n").gsub(/^#:\s*/, "#: ")
|
|
322
|
+
if semi_comment.size > 0
|
|
323
|
+
str << "\n"
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
if is_fuzzy
|
|
327
|
+
str << "#, fuzzy\n"
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
str
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def merge_header(target, definition)
|
|
334
|
+
merge_comment('', target, '', definition)
|
|
335
|
+
|
|
336
|
+
msg = target.msgstr('')
|
|
337
|
+
def_msg = definition.msgstr('')
|
|
338
|
+
if POT_DATE_EXTRACT_RE =~ msg
|
|
339
|
+
time = $1
|
|
340
|
+
def_msg = def_msg.sub(POT_DATE_RE, "POT-Creation-Date: #{time}")
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
target[''] = def_msg
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
module GetText::RMsgMerge #:nodoc:
|
|
353
|
+
|
|
354
|
+
class Config #:nodoc:
|
|
355
|
+
|
|
356
|
+
attr_accessor :defpo, :refpot, :output, :fuzzy, :update
|
|
357
|
+
|
|
358
|
+
# update mode options
|
|
359
|
+
attr_accessor :backup, :suffix
|
|
360
|
+
|
|
361
|
+
=begin
|
|
362
|
+
The result is written back to def.po.
|
|
363
|
+
--backup=CONTROL make a backup of def.po
|
|
364
|
+
--suffix=SUFFIX override the usual backup suffix
|
|
365
|
+
The version control method may be selected via the --backup option or through
|
|
366
|
+
the VERSION_CONTROL environment variable. Here are the values:
|
|
367
|
+
none, off never make backups (even if --backup is given)
|
|
368
|
+
numbered, t make numbered backups
|
|
369
|
+
existing, nil numbered if numbered backups exist, simple otherwise
|
|
370
|
+
simple, never always make simple backups
|
|
371
|
+
The backup suffix is `~', unless set with --suffix or the SIMPLE_BACKUP_SUFFIX
|
|
372
|
+
environment variable.
|
|
373
|
+
=end
|
|
374
|
+
|
|
375
|
+
def initialize
|
|
376
|
+
@output = STDOUT
|
|
377
|
+
@fuzzy = nil
|
|
378
|
+
@update = nil
|
|
379
|
+
@backup = ENV["VERSION_CONTROL"]
|
|
380
|
+
@suffix= ENV["SIMPLE_BACKUP_SUFFIX"] || "~"
|
|
381
|
+
@input_dirs = ["."]
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
module GetText
|
|
389
|
+
|
|
390
|
+
module RMsgMerge
|
|
391
|
+
extend GetText
|
|
392
|
+
|
|
393
|
+
bindtextdomain("rgettext")
|
|
394
|
+
|
|
395
|
+
# constant values
|
|
396
|
+
VERSION = GetText::VERSION
|
|
397
|
+
DATE = %w($Date: 2007/07/21 15:03:05 $)[1]
|
|
398
|
+
|
|
399
|
+
module_function
|
|
400
|
+
|
|
401
|
+
def check_options(config)
|
|
402
|
+
opts = OptionParser.new
|
|
403
|
+
opts.banner = _("Usage: %s def.po ref.pot [-o output.pot]") % $0
|
|
404
|
+
#opts.summary_width = 80
|
|
405
|
+
opts.separator("")
|
|
406
|
+
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."))
|
|
407
|
+
opts.separator("")
|
|
408
|
+
opts.separator(_("Specific options:"))
|
|
409
|
+
|
|
410
|
+
opts.on("-o", "--output=FILE", _("write output to specified file")) do |out|
|
|
411
|
+
unless FileTest.exist? out
|
|
412
|
+
config.output = out
|
|
413
|
+
else
|
|
414
|
+
#$stderr.puts(_("File '%s' has already existed.") % out)
|
|
415
|
+
#exit 1
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
#opts.on("-F", "--fuzzy-matching")
|
|
420
|
+
|
|
421
|
+
opts.on_tail("--version", _("display version information and exit")) do
|
|
422
|
+
puts "#{$0} #{VERSION} (#{DATE})"
|
|
423
|
+
puts "#{File.join(::Config::CONFIG["bindir"], ::Config::CONFIG["RUBY_INSTALL_NAME"])} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
|
|
424
|
+
exit
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
opts.parse!(ARGV)
|
|
428
|
+
|
|
429
|
+
if ARGV.size != 2
|
|
430
|
+
puts opts.help
|
|
431
|
+
exit 1
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
config.defpo = ARGV[0]
|
|
435
|
+
config.refpot = ARGV[1]
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
def run(reference = nil, definition = nil, out = STDOUT)
|
|
439
|
+
config = GetText::RMsgMerge::Config.new
|
|
440
|
+
config.refpot = reference
|
|
441
|
+
config.defpo = definition
|
|
442
|
+
config.output = out
|
|
443
|
+
|
|
444
|
+
check_options(config)
|
|
445
|
+
|
|
446
|
+
if config.defpo.nil?
|
|
447
|
+
raise ArgumentError, _("definition po is not given.")
|
|
448
|
+
elsif config.refpot.nil?
|
|
449
|
+
raise ArgumentError, _("reference pot is not given.")
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
parser = PoParser.new
|
|
453
|
+
defstr = nil
|
|
454
|
+
refstr = nil
|
|
455
|
+
File.open(config.defpo){|f| defstr = f.read}
|
|
456
|
+
File.open(config.refpot){|f| refstr = f.read}
|
|
457
|
+
defpo = parser.parse(defstr, PoData.new, false)
|
|
458
|
+
refpot = parser.parse(refstr, PoData.new, false)
|
|
459
|
+
|
|
460
|
+
m = Merger.new
|
|
461
|
+
result = m.merge(defpo, refpot)
|
|
462
|
+
p result if $DEBUG
|
|
463
|
+
print result.generate_po if $DEBUG
|
|
464
|
+
|
|
465
|
+
begin
|
|
466
|
+
if out.is_a? String
|
|
467
|
+
File.open(File.expand_path(out), "w+") do |file|
|
|
468
|
+
file.write(result.generate_po)
|
|
469
|
+
end
|
|
470
|
+
else
|
|
471
|
+
out.puts(result.generate_po)
|
|
472
|
+
end
|
|
473
|
+
ensure
|
|
474
|
+
out.close
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
module GetText
|
|
485
|
+
|
|
486
|
+
module_function
|
|
487
|
+
|
|
488
|
+
# Experimental
|
|
489
|
+
def rmsgmerge(reference = nil, definition = nil, out = STDOUT)
|
|
490
|
+
RMsgMerge.run(reference, definition, out)
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
if $0 == __FILE__ then
|
|
498
|
+
require 'pp'
|
|
499
|
+
|
|
500
|
+
#parser = GetText::RMsgMerge::PoParser.new;
|
|
501
|
+
#parser = GetText::PoParser.new;
|
|
502
|
+
#pp parser.parse(ARGF.read)
|
|
503
|
+
|
|
504
|
+
GetText.rmsgmerge
|
|
505
|
+
end
|