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.
Files changed (406) hide show
  1. data/ChangeLog +2014 -0
  2. data/README.rdoc +172 -0
  3. data/Rakefile +192 -0
  4. data/bin/rgettext +24 -0
  5. data/bin/rmsgfmt +24 -0
  6. data/bin/rmsgmerge +24 -0
  7. data/gettext.gemspec +39 -0
  8. data/lib/gettext.rb +263 -0
  9. data/lib/gettext/cgi.rb +40 -0
  10. data/lib/gettext/class_info.rb +55 -0
  11. data/lib/gettext/core_ext/iconv.rb +109 -0
  12. data/lib/gettext/core_ext/string.rb +63 -0
  13. data/lib/gettext/mofile.rb +320 -0
  14. data/lib/gettext/parser/erb.rb +50 -0
  15. data/lib/gettext/parser/glade.rb +99 -0
  16. data/lib/gettext/parser/ruby.rb +170 -0
  17. data/lib/gettext/poparser.rb +332 -0
  18. data/lib/gettext/textdomain.rb +225 -0
  19. data/lib/gettext/textdomain_manager.rb +218 -0
  20. data/lib/gettext/tools.rb +177 -0
  21. data/lib/gettext/tools/rgettext.rb +275 -0
  22. data/lib/gettext/tools/rmsgfmt.rb +84 -0
  23. data/lib/gettext/tools/rmsgmerge.rb +505 -0
  24. data/lib/gettext/utils.rb +39 -0
  25. data/lib/gettext/version.rb +12 -0
  26. data/po/bg/rgettext.po +150 -0
  27. data/po/bs/rgettext.po +151 -0
  28. data/po/ca/rgettext.po +149 -0
  29. data/po/cs/rgettext.po +152 -0
  30. data/po/de/#rails.po# +175 -0
  31. data/po/de/rgettext.po +157 -0
  32. data/po/el/rgettext.po +148 -0
  33. data/po/eo/rgettext.po +149 -0
  34. data/po/es/rgettext.po +150 -0
  35. data/po/et/rgettext.po +147 -0
  36. data/po/fr/rgettext.po +153 -0
  37. data/po/hr/rgettext.po +151 -0
  38. data/po/hu/rgettext.po +149 -0
  39. data/po/it/rgettext.po +150 -0
  40. data/po/ja/rails.po.old +150 -0
  41. data/po/ja/rgettext.po +149 -0
  42. data/po/ko/rgettext.po +149 -0
  43. data/po/lv/rgettext.po +150 -0
  44. data/po/nb/rgettext.po +151 -0
  45. data/po/nl/rgettext.po +150 -0
  46. data/po/pt_BR/rgettext.po +152 -0
  47. data/po/rgettext.pot +141 -0
  48. data/po/ru/rgettext.po +151 -0
  49. data/po/sr/rgettext.po +150 -0
  50. data/po/sv/rgettext.po +143 -0
  51. data/po/ua/rgettext.po +155 -0
  52. data/po/vi/rgettext.po +148 -0
  53. data/po/zh/rgettext.po +149 -0
  54. data/po/zh_TW/rgettext.po +148 -0
  55. data/samples/README +16 -0
  56. data/samples/cgi/README +43 -0
  57. data/samples/cgi/Rakefile +27 -0
  58. data/samples/cgi/cookie.cgi +64 -0
  59. data/samples/cgi/gettext.css +116 -0
  60. data/samples/cgi/helloerb.rhtml +28 -0
  61. data/samples/cgi/helloerb1.cgi +58 -0
  62. data/samples/cgi/helloerb2.cgi +51 -0
  63. data/samples/cgi/hellolib.rb +20 -0
  64. data/samples/cgi/http.rb +51 -0
  65. data/samples/cgi/index.cgi +111 -0
  66. data/samples/cgi/other.rhtml +20 -0
  67. data/samples/cgi/po/bg/helloerb1.po +59 -0
  68. data/samples/cgi/po/bg/helloerb2.po +51 -0
  69. data/samples/cgi/po/bg/hellolib.po +23 -0
  70. data/samples/cgi/po/bg/main.po +83 -0
  71. data/samples/cgi/po/bs/helloerb1.po +59 -0
  72. data/samples/cgi/po/bs/helloerb2.po +51 -0
  73. data/samples/cgi/po/bs/hellolib.po +23 -0
  74. data/samples/cgi/po/bs/main.po +83 -0
  75. data/samples/cgi/po/ca/helloerb1.po +59 -0
  76. data/samples/cgi/po/ca/helloerb2.po +51 -0
  77. data/samples/cgi/po/ca/hellolib.po +23 -0
  78. data/samples/cgi/po/ca/main.po +83 -0
  79. data/samples/cgi/po/cs/helloerb1.po +61 -0
  80. data/samples/cgi/po/cs/helloerb2.po +52 -0
  81. data/samples/cgi/po/cs/hellolib.po +25 -0
  82. data/samples/cgi/po/cs/main.po +85 -0
  83. data/samples/cgi/po/de/helloerb1.po +61 -0
  84. data/samples/cgi/po/de/helloerb2.po +52 -0
  85. data/samples/cgi/po/de/hellolib.po +24 -0
  86. data/samples/cgi/po/de/main.po +86 -0
  87. data/samples/cgi/po/el/helloerb1.po +60 -0
  88. data/samples/cgi/po/el/helloerb2.po +51 -0
  89. data/samples/cgi/po/el/hellolib.po +23 -0
  90. data/samples/cgi/po/el/main.po +84 -0
  91. data/samples/cgi/po/eo/helloerb1.po +60 -0
  92. data/samples/cgi/po/eo/helloerb2.po +52 -0
  93. data/samples/cgi/po/eo/hellolib.po +24 -0
  94. data/samples/cgi/po/eo/main.po +84 -0
  95. data/samples/cgi/po/es/helloerb1.po +59 -0
  96. data/samples/cgi/po/es/helloerb2.po +50 -0
  97. data/samples/cgi/po/es/hellolib.po +22 -0
  98. data/samples/cgi/po/es/main.po +83 -0
  99. data/samples/cgi/po/fr/helloerb1.po +59 -0
  100. data/samples/cgi/po/fr/helloerb2.po +51 -0
  101. data/samples/cgi/po/fr/hellolib.po +22 -0
  102. data/samples/cgi/po/fr/main.po +85 -0
  103. data/samples/cgi/po/helloerb1.pot +60 -0
  104. data/samples/cgi/po/helloerb2.pot +52 -0
  105. data/samples/cgi/po/hellolib.pot +24 -0
  106. data/samples/cgi/po/hr/helloerb1.po +59 -0
  107. data/samples/cgi/po/hr/helloerb2.po +51 -0
  108. data/samples/cgi/po/hr/hellolib.po +23 -0
  109. data/samples/cgi/po/hr/main.po +83 -0
  110. data/samples/cgi/po/hu/helloerb1.po +59 -0
  111. data/samples/cgi/po/hu/helloerb2.po +51 -0
  112. data/samples/cgi/po/hu/hellolib.po +23 -0
  113. data/samples/cgi/po/hu/main.po +82 -0
  114. data/samples/cgi/po/it/helloerb1.po +60 -0
  115. data/samples/cgi/po/it/helloerb2.po +52 -0
  116. data/samples/cgi/po/it/hellolib.po +24 -0
  117. data/samples/cgi/po/it/main.po +84 -0
  118. data/samples/cgi/po/ja/helloerb1.po +60 -0
  119. data/samples/cgi/po/ja/helloerb2.po +52 -0
  120. data/samples/cgi/po/ja/hellolib.po +24 -0
  121. data/samples/cgi/po/ja/main.po +85 -0
  122. data/samples/cgi/po/ko/helloerb1.po +59 -0
  123. data/samples/cgi/po/ko/helloerb2.po +51 -0
  124. data/samples/cgi/po/ko/hellolib.po +23 -0
  125. data/samples/cgi/po/ko/main.po +84 -0
  126. data/samples/cgi/po/lv/helloerb1.po +65 -0
  127. data/samples/cgi/po/lv/helloerb2.po +52 -0
  128. data/samples/cgi/po/lv/hellolib.po +24 -0
  129. data/samples/cgi/po/lv/main.po +77 -0
  130. data/samples/cgi/po/main.pot +80 -0
  131. data/samples/cgi/po/nb/helloerb1.po +60 -0
  132. data/samples/cgi/po/nb/helloerb2.po +52 -0
  133. data/samples/cgi/po/nb/hellolib.po +24 -0
  134. data/samples/cgi/po/nb/main.po +84 -0
  135. data/samples/cgi/po/nl/helloerb1.po +61 -0
  136. data/samples/cgi/po/nl/helloerb2.po +52 -0
  137. data/samples/cgi/po/nl/hellolib.po +24 -0
  138. data/samples/cgi/po/nl/main.po +86 -0
  139. data/samples/cgi/po/pt_BR/helloerb1.po +59 -0
  140. data/samples/cgi/po/pt_BR/helloerb2.po +51 -0
  141. data/samples/cgi/po/pt_BR/hellolib.po +23 -0
  142. data/samples/cgi/po/pt_BR/main.po +84 -0
  143. data/samples/cgi/po/ru/helloerb1.po +58 -0
  144. data/samples/cgi/po/ru/helloerb2.po +50 -0
  145. data/samples/cgi/po/ru/hellolib.po +22 -0
  146. data/samples/cgi/po/ru/main.po +82 -0
  147. data/samples/cgi/po/sr/helloerb1.po +60 -0
  148. data/samples/cgi/po/sr/helloerb2.po +52 -0
  149. data/samples/cgi/po/sr/hellolib.po +24 -0
  150. data/samples/cgi/po/sr/main.po +80 -0
  151. data/samples/cgi/po/ua/helloerb1.po +62 -0
  152. data/samples/cgi/po/ua/helloerb2.po +54 -0
  153. data/samples/cgi/po/ua/hellolib.po +26 -0
  154. data/samples/cgi/po/ua/main.po +84 -0
  155. data/samples/cgi/po/vi/helloerb1.po +65 -0
  156. data/samples/cgi/po/vi/helloerb2.po +52 -0
  157. data/samples/cgi/po/vi/hellolib.po +24 -0
  158. data/samples/cgi/po/vi/main.po +77 -0
  159. data/samples/cgi/po/zh/helloerb1.po +60 -0
  160. data/samples/cgi/po/zh/helloerb2.po +52 -0
  161. data/samples/cgi/po/zh/hellolib.po +24 -0
  162. data/samples/cgi/po/zh/main.po +80 -0
  163. data/samples/cgi/po/zh_TW/helloerb1.po +67 -0
  164. data/samples/cgi/po/zh_TW/helloerb2.po +54 -0
  165. data/samples/cgi/po/zh_TW/hellolib.po +26 -0
  166. data/samples/cgi/po/zh_TW/main.po +79 -0
  167. data/samples/hello.rb +36 -0
  168. data/samples/hello2.rb +23 -0
  169. data/samples/hello_glade2.glade +70 -0
  170. data/samples/hello_glade2.rb +25 -0
  171. data/samples/hello_gtk2.rb +27 -0
  172. data/samples/hello_noop.rb +31 -0
  173. data/samples/hello_plural.rb +26 -0
  174. data/samples/hello_tk.rb +19 -0
  175. data/samples/makemo.rb +4 -0
  176. data/samples/po/bg/hello.po +24 -0
  177. data/samples/po/bg/hello2.po +31 -0
  178. data/samples/po/bg/hello_glade2.po +31 -0
  179. data/samples/po/bg/hello_gtk.po +23 -0
  180. data/samples/po/bg/hello_noop.po +27 -0
  181. data/samples/po/bg/hello_plural.po +25 -0
  182. data/samples/po/bg/hello_tk.po +23 -0
  183. data/samples/po/bs/hello.po +23 -0
  184. data/samples/po/bs/hello2.po +31 -0
  185. data/samples/po/bs/hello_glade2.po +31 -0
  186. data/samples/po/bs/hello_gtk.po +23 -0
  187. data/samples/po/bs/hello_noop.po +27 -0
  188. data/samples/po/bs/hello_plural.po +26 -0
  189. data/samples/po/bs/hello_tk.po +23 -0
  190. data/samples/po/ca/hello.po +23 -0
  191. data/samples/po/ca/hello2.po +31 -0
  192. data/samples/po/ca/hello_glade2.po +31 -0
  193. data/samples/po/ca/hello_gtk.po +23 -0
  194. data/samples/po/ca/hello_noop.po +27 -0
  195. data/samples/po/ca/hello_plural.po +25 -0
  196. data/samples/po/ca/hello_tk.po +23 -0
  197. data/samples/po/cs/hello.po +23 -0
  198. data/samples/po/cs/hello2.po +31 -0
  199. data/samples/po/cs/hello_glade2.po +37 -0
  200. data/samples/po/cs/hello_gtk.po +23 -0
  201. data/samples/po/cs/hello_noop.po +27 -0
  202. data/samples/po/cs/hello_plural.po +26 -0
  203. data/samples/po/cs/hello_tk.po +23 -0
  204. data/samples/po/de/hello.po +20 -0
  205. data/samples/po/de/hello2.po +28 -0
  206. data/samples/po/de/hello_glade2.po +27 -0
  207. data/samples/po/de/hello_gtk.po +20 -0
  208. data/samples/po/de/hello_noop.po +24 -0
  209. data/samples/po/de/hello_plural.po +25 -0
  210. data/samples/po/de/hello_tk.po +20 -0
  211. data/samples/po/el/hello.po +23 -0
  212. data/samples/po/el/hello2.po +31 -0
  213. data/samples/po/el/hello_glade2.po +31 -0
  214. data/samples/po/el/hello_gtk.po +22 -0
  215. data/samples/po/el/hello_noop.po +27 -0
  216. data/samples/po/el/hello_plural.po +25 -0
  217. data/samples/po/el/hello_tk.po +23 -0
  218. data/samples/po/eo/hello.po +23 -0
  219. data/samples/po/eo/hello2.po +31 -0
  220. data/samples/po/eo/hello_glade2.po +32 -0
  221. data/samples/po/eo/hello_gtk.po +23 -0
  222. data/samples/po/eo/hello_noop.po +27 -0
  223. data/samples/po/eo/hello_plural.po +26 -0
  224. data/samples/po/eo/hello_tk.po +24 -0
  225. data/samples/po/es/hello.po +21 -0
  226. data/samples/po/es/hello2.po +28 -0
  227. data/samples/po/es/hello_glade2.po +28 -0
  228. data/samples/po/es/hello_gtk.po +20 -0
  229. data/samples/po/es/hello_noop.po +24 -0
  230. data/samples/po/es/hello_plural.po +23 -0
  231. data/samples/po/es/hello_tk.po +20 -0
  232. data/samples/po/fr/hello.po +18 -0
  233. data/samples/po/fr/hello2.po +26 -0
  234. data/samples/po/fr/hello_glade2.po +27 -0
  235. data/samples/po/fr/hello_gtk.po +18 -0
  236. data/samples/po/fr/hello_noop.po +22 -0
  237. data/samples/po/fr/hello_plural.po +21 -0
  238. data/samples/po/fr/hello_tk.po +18 -0
  239. data/samples/po/hello.pot +23 -0
  240. data/samples/po/hello2.pot +31 -0
  241. data/samples/po/hello_glade2.pot +32 -0
  242. data/samples/po/hello_gtk.pot +23 -0
  243. data/samples/po/hello_noop.pot +27 -0
  244. data/samples/po/hello_plural.pot +26 -0
  245. data/samples/po/hello_tk.pot +24 -0
  246. data/samples/po/hr/hello.po +23 -0
  247. data/samples/po/hr/hello2.po +31 -0
  248. data/samples/po/hr/hello_glade2.po +31 -0
  249. data/samples/po/hr/hello_gtk.po +23 -0
  250. data/samples/po/hr/hello_noop.po +27 -0
  251. data/samples/po/hr/hello_plural.po +26 -0
  252. data/samples/po/hr/hello_tk.po +23 -0
  253. data/samples/po/hu/hello.po +22 -0
  254. data/samples/po/hu/hello2.po +30 -0
  255. data/samples/po/hu/hello_glade2.po +31 -0
  256. data/samples/po/hu/hello_gtk.po +22 -0
  257. data/samples/po/hu/hello_noop.po +26 -0
  258. data/samples/po/hu/hello_plural.po +25 -0
  259. data/samples/po/hu/hello_tk.po +23 -0
  260. data/samples/po/it/hello.po +20 -0
  261. data/samples/po/it/hello2.po +28 -0
  262. data/samples/po/it/hello_glade2.po +28 -0
  263. data/samples/po/it/hello_gtk.po +21 -0
  264. data/samples/po/it/hello_noop.po +24 -0
  265. data/samples/po/it/hello_plural.po +23 -0
  266. data/samples/po/it/hello_tk.po +21 -0
  267. data/samples/po/ja/hello.po +20 -0
  268. data/samples/po/ja/hello2.po +28 -0
  269. data/samples/po/ja/hello_glade2.po +26 -0
  270. data/samples/po/ja/hello_gtk.po +19 -0
  271. data/samples/po/ja/hello_noop.po +23 -0
  272. data/samples/po/ja/hello_plural.po +21 -0
  273. data/samples/po/ja/hello_tk.po +19 -0
  274. data/samples/po/ko/hello.po +18 -0
  275. data/samples/po/ko/hello2.po +26 -0
  276. data/samples/po/ko/hello_glade2.po +29 -0
  277. data/samples/po/ko/hello_gtk.po +18 -0
  278. data/samples/po/ko/hello_noop.po +22 -0
  279. data/samples/po/ko/hello_plural.po +25 -0
  280. data/samples/po/ko/hello_tk.po +19 -0
  281. data/samples/po/lv/hello.po +24 -0
  282. data/samples/po/lv/hello2.po +32 -0
  283. data/samples/po/lv/hello_glade2.po +38 -0
  284. data/samples/po/lv/hello_gtk.po +24 -0
  285. data/samples/po/lv/hello_noop.po +28 -0
  286. data/samples/po/lv/hello_plural.po +26 -0
  287. data/samples/po/lv/hello_tk.po +24 -0
  288. data/samples/po/nb/hello.po +23 -0
  289. data/samples/po/nb/hello2.po +31 -0
  290. data/samples/po/nb/hello_glade2.po +31 -0
  291. data/samples/po/nb/hello_gtk.po +23 -0
  292. data/samples/po/nb/hello_noop.po +27 -0
  293. data/samples/po/nb/hello_plural.po +26 -0
  294. data/samples/po/nb/hello_tk.po +24 -0
  295. data/samples/po/nl/hello.po +24 -0
  296. data/samples/po/nl/hello2.po +32 -0
  297. data/samples/po/nl/hello_glade2.po +31 -0
  298. data/samples/po/nl/hello_gtk.po +24 -0
  299. data/samples/po/nl/hello_noop.po +28 -0
  300. data/samples/po/nl/hello_plural.po +25 -0
  301. data/samples/po/nl/hello_tk.po +24 -0
  302. data/samples/po/pt_BR/hello.po +21 -0
  303. data/samples/po/pt_BR/hello2.po +29 -0
  304. data/samples/po/pt_BR/hello_glade2.po +29 -0
  305. data/samples/po/pt_BR/hello_gtk.po +21 -0
  306. data/samples/po/pt_BR/hello_noop.po +25 -0
  307. data/samples/po/pt_BR/hello_plural.po +23 -0
  308. data/samples/po/pt_BR/hello_tk.po +21 -0
  309. data/samples/po/ru/hello.po +22 -0
  310. data/samples/po/ru/hello2.po +30 -0
  311. data/samples/po/ru/hello_glade2.po +30 -0
  312. data/samples/po/ru/hello_gtk.po +22 -0
  313. data/samples/po/ru/hello_noop.po +26 -0
  314. data/samples/po/ru/hello_plural.po +28 -0
  315. data/samples/po/ru/hello_tk.po +22 -0
  316. data/samples/po/sr/hello.po +22 -0
  317. data/samples/po/sr/hello2.po +30 -0
  318. data/samples/po/sr/hello_glade2.po +32 -0
  319. data/samples/po/sr/hello_gtk.po +22 -0
  320. data/samples/po/sr/hello_noop.po +26 -0
  321. data/samples/po/sr/hello_plural.po +26 -0
  322. data/samples/po/sr/hello_tk.po +24 -0
  323. data/samples/po/sv/hello.po +20 -0
  324. data/samples/po/sv/hello2.po +28 -0
  325. data/samples/po/sv/hello_glade2.po +28 -0
  326. data/samples/po/sv/hello_gtk.po +20 -0
  327. data/samples/po/sv/hello_noop.po +24 -0
  328. data/samples/po/sv/hello_plural.po +23 -0
  329. data/samples/po/sv/hello_tk.po +20 -0
  330. data/samples/po/test.rb +11 -0
  331. data/samples/po/ua/hello.po +22 -0
  332. data/samples/po/ua/hello2.po +30 -0
  333. data/samples/po/ua/hello_glade2.po +34 -0
  334. data/samples/po/ua/hello_gtk.po +22 -0
  335. data/samples/po/ua/hello_noop.po +26 -0
  336. data/samples/po/ua/hello_plural.po +29 -0
  337. data/samples/po/ua/hello_tk.po +26 -0
  338. data/samples/po/vi/hello.po +23 -0
  339. data/samples/po/vi/hello2.po +31 -0
  340. data/samples/po/vi/hello_glade2.po +38 -0
  341. data/samples/po/vi/hello_gtk.po +23 -0
  342. data/samples/po/vi/hello_noop.po +27 -0
  343. data/samples/po/vi/hello_plural.po +26 -0
  344. data/samples/po/vi/hello_tk.po +24 -0
  345. data/samples/po/zh/hello.po +23 -0
  346. data/samples/po/zh/hello2.po +31 -0
  347. data/samples/po/zh/hello_glade2.po +31 -0
  348. data/samples/po/zh/hello_gtk.po +23 -0
  349. data/samples/po/zh/hello_noop.po +27 -0
  350. data/samples/po/zh/hello_plural.po +25 -0
  351. data/samples/po/zh/hello_tk.po +23 -0
  352. data/samples/po/zh_TW/hello.po +26 -0
  353. data/samples/po/zh_TW/hello2.po +34 -0
  354. data/samples/po/zh_TW/hello_glade2.po +40 -0
  355. data/samples/po/zh_TW/hello_gtk.po +25 -0
  356. data/samples/po/zh_TW/hello_noop.po +30 -0
  357. data/samples/po/zh_TW/hello_plural.po +28 -0
  358. data/samples/po/zh_TW/hello_tk.po +26 -0
  359. data/src/poparser.ry +198 -0
  360. data/test/README +1 -0
  361. data/test/Rakefile +19 -0
  362. data/test/po/cr/plural.po +23 -0
  363. data/test/po/da/plural.po +22 -0
  364. data/test/po/da/plural_error.po +21 -0
  365. data/test/po/fr/plural.po +28 -0
  366. data/test/po/fr/plural_error.po +20 -0
  367. data/test/po/fr/test1.po +23 -0
  368. data/test/po/fr/test2.po +19 -0
  369. data/test/po/fr/test6.po +23 -0
  370. data/test/po/ir/plural.po +23 -0
  371. data/test/po/ja/npgettext.po +46 -0
  372. data/test/po/ja/nsgettext.po +65 -0
  373. data/test/po/ja/pgettext.po +41 -0
  374. data/test/po/ja/plural.po +28 -0
  375. data/test/po/ja/plural_error.po +20 -0
  376. data/test/po/ja/rubyparser.po +43 -0
  377. data/test/po/ja/sgettext.po +47 -0
  378. data/test/po/ja/test1.po +23 -0
  379. data/test/po/ja/test2.po +19 -0
  380. data/test/po/ja/test6.po +23 -0
  381. data/test/po/la/plural.po +23 -0
  382. data/test/po/la/plural_error.po +21 -0
  383. data/test/po/li/plural.po +23 -0
  384. data/test/po/po/plural.po +23 -0
  385. data/test/po/sl/plural.po +24 -0
  386. data/test/test_class_info.rb +80 -0
  387. data/test/test_gettext.rb +274 -0
  388. data/test/test_parser.rb +113 -0
  389. data/test/test_string.rb +14 -0
  390. data/test/test_textdomain.rb +25 -0
  391. data/test/test_textdomain_multi.rb +69 -0
  392. data/test/test_textdomain_toplevel.rb +42 -0
  393. data/test/testlib/N_.rb +66 -0
  394. data/test/testlib/erb.rhtml +15 -0
  395. data/test/testlib/erb.rxml +16 -0
  396. data/test/testlib/gettext.rb +96 -0
  397. data/test/testlib/gladeparser.glade +183 -0
  398. data/test/testlib/helper.rb +11 -0
  399. data/test/testlib/multi_textdomain.rb +119 -0
  400. data/test/testlib/ngettext.rb +74 -0
  401. data/test/testlib/npgettext.rb +31 -0
  402. data/test/testlib/nsgettext.rb +42 -0
  403. data/test/testlib/pgettext.rb +31 -0
  404. data/test/testlib/sgettext.rb +46 -0
  405. data/test/testlib/simple.rb +14 -0
  406. 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