ofm_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 +78 -0
- data/README.rdoc +245 -0
- data/Rakefile +234 -0
- data/bin/rgettext +23 -0
- data/bin/rmsgfmt +22 -0
- data/bin/rmsgmerge +22 -0
- data/gettext.gemspec +40 -0
- data/lib/gettext/cgi.rb +39 -0
- data/lib/gettext/core_ext/iconv.rb +110 -0
- data/lib/gettext/core_ext/string.rb +86 -0
- data/lib/gettext/parser/erb.rb +5 -0
- data/lib/gettext/parser/glade.rb +5 -0
- data/lib/gettext/parser/ruby.rb +172 -0
- data/lib/gettext/tools/rgettext.rb +251 -0
- data/lib/gettext/tools/rmsgfmt.rb +86 -0
- data/lib/gettext/tools/rmsgmerge.rb +500 -0
- data/lib/gettext/tools.rb +197 -0
- data/lib/gettext/utils.rb +39 -0
- data/lib/gettext/version.rb +12 -0
- data/lib/gettext.rb +312 -0
- data/po/bg/rgettext.po +139 -0
- data/po/bs/rgettext.po +139 -0
- data/po/ca/rgettext.po +138 -0
- data/po/cs/rgettext.po +140 -0
- data/po/de/rgettext.po +146 -0
- data/po/el/rgettext.po +137 -0
- data/po/eo/rgettext.po +138 -0
- data/po/es/rgettext.po +139 -0
- data/po/et/rgettext.po +136 -0
- data/po/fr/rgettext.po +142 -0
- data/po/hr/rgettext.po +139 -0
- data/po/hu/rgettext.po +138 -0
- data/po/it/rgettext.po +138 -0
- data/po/ja/rgettext.po +140 -0
- data/po/ko/rgettext.po +137 -0
- data/po/lv/rgettext.po +139 -0
- data/po/nb/rgettext.po +140 -0
- data/po/nl/rgettext.po +138 -0
- data/po/pt_BR/rgettext.po +141 -0
- data/po/rgettext.pot +129 -0
- data/po/ru/rgettext.po +140 -0
- data/po/sr/rgettext.po +139 -0
- data/po/sv/rgettext.po +131 -0
- data/po/vi/rgettext.po +137 -0
- data/po/zh/rgettext.po +138 -0
- data/po/zh_TW/rgettext.po +137 -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 +18 -0
- data/samples/cgi/http.rb +49 -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/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 +6 -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 +13 -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 +217 -0
- data/test/README +1 -0
- data/test/Rakefile +17 -0
- data/test/po/cr/plural.po +23 -0
- data/test/po/da/plural.po +22 -0
- data/test/po/da/plural_error.po +22 -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/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/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 +88 -0
- data/test/test_gettext.rb +322 -0
- data/test/test_parser.rb +160 -0
- data/test/test_string.rb +67 -0
- data/test/test_textdomain_multi.rb +82 -0
- data/test/test_textdomain_toplevel.rb +44 -0
- data/test/testlib/N_.rb +68 -0
- data/test/testlib/erb.rhtml +15 -0
- data/test/testlib/erb.rxml +16 -0
- data/test/testlib/gettext.rb +115 -0
- data/test/testlib/gladeparser.glade +183 -0
- data/test/testlib/helper.rb +13 -0
- data/test/testlib/multi_textdomain.rb +133 -0
- data/test/testlib/ngettext.rb +81 -0
- data/test/testlib/npgettext.rb +33 -0
- data/test/testlib/nsgettext.rb +44 -0
- data/test/testlib/pgettext.rb +38 -0
- data/test/testlib/sgettext.rb +48 -0
- data/test/testlib/simple.rb +16 -0
- metadata +475 -0
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
rmsgmerge.rb - Merge old .po to new .po
|
|
5
|
+
|
|
6
|
+
Copyright (C) 2005-2009 Masao Mutoh
|
|
7
|
+
Copyright (C) 2005,2006 speakillof
|
|
8
|
+
|
|
9
|
+
You may redistribute it and/or modify it under the same
|
|
10
|
+
license terms as Ruby or LGPL.
|
|
11
|
+
=end
|
|
12
|
+
|
|
13
|
+
require 'optparse'
|
|
14
|
+
require 'gettext'
|
|
15
|
+
require 'gettext/tools/poparser'
|
|
16
|
+
require 'rbconfig'
|
|
17
|
+
|
|
18
|
+
module GetText
|
|
19
|
+
|
|
20
|
+
module RMsgMerge
|
|
21
|
+
|
|
22
|
+
class PoData #:nodoc:
|
|
23
|
+
|
|
24
|
+
attr_reader :msgids
|
|
25
|
+
|
|
26
|
+
def initialize
|
|
27
|
+
@msgid2msgstr = {}
|
|
28
|
+
@msgid2comment = {}
|
|
29
|
+
@msgids = []
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def set_comment(msgid_or_sym, comment)
|
|
33
|
+
@msgid2comment[msgid_or_sym] = comment
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def msgstr(msgid)
|
|
37
|
+
@msgid2msgstr[msgid]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def comment(msgid)
|
|
41
|
+
@msgid2comment[msgid]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def [](msgid)
|
|
45
|
+
@msgid2msgstr[msgid]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def []=(msgid, msgstr)
|
|
49
|
+
# Retain the order
|
|
50
|
+
unless @msgid2msgstr[msgid]
|
|
51
|
+
@msgids << msgid
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
@msgid2msgstr[msgid] = msgstr
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def each_msgid
|
|
58
|
+
arr = @msgids.delete_if{|i| Symbol === i or i == ''}
|
|
59
|
+
arr.each do |i|
|
|
60
|
+
yield i
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def msgid?(msgid)
|
|
65
|
+
!(Symbol === msgid) and @msgid2msgstr[msgid] and (msgid != '')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Is it necessary to implement this method?
|
|
69
|
+
def search_msgid_fuzzy(msgid, used_msgids)
|
|
70
|
+
nil
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def nplural
|
|
74
|
+
unless @msgid2msgstr['']
|
|
75
|
+
return 0
|
|
76
|
+
else
|
|
77
|
+
if /\s*nplural\s*=\s*(\d+)/ =~ @msgid2msgstr['']
|
|
78
|
+
return $1.to_i
|
|
79
|
+
else
|
|
80
|
+
return 0
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def generate_po
|
|
87
|
+
str = ''
|
|
88
|
+
str << generate_po_header
|
|
89
|
+
|
|
90
|
+
self.each_msgid do |id|
|
|
91
|
+
str << self.generate_po_entry(id)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
str << @msgid2comment[:last]
|
|
95
|
+
str
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def generate_po_header
|
|
99
|
+
str = ""
|
|
100
|
+
|
|
101
|
+
str << @msgid2comment[''].strip << "\n"
|
|
102
|
+
str << 'msgid ""' << "\n"
|
|
103
|
+
str << 'msgstr ""' << "\n"
|
|
104
|
+
msgstr = @msgid2msgstr[''].gsub(/"/, '\"').gsub(/\r/, '')
|
|
105
|
+
msgstr = msgstr.gsub(/^(.*)$/, '"\1\n"')
|
|
106
|
+
str << msgstr
|
|
107
|
+
str << "\n"
|
|
108
|
+
|
|
109
|
+
str
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def generate_po_entry(msgid)
|
|
113
|
+
str = ""
|
|
114
|
+
str << @msgid2comment[msgid]
|
|
115
|
+
if str[-1] != "\n"[0]
|
|
116
|
+
str << "\n"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
id = msgid.gsub(/"/, '\"').gsub(/\r/, '')
|
|
120
|
+
msgstr = @msgid2msgstr[msgid].gsub(/"/, '\"').gsub(/\r/, '')
|
|
121
|
+
|
|
122
|
+
if id.include?("\000")
|
|
123
|
+
ids = id.split(/\000/)
|
|
124
|
+
str << "msgid " << __conv(ids[0]) << "\n"
|
|
125
|
+
ids[1..-1].each do |single_id|
|
|
126
|
+
str << "msgid_plural " << __conv(single_id) << "\n"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
msgstr.split("\000").each_with_index do |m, n|
|
|
130
|
+
str << "msgstr[#{n}] " << __conv(m) << "\n"
|
|
131
|
+
end
|
|
132
|
+
else
|
|
133
|
+
str << "msgid " << __conv(id) << "\n"
|
|
134
|
+
str << "msgstr " << __conv(msgstr) << "\n"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
str << "\n"
|
|
138
|
+
str
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def __conv(str)
|
|
142
|
+
s = ''
|
|
143
|
+
|
|
144
|
+
if str.count("\n") > 1
|
|
145
|
+
s << '""' << "\n"
|
|
146
|
+
s << str.gsub(/^(.*)$/, '"\1\n"')
|
|
147
|
+
else
|
|
148
|
+
s << '"' << str.sub("\n", "\\n") << '"'
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
s.rstrip
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
class Merger #:nodoc:
|
|
157
|
+
|
|
158
|
+
# From GNU gettext source.
|
|
159
|
+
#
|
|
160
|
+
# Merge the reference with the definition: take the #. and
|
|
161
|
+
# #: comments from the reference, take the # comments from
|
|
162
|
+
# the definition, take the msgstr from the definition. Add
|
|
163
|
+
# this merged entry to the output message list.
|
|
164
|
+
DOT_COMMENT_RE = /\A#\./
|
|
165
|
+
SEMICOLON_COMMENT_RE = /\A#\:/
|
|
166
|
+
FUZZY_RE = /\A#\,/
|
|
167
|
+
NOT_SPECIAL_COMMENT_RE = /\A#([^:.,]|\z)/
|
|
168
|
+
|
|
169
|
+
CRLF_RE = /\r?\n/
|
|
170
|
+
POT_DATE_EXTRACT_RE = /POT-Creation-Date:\s*(.*)?\s*$/
|
|
171
|
+
POT_DATE_RE = /POT-Creation-Date:.*?$/
|
|
172
|
+
|
|
173
|
+
def merge(definition, reference)
|
|
174
|
+
# deep copy
|
|
175
|
+
result = Marshal.load( Marshal.dump(reference) )
|
|
176
|
+
|
|
177
|
+
used = []
|
|
178
|
+
merge_header(result, definition)
|
|
179
|
+
|
|
180
|
+
result.each_msgid do |msgid|
|
|
181
|
+
if definition.msgid?(msgid)
|
|
182
|
+
used << msgid
|
|
183
|
+
merge_message(msgid, result, msgid, definition)
|
|
184
|
+
elsif other_msgid = definition.search_msgid_fuzzy(msgid, used)
|
|
185
|
+
used << other_msgid
|
|
186
|
+
merge_fuzzy_message(msgid, result, other_msgid, definition)
|
|
187
|
+
elsif msgid.index("\000") and ( reference.msgstr(msgid).gsub("\000", '') == '' )
|
|
188
|
+
# plural
|
|
189
|
+
result[msgid] = "\000" * definition.nplural
|
|
190
|
+
else
|
|
191
|
+
change_reference_comment(msgid, result)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
###################################################################
|
|
196
|
+
# msgids which are not used in reference are handled as obsolete. #
|
|
197
|
+
###################################################################
|
|
198
|
+
last_comment = result.comment(:last) || ''
|
|
199
|
+
definition.each_msgid do |msgid|
|
|
200
|
+
unless used.include?(msgid)
|
|
201
|
+
last_comment << "\n"
|
|
202
|
+
last_comment << definition.generate_po_entry(msgid).strip.gsub(/^/, '#. ')
|
|
203
|
+
last_comment << "\n"
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
result.set_comment(:last, last_comment)
|
|
207
|
+
|
|
208
|
+
result
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def merge_message(msgid, target, def_msgid, definition)
|
|
212
|
+
merge_comment(msgid, target, def_msgid, definition)
|
|
213
|
+
|
|
214
|
+
############################################
|
|
215
|
+
# check mismatch of msgid and msgid_plural #
|
|
216
|
+
############################################
|
|
217
|
+
def_msgstr = definition[def_msgid]
|
|
218
|
+
if msgid.index("\000")
|
|
219
|
+
if def_msgstr.index("\000")
|
|
220
|
+
# OK
|
|
221
|
+
target[msgid] = def_msgstr
|
|
222
|
+
else
|
|
223
|
+
# NG
|
|
224
|
+
s = ''
|
|
225
|
+
definition.nplural.times {
|
|
226
|
+
s << def_msgstr
|
|
227
|
+
s << "\000"
|
|
228
|
+
}
|
|
229
|
+
target[msgid] = s
|
|
230
|
+
end
|
|
231
|
+
else
|
|
232
|
+
if def_msgstr.index("\000")
|
|
233
|
+
# NG
|
|
234
|
+
target[msgid] = def_msgstr.split("\000")[0]
|
|
235
|
+
else
|
|
236
|
+
# OK
|
|
237
|
+
target[msgid] = def_msgstr
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# for the future
|
|
243
|
+
def merge_fuzzy_message(msgid, target, def_msgid, definition)
|
|
244
|
+
merge_message(msgid, target, def_msgid, definition)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def merge_comment(msgid, target, def_msgid, definition)
|
|
248
|
+
ref_comment = target.comment(msgid)
|
|
249
|
+
def_comment = definition.comment(def_msgid)
|
|
250
|
+
|
|
251
|
+
normal_comment = []
|
|
252
|
+
dot_comment = []
|
|
253
|
+
semi_comment = []
|
|
254
|
+
is_fuzzy = false
|
|
255
|
+
|
|
256
|
+
def_comment.split(CRLF_RE).each do |l|
|
|
257
|
+
if NOT_SPECIAL_COMMENT_RE =~ l
|
|
258
|
+
normal_comment << l
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
ref_comment.split(CRLF_RE).each do |l|
|
|
263
|
+
if DOT_COMMENT_RE =~ l
|
|
264
|
+
dot_comment << l
|
|
265
|
+
elsif SEMICOLON_COMMENT_RE =~ l
|
|
266
|
+
semi_comment << l
|
|
267
|
+
elsif FUZZY_RE =~ l
|
|
268
|
+
is_fuzzy = true
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
str = format_comment(normal_comment, dot_comment, semi_comment, is_fuzzy)
|
|
273
|
+
target.set_comment(msgid, str)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def change_reference_comment(msgid, podata)
|
|
277
|
+
normal_comment = []
|
|
278
|
+
dot_comment = []
|
|
279
|
+
semi_comment = []
|
|
280
|
+
is_fuzzy = false
|
|
281
|
+
|
|
282
|
+
podata.comment(msgid).split(CRLF_RE).each do |l|
|
|
283
|
+
if DOT_COMMENT_RE =~ l
|
|
284
|
+
dot_comment << l
|
|
285
|
+
elsif SEMICOLON_COMMENT_RE =~ l
|
|
286
|
+
semi_comment << l
|
|
287
|
+
elsif FUZZY_RE =~ l
|
|
288
|
+
is_fuzzy = true
|
|
289
|
+
else
|
|
290
|
+
normal_comment << l
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
str = format_comment(normal_comment, dot_comment, semi_comment, is_fuzzy)
|
|
295
|
+
podata.set_comment(msgid, str)
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def format_comment(normal_comment, dot_comment, semi_comment, is_fuzzy)
|
|
299
|
+
str = ''
|
|
300
|
+
|
|
301
|
+
str << normal_comment.join("\n").gsub(/^#(\s*)/){|sss|
|
|
302
|
+
if $1 == ""
|
|
303
|
+
"# "
|
|
304
|
+
else
|
|
305
|
+
sss
|
|
306
|
+
end
|
|
307
|
+
}
|
|
308
|
+
if normal_comment.size > 0
|
|
309
|
+
str << "\n"
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
str << dot_comment.join("\n").gsub(/^#.(\s*)/){|sss|
|
|
313
|
+
if $1 == ""
|
|
314
|
+
"#. "
|
|
315
|
+
else
|
|
316
|
+
sss
|
|
317
|
+
end
|
|
318
|
+
}
|
|
319
|
+
if dot_comment.size > 0
|
|
320
|
+
str << "\n"
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
str << semi_comment.join("\n").gsub(/^#:\s*/, "#: ")
|
|
324
|
+
if semi_comment.size > 0
|
|
325
|
+
str << "\n"
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
if is_fuzzy
|
|
329
|
+
str << "#, fuzzy\n"
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
str
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def merge_header(target, definition)
|
|
336
|
+
merge_comment('', target, '', definition)
|
|
337
|
+
|
|
338
|
+
msg = target.msgstr('')
|
|
339
|
+
def_msg = definition.msgstr('')
|
|
340
|
+
if POT_DATE_EXTRACT_RE =~ msg
|
|
341
|
+
time = $1
|
|
342
|
+
def_msg = def_msg.sub(POT_DATE_RE, "POT-Creation-Date: #{time}")
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
target[''] = def_msg
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
module GetText::RMsgMerge #:nodoc:
|
|
355
|
+
|
|
356
|
+
class Config #:nodoc:
|
|
357
|
+
|
|
358
|
+
attr_accessor :defpo, :refpot, :output, :fuzzy, :update
|
|
359
|
+
|
|
360
|
+
# update mode options
|
|
361
|
+
attr_accessor :backup, :suffix
|
|
362
|
+
|
|
363
|
+
=begin
|
|
364
|
+
The result is written back to def.po.
|
|
365
|
+
--backup=CONTROL make a backup of def.po
|
|
366
|
+
--suffix=SUFFIX override the usual backup suffix
|
|
367
|
+
The version control method may be selected via the --backup option or through
|
|
368
|
+
the VERSION_CONTROL environment variable. Here are the values:
|
|
369
|
+
none, off never make backups (even if --backup is given)
|
|
370
|
+
numbered, t make numbered backups
|
|
371
|
+
existing, nil numbered if numbered backups exist, simple otherwise
|
|
372
|
+
simple, never always make simple backups
|
|
373
|
+
The backup suffix is `~', unless set with --suffix or the SIMPLE_BACKUP_SUFFIX
|
|
374
|
+
environment variable.
|
|
375
|
+
=end
|
|
376
|
+
|
|
377
|
+
def initialize
|
|
378
|
+
@output = STDOUT
|
|
379
|
+
@fuzzy = nil
|
|
380
|
+
@update = nil
|
|
381
|
+
@backup = ENV["VERSION_CONTROL"]
|
|
382
|
+
@suffix= ENV["SIMPLE_BACKUP_SUFFIX"] || "~"
|
|
383
|
+
@input_dirs = ["."]
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
module GetText
|
|
391
|
+
|
|
392
|
+
module RMsgMerge
|
|
393
|
+
extend GetText
|
|
394
|
+
extend self
|
|
395
|
+
|
|
396
|
+
bindtextdomain("rgettext")
|
|
397
|
+
|
|
398
|
+
# constant values
|
|
399
|
+
VERSION = GetText::VERSION
|
|
400
|
+
DATE = %w($Date: 2007/07/21 15:03:05 $)[1]
|
|
401
|
+
|
|
402
|
+
def check_options(config)
|
|
403
|
+
opts = OptionParser.new
|
|
404
|
+
opts.banner = _("Usage: %s def.po ref.pot [-o output.pot]") % $0
|
|
405
|
+
#opts.summary_width = 80
|
|
406
|
+
opts.separator("")
|
|
407
|
+
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."))
|
|
408
|
+
opts.separator("")
|
|
409
|
+
opts.separator(_("Specific options:"))
|
|
410
|
+
|
|
411
|
+
opts.on("-o", "--output=FILE", _("write output to specified file")) do |out|
|
|
412
|
+
unless FileTest.exist? out
|
|
413
|
+
config.output = out
|
|
414
|
+
else
|
|
415
|
+
#$stderr.puts(_("File '%s' has already existed.") % out)
|
|
416
|
+
#exit 1
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
#opts.on("-F", "--fuzzy-matching")
|
|
421
|
+
|
|
422
|
+
opts.on_tail("--version", _("display version information and exit")) do
|
|
423
|
+
puts "#{$0} #{VERSION} (#{DATE})"
|
|
424
|
+
puts "#{File.join(::Config::CONFIG["bindir"], ::Config::CONFIG["RUBY_INSTALL_NAME"])} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
|
|
425
|
+
exit
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
opts.parse!(ARGV)
|
|
429
|
+
|
|
430
|
+
if ARGV.size != 2
|
|
431
|
+
puts opts.help
|
|
432
|
+
exit 1
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
config.defpo = ARGV[0]
|
|
436
|
+
config.refpot = ARGV[1]
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
def run(reference = nil, definition = nil, out = STDOUT)
|
|
440
|
+
config = GetText::RMsgMerge::Config.new
|
|
441
|
+
config.refpot = reference
|
|
442
|
+
config.defpo = definition
|
|
443
|
+
config.output = out
|
|
444
|
+
|
|
445
|
+
check_options(config)
|
|
446
|
+
|
|
447
|
+
if config.defpo.nil?
|
|
448
|
+
raise ArgumentError, _("definition po is not given.")
|
|
449
|
+
elsif config.refpot.nil?
|
|
450
|
+
raise ArgumentError, _("reference pot is not given.")
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
parser = PoParser.new
|
|
454
|
+
defpo = parser.parse_file(config.defpo, PoData.new, false)
|
|
455
|
+
refpot = parser.parse_file(config.refstrrefstr, PoData.new, false)
|
|
456
|
+
|
|
457
|
+
m = Merger.new
|
|
458
|
+
result = m.merge(defpo, refpot)
|
|
459
|
+
p result if $DEBUG
|
|
460
|
+
print result.generate_po if $DEBUG
|
|
461
|
+
|
|
462
|
+
begin
|
|
463
|
+
if out.is_a? String
|
|
464
|
+
File.open(File.expand_path(out), "w+") do |file|
|
|
465
|
+
file.write(result.generate_po)
|
|
466
|
+
end
|
|
467
|
+
else
|
|
468
|
+
out.puts(result.generate_po)
|
|
469
|
+
end
|
|
470
|
+
ensure
|
|
471
|
+
out.close
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
module GetText
|
|
482
|
+
|
|
483
|
+
# Experimental
|
|
484
|
+
def rmsgmerge(reference = nil, definition = nil, out = STDOUT)
|
|
485
|
+
RMsgMerge.run(reference, definition, out)
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
if $0 == __FILE__ then
|
|
493
|
+
require 'pp'
|
|
494
|
+
|
|
495
|
+
#parser = GetText::RMsgMerge::PoParser.new;
|
|
496
|
+
#parser = GetText::PoParser.new;
|
|
497
|
+
#pp parser.parse(ARGF.read)
|
|
498
|
+
|
|
499
|
+
GetText.rmsgmerge
|
|
500
|
+
end
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
tools.rb - Utility functions
|
|
5
|
+
|
|
6
|
+
Copyright (C) 2005-2008 Masao Mutoh
|
|
7
|
+
|
|
8
|
+
You may redistribute it and/or modify it under the same
|
|
9
|
+
license terms as Ruby or LGPL.
|
|
10
|
+
=end
|
|
11
|
+
|
|
12
|
+
require 'rbconfig'
|
|
13
|
+
if /mingw|mswin|mswin32/ =~ RUBY_PLATFORM
|
|
14
|
+
ENV['PATH'] = %w(bin lib).collect{|dir|
|
|
15
|
+
"#{Config::CONFIG["prefix"]}\\lib\\GTK\\#{dir};"
|
|
16
|
+
}.join('') + ENV['PATH']
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
require 'gettext/tools/rgettext'
|
|
20
|
+
require 'gettext/tools/rmsgfmt'
|
|
21
|
+
require 'gettext/runtime/mofile'
|
|
22
|
+
require 'fileutils'
|
|
23
|
+
|
|
24
|
+
module GetText
|
|
25
|
+
bindtextdomain "rgettext"
|
|
26
|
+
|
|
27
|
+
BOM_UTF8 = [0xef, 0xbb, 0xbf].pack("c3")
|
|
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)[3..-1]
|
|
35
|
+
File.open(path, "w") {|f| f.write(data)}
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Merges two Uniforum style .po files together.
|
|
40
|
+
#
|
|
41
|
+
# *Note* This function requires "msgmerge" tool included in GNU GetText. So you need to install GNU GetText.
|
|
42
|
+
#
|
|
43
|
+
# The def.po file is an existing PO file with translations which will be taken
|
|
44
|
+
# over to the newly created file as long as they still match; comments will be preserved,
|
|
45
|
+
# but extracted comments and file positions will be discarded.
|
|
46
|
+
#
|
|
47
|
+
# The ref.pot file is the last created PO file with up-to-date source references but
|
|
48
|
+
# old translations, or a PO Template file (generally created by rgettext);
|
|
49
|
+
# any translations or comments in the file will be discarded, however dot
|
|
50
|
+
# comments and file positions will be preserved. Where an exact match
|
|
51
|
+
# cannot be found, fuzzy matching is used to produce better results.
|
|
52
|
+
#
|
|
53
|
+
# Usually you don't need to call this function directly. Use GetText.update_pofiles instead.
|
|
54
|
+
#
|
|
55
|
+
# * defpo: a po-file. translations referring to old sources
|
|
56
|
+
# * refpo: a po-file. references to new sources
|
|
57
|
+
# * app_version: the application information which appears "Project-Id-Version: #{app_version}" in the pot/po-files.
|
|
58
|
+
# * Returns: self
|
|
59
|
+
def msgmerge(defpo, refpo, app_version, options={})
|
|
60
|
+
verbose = options.delete(:verbose)
|
|
61
|
+
puts "msgmerge called" if verbose
|
|
62
|
+
$stderr.print defpo + " "
|
|
63
|
+
|
|
64
|
+
content = merge_po_files(defpo,refpo,options.delete(:msgmerge),verbose)
|
|
65
|
+
|
|
66
|
+
if content.empty?
|
|
67
|
+
# report failure
|
|
68
|
+
failed_filename = refpo + "~"
|
|
69
|
+
FileUtils.cp(refpo, failed_filename)
|
|
70
|
+
$stderr.puts _("Failed to merge with %{defpo}") % {:defpo => defpo}
|
|
71
|
+
$stderr.puts _("New .pot was copied to %{failed_filename}") %{:failed_filename => failed_filename}
|
|
72
|
+
raise _("Check these po/pot-files. It may have syntax errors or something wrong.")
|
|
73
|
+
else
|
|
74
|
+
# update version and save merged data
|
|
75
|
+
content.sub!(/(Project-Id-Version\:).*$/, "\\1 #{app_version}\\n\"")
|
|
76
|
+
File.open(defpo, "w") {|f|f.write(content)}
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
self
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Creates mo-files using #{po_root}/#{lang}/*.po an put them to
|
|
83
|
+
# #{targetdir}/#{targetdir_rule}/.
|
|
84
|
+
#
|
|
85
|
+
# This is a convenience function of GetText.rmsgfmt for multiple target files.
|
|
86
|
+
# * options: options as a Hash.
|
|
87
|
+
# * verbose: true if verbose mode, otherwise false
|
|
88
|
+
# * po_root: the root directory of po-files.
|
|
89
|
+
# * mo_root: the target root directory where the mo-files are stored.
|
|
90
|
+
# * mo_path_rule: the target directory for each mo-files.
|
|
91
|
+
def create_mofiles(options = {})
|
|
92
|
+
options = {:po_root => "./po"}.merge(options)
|
|
93
|
+
|
|
94
|
+
Dir.glob(File.join(options[:po_root], "*/*.po")) do |po_file|
|
|
95
|
+
mo_file = mo_file_from_po_file(po_file,options)
|
|
96
|
+
$stderr.print %Q[#{po_file} -> #{mo_file} ... ] if options[:verbose]
|
|
97
|
+
FileUtils.mkdir_p(File.dirname(mo_file))
|
|
98
|
+
rmsgfmt(po_file, mo_file)
|
|
99
|
+
$stderr.puts "Done." if options[:verbose]
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# At first, this creates the #{po_root}/#{domainname}.pot file using GetText.rgettext.
|
|
105
|
+
# In the second step, this updates(merges) the #{po_root}/#{domainname}.pot and all of the
|
|
106
|
+
# #{po_root}/#{lang}/#{domainname}.po files under "po_root" using "msgmerge".
|
|
107
|
+
#
|
|
108
|
+
# *Note* "msgmerge" tool is included in GNU GetText. So you need to install GNU GetText.
|
|
109
|
+
#
|
|
110
|
+
# See <HOWTO maintain po/mo files(http://www.yotabanana.com/hiki/ruby-gettext-howto-manage.html)> for more detals.
|
|
111
|
+
# * domainname: the textdomain name.
|
|
112
|
+
# * targetfiles: An Array of target files, that should be parsed for messages (See GetText.rgettext for more details).
|
|
113
|
+
# * app_version: the application information which appears "Project-Id-Version: #{app_version}" in the pot/po-files.
|
|
114
|
+
# * options: a hash with following possible settings
|
|
115
|
+
# :lang - update files only for one language - the language specified by this option
|
|
116
|
+
# :po_root - the root directory of po-files
|
|
117
|
+
# :msgmerge - an array with the options, passed through to the gnu msgmerge tool
|
|
118
|
+
# symbols are automatically translated to options with dashes,
|
|
119
|
+
# example: [:no_wrap, :no_fuzzy_matching, :sort_output] translated to '--no-fuzzy-matching --sort-output'
|
|
120
|
+
# :verbose - true to show verbose messages. default is false.
|
|
121
|
+
#
|
|
122
|
+
# Example: GetText.update_pofiles("myapp", Dir.glob("lib/*.rb"), "myapp 1.0.0", :verbose => true)
|
|
123
|
+
def update_pofiles(textdomain, files, app_version, options = {})
|
|
124
|
+
puts options.inspect if options[:verbose]
|
|
125
|
+
|
|
126
|
+
#write found messages to tmp.pot
|
|
127
|
+
temp_pot = "tmp.pot"
|
|
128
|
+
rgettext(files, temp_pot)
|
|
129
|
+
|
|
130
|
+
#merge tmp.pot and existing pot
|
|
131
|
+
po_root = options.delete(:po_root) || "po"
|
|
132
|
+
FileUtils.mkdir_p(po_root)
|
|
133
|
+
msgmerge("#{po_root}/#{textdomain}.pot", temp_pot, app_version, options.dup)
|
|
134
|
+
|
|
135
|
+
#update local po-files
|
|
136
|
+
only_one_language = options.delete(:lang)
|
|
137
|
+
if only_one_language
|
|
138
|
+
msgmerge("#{po_root}/#{only_one_language}/#{textdomain}.po", temp_pot, app_version, options.dup)
|
|
139
|
+
else
|
|
140
|
+
Dir.glob("#{po_root}/*/#{textdomain}.po") do |po_file|
|
|
141
|
+
msgmerge(po_file, temp_pot, app_version, options.dup)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
File.delete(temp_pot)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
private
|
|
149
|
+
|
|
150
|
+
# Merge 2 po files, using msgmerge
|
|
151
|
+
def merge_po_files(po_a,po_b,msgmerge_options=[],verbose=false)
|
|
152
|
+
return File.read(po_b) unless FileTest.exist? po_a
|
|
153
|
+
|
|
154
|
+
cmd = ENV["MSGMERGE_PATH"] || "msgmerge"
|
|
155
|
+
ensure_command_exists(cmd)
|
|
156
|
+
|
|
157
|
+
remove_bom(po_a)
|
|
158
|
+
|
|
159
|
+
cmd_params = array_to_cli_options(msgmerge_options)
|
|
160
|
+
to_run = "#{cmd} #{cmd_params} #{po_a} #{po_b}"
|
|
161
|
+
puts "\nrunning #{to_run}" if verbose
|
|
162
|
+
`#{to_run}`
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# convert an array of String/Symbol to cli options
|
|
166
|
+
def array_to_cli_options(array)
|
|
167
|
+
[*array].map do |o|
|
|
168
|
+
o.kind_of?(Symbol) ? "--#{o}".gsub('_','-') : o.to_s
|
|
169
|
+
end.join(' ')
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def ensure_command_exists(cmd)
|
|
173
|
+
`#{cmd} --help`
|
|
174
|
+
unless $? && $?.success?
|
|
175
|
+
raise _("`%{cmd}' can not be found. \nInstall GNU Gettext then set PATH or MSGMERGE_PATH correctly.") % {:cmd => cmd}
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# where lies the mo file for a given po_file
|
|
180
|
+
# generare directory unless it exists
|
|
181
|
+
def mo_file_from_po_file(po_file,options)
|
|
182
|
+
options = {
|
|
183
|
+
:mo_root => "./data/locale",
|
|
184
|
+
:mo_path_rule => "%{lang}/LC_MESSAGES"
|
|
185
|
+
}.merge(options)
|
|
186
|
+
|
|
187
|
+
lang, textdomain = %r[/([^/]+?)/(.*)\.po].match(po_file[options[:po_root].size..-1]).to_a[1,2]
|
|
188
|
+
|
|
189
|
+
mo_dir_rule = File.join(options[:mo_root], options[:mo_path_rule])
|
|
190
|
+
mo_dir = mo_dir_rule % {:lang => lang}
|
|
191
|
+
File.join(mo_dir, "#{textdomain}.mo")
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
if __FILE__ == $0
|
|
196
|
+
GetText.update_pofiles("foo", ARGV, "foo 1.1.0")
|
|
197
|
+
end
|