experteer-gettext 2.0.4

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 (424) hide show
  1. data/COPYING +55 -0
  2. data/ChangeLog +57 -0
  3. data/ChangeLog-1 +2016 -0
  4. data/NEWS-1 +414 -0
  5. data/README.rdoc +251 -0
  6. data/Rakefile +260 -0
  7. data/VERSION +2 -0
  8. data/bin/rgettext +24 -0
  9. data/bin/rmsgfmt +24 -0
  10. data/bin/rmsgmerge +24 -0
  11. data/gettext.gemspec +494 -0
  12. data/lib/gettext/cgi.rb +39 -0
  13. data/lib/gettext/class_info.rb +67 -0
  14. data/lib/gettext/core_ext/iconv.rb +112 -0
  15. data/lib/gettext/core_ext/string.rb +84 -0
  16. data/lib/gettext/locale_path.rb +123 -0
  17. data/lib/gettext/mofile.rb +330 -0
  18. data/lib/gettext/parser/erb.rb +54 -0
  19. data/lib/gettext/parser/glade.rb +100 -0
  20. data/lib/gettext/parser/ruby.rb +193 -0
  21. data/lib/gettext/poparser.rb +355 -0
  22. data/lib/gettext/textdomain.rb +179 -0
  23. data/lib/gettext/textdomain_group.rb +24 -0
  24. data/lib/gettext/textdomain_manager.rb +212 -0
  25. data/lib/gettext/tools/rgettext.rb +236 -0
  26. data/lib/gettext/tools/rmsgfmt.rb +84 -0
  27. data/lib/gettext/tools/rmsgmerge.rb +498 -0
  28. data/lib/gettext/tools.rb +195 -0
  29. data/lib/gettext/translation_target.rb +93 -0
  30. data/lib/gettext/utils.rb +37 -0
  31. data/lib/gettext/version.rb +12 -0
  32. data/lib/gettext.rb +312 -0
  33. data/po/bg/rgettext.po +130 -0
  34. data/po/bs/rgettext.po +131 -0
  35. data/po/ca/rgettext.po +129 -0
  36. data/po/cs/rgettext.po +132 -0
  37. data/po/de/rgettext.po +137 -0
  38. data/po/el/rgettext.po +128 -0
  39. data/po/eo/rgettext.po +129 -0
  40. data/po/es/rgettext.po +130 -0
  41. data/po/et/rgettext.po +127 -0
  42. data/po/fr/rgettext.po +133 -0
  43. data/po/hr/rgettext.po +131 -0
  44. data/po/hu/rgettext.po +129 -0
  45. data/po/it/rgettext.po +130 -0
  46. data/po/ja/rgettext.po +129 -0
  47. data/po/ko/rgettext.po +129 -0
  48. data/po/lv/rgettext.po +130 -0
  49. data/po/nb/rgettext.po +131 -0
  50. data/po/nl/rgettext.po +130 -0
  51. data/po/pt_BR/rgettext.po +132 -0
  52. data/po/rgettext.pot +121 -0
  53. data/po/ru/rgettext.po +131 -0
  54. data/po/sr/rgettext.po +130 -0
  55. data/po/sv/rgettext.po +123 -0
  56. data/po/ua/rgettext.po +134 -0
  57. data/po/vi/rgettext.po +128 -0
  58. data/po/zh/rgettext.po +129 -0
  59. data/po/zh_TW/rgettext.po +128 -0
  60. data/samples/README +16 -0
  61. data/samples/cgi/README +43 -0
  62. data/samples/cgi/Rakefile +27 -0
  63. data/samples/cgi/cookie.cgi +64 -0
  64. data/samples/cgi/gettext.css +116 -0
  65. data/samples/cgi/helloerb.rhtml +28 -0
  66. data/samples/cgi/helloerb1.cgi +58 -0
  67. data/samples/cgi/helloerb2.cgi +51 -0
  68. data/samples/cgi/hellolib.rb +20 -0
  69. data/samples/cgi/http.rb +51 -0
  70. data/samples/cgi/index.cgi +111 -0
  71. data/samples/cgi/other.rhtml +20 -0
  72. data/samples/cgi/po/bg/helloerb1.po +59 -0
  73. data/samples/cgi/po/bg/helloerb2.po +51 -0
  74. data/samples/cgi/po/bg/hellolib.po +23 -0
  75. data/samples/cgi/po/bg/main.po +83 -0
  76. data/samples/cgi/po/bs/helloerb1.po +59 -0
  77. data/samples/cgi/po/bs/helloerb2.po +51 -0
  78. data/samples/cgi/po/bs/hellolib.po +23 -0
  79. data/samples/cgi/po/bs/main.po +83 -0
  80. data/samples/cgi/po/ca/helloerb1.po +59 -0
  81. data/samples/cgi/po/ca/helloerb2.po +51 -0
  82. data/samples/cgi/po/ca/hellolib.po +23 -0
  83. data/samples/cgi/po/ca/main.po +83 -0
  84. data/samples/cgi/po/cs/helloerb1.po +61 -0
  85. data/samples/cgi/po/cs/helloerb2.po +52 -0
  86. data/samples/cgi/po/cs/hellolib.po +25 -0
  87. data/samples/cgi/po/cs/main.po +85 -0
  88. data/samples/cgi/po/de/helloerb1.po +61 -0
  89. data/samples/cgi/po/de/helloerb2.po +52 -0
  90. data/samples/cgi/po/de/hellolib.po +24 -0
  91. data/samples/cgi/po/de/main.po +86 -0
  92. data/samples/cgi/po/el/helloerb1.po +60 -0
  93. data/samples/cgi/po/el/helloerb2.po +51 -0
  94. data/samples/cgi/po/el/hellolib.po +23 -0
  95. data/samples/cgi/po/el/main.po +84 -0
  96. data/samples/cgi/po/eo/helloerb1.po +60 -0
  97. data/samples/cgi/po/eo/helloerb2.po +52 -0
  98. data/samples/cgi/po/eo/hellolib.po +24 -0
  99. data/samples/cgi/po/eo/main.po +84 -0
  100. data/samples/cgi/po/es/helloerb1.po +59 -0
  101. data/samples/cgi/po/es/helloerb2.po +50 -0
  102. data/samples/cgi/po/es/hellolib.po +22 -0
  103. data/samples/cgi/po/es/main.po +83 -0
  104. data/samples/cgi/po/fr/helloerb1.po +59 -0
  105. data/samples/cgi/po/fr/helloerb2.po +51 -0
  106. data/samples/cgi/po/fr/hellolib.po +22 -0
  107. data/samples/cgi/po/fr/main.po +85 -0
  108. data/samples/cgi/po/helloerb1.pot +60 -0
  109. data/samples/cgi/po/helloerb2.pot +52 -0
  110. data/samples/cgi/po/hellolib.pot +24 -0
  111. data/samples/cgi/po/hr/helloerb1.po +59 -0
  112. data/samples/cgi/po/hr/helloerb2.po +51 -0
  113. data/samples/cgi/po/hr/hellolib.po +23 -0
  114. data/samples/cgi/po/hr/main.po +83 -0
  115. data/samples/cgi/po/hu/helloerb1.po +59 -0
  116. data/samples/cgi/po/hu/helloerb2.po +51 -0
  117. data/samples/cgi/po/hu/hellolib.po +23 -0
  118. data/samples/cgi/po/hu/main.po +82 -0
  119. data/samples/cgi/po/it/helloerb1.po +60 -0
  120. data/samples/cgi/po/it/helloerb2.po +52 -0
  121. data/samples/cgi/po/it/hellolib.po +24 -0
  122. data/samples/cgi/po/it/main.po +84 -0
  123. data/samples/cgi/po/ja/helloerb1.po +60 -0
  124. data/samples/cgi/po/ja/helloerb2.po +52 -0
  125. data/samples/cgi/po/ja/hellolib.po +24 -0
  126. data/samples/cgi/po/ja/main.po +85 -0
  127. data/samples/cgi/po/ko/helloerb1.po +59 -0
  128. data/samples/cgi/po/ko/helloerb2.po +51 -0
  129. data/samples/cgi/po/ko/hellolib.po +23 -0
  130. data/samples/cgi/po/ko/main.po +84 -0
  131. data/samples/cgi/po/lv/helloerb1.po +65 -0
  132. data/samples/cgi/po/lv/helloerb2.po +52 -0
  133. data/samples/cgi/po/lv/hellolib.po +24 -0
  134. data/samples/cgi/po/lv/main.po +77 -0
  135. data/samples/cgi/po/main.pot +80 -0
  136. data/samples/cgi/po/nb/helloerb1.po +60 -0
  137. data/samples/cgi/po/nb/helloerb2.po +52 -0
  138. data/samples/cgi/po/nb/hellolib.po +24 -0
  139. data/samples/cgi/po/nb/main.po +84 -0
  140. data/samples/cgi/po/nl/helloerb1.po +61 -0
  141. data/samples/cgi/po/nl/helloerb2.po +52 -0
  142. data/samples/cgi/po/nl/hellolib.po +24 -0
  143. data/samples/cgi/po/nl/main.po +86 -0
  144. data/samples/cgi/po/pt_BR/helloerb1.po +59 -0
  145. data/samples/cgi/po/pt_BR/helloerb2.po +51 -0
  146. data/samples/cgi/po/pt_BR/hellolib.po +23 -0
  147. data/samples/cgi/po/pt_BR/main.po +84 -0
  148. data/samples/cgi/po/ru/helloerb1.po +58 -0
  149. data/samples/cgi/po/ru/helloerb2.po +50 -0
  150. data/samples/cgi/po/ru/hellolib.po +22 -0
  151. data/samples/cgi/po/ru/main.po +82 -0
  152. data/samples/cgi/po/sr/helloerb1.po +60 -0
  153. data/samples/cgi/po/sr/helloerb2.po +52 -0
  154. data/samples/cgi/po/sr/hellolib.po +24 -0
  155. data/samples/cgi/po/sr/main.po +80 -0
  156. data/samples/cgi/po/ua/helloerb1.po +62 -0
  157. data/samples/cgi/po/ua/helloerb2.po +54 -0
  158. data/samples/cgi/po/ua/hellolib.po +26 -0
  159. data/samples/cgi/po/ua/main.po +84 -0
  160. data/samples/cgi/po/vi/helloerb1.po +65 -0
  161. data/samples/cgi/po/vi/helloerb2.po +52 -0
  162. data/samples/cgi/po/vi/hellolib.po +24 -0
  163. data/samples/cgi/po/vi/main.po +77 -0
  164. data/samples/cgi/po/zh/helloerb1.po +60 -0
  165. data/samples/cgi/po/zh/helloerb2.po +52 -0
  166. data/samples/cgi/po/zh/hellolib.po +24 -0
  167. data/samples/cgi/po/zh/main.po +80 -0
  168. data/samples/cgi/po/zh_TW/helloerb1.po +67 -0
  169. data/samples/cgi/po/zh_TW/helloerb2.po +54 -0
  170. data/samples/cgi/po/zh_TW/hellolib.po +26 -0
  171. data/samples/cgi/po/zh_TW/main.po +79 -0
  172. data/samples/hello.rb +36 -0
  173. data/samples/hello2.rb +23 -0
  174. data/samples/hello_glade2.glade +70 -0
  175. data/samples/hello_glade2.rb +25 -0
  176. data/samples/hello_gtk2.rb +27 -0
  177. data/samples/hello_noop.rb +31 -0
  178. data/samples/hello_plural.rb +26 -0
  179. data/samples/hello_tk.rb +19 -0
  180. data/samples/makemo.rb +4 -0
  181. data/samples/po/bg/hello.po +24 -0
  182. data/samples/po/bg/hello2.po +31 -0
  183. data/samples/po/bg/hello_glade2.po +31 -0
  184. data/samples/po/bg/hello_gtk.po +23 -0
  185. data/samples/po/bg/hello_noop.po +27 -0
  186. data/samples/po/bg/hello_plural.po +25 -0
  187. data/samples/po/bg/hello_tk.po +23 -0
  188. data/samples/po/bs/hello.po +23 -0
  189. data/samples/po/bs/hello2.po +31 -0
  190. data/samples/po/bs/hello_glade2.po +31 -0
  191. data/samples/po/bs/hello_gtk.po +23 -0
  192. data/samples/po/bs/hello_noop.po +27 -0
  193. data/samples/po/bs/hello_plural.po +26 -0
  194. data/samples/po/bs/hello_tk.po +23 -0
  195. data/samples/po/ca/hello.po +23 -0
  196. data/samples/po/ca/hello2.po +31 -0
  197. data/samples/po/ca/hello_glade2.po +31 -0
  198. data/samples/po/ca/hello_gtk.po +23 -0
  199. data/samples/po/ca/hello_noop.po +27 -0
  200. data/samples/po/ca/hello_plural.po +25 -0
  201. data/samples/po/ca/hello_tk.po +23 -0
  202. data/samples/po/cs/hello.po +23 -0
  203. data/samples/po/cs/hello2.po +31 -0
  204. data/samples/po/cs/hello_glade2.po +37 -0
  205. data/samples/po/cs/hello_gtk.po +23 -0
  206. data/samples/po/cs/hello_noop.po +27 -0
  207. data/samples/po/cs/hello_plural.po +26 -0
  208. data/samples/po/cs/hello_tk.po +23 -0
  209. data/samples/po/de/hello.po +20 -0
  210. data/samples/po/de/hello2.po +28 -0
  211. data/samples/po/de/hello_glade2.po +27 -0
  212. data/samples/po/de/hello_gtk.po +20 -0
  213. data/samples/po/de/hello_noop.po +24 -0
  214. data/samples/po/de/hello_plural.po +25 -0
  215. data/samples/po/de/hello_tk.po +20 -0
  216. data/samples/po/el/hello.po +23 -0
  217. data/samples/po/el/hello2.po +31 -0
  218. data/samples/po/el/hello_glade2.po +31 -0
  219. data/samples/po/el/hello_gtk.po +22 -0
  220. data/samples/po/el/hello_noop.po +27 -0
  221. data/samples/po/el/hello_plural.po +25 -0
  222. data/samples/po/el/hello_tk.po +23 -0
  223. data/samples/po/eo/hello.po +23 -0
  224. data/samples/po/eo/hello2.po +31 -0
  225. data/samples/po/eo/hello_glade2.po +32 -0
  226. data/samples/po/eo/hello_gtk.po +23 -0
  227. data/samples/po/eo/hello_noop.po +27 -0
  228. data/samples/po/eo/hello_plural.po +26 -0
  229. data/samples/po/eo/hello_tk.po +24 -0
  230. data/samples/po/es/hello.po +21 -0
  231. data/samples/po/es/hello2.po +28 -0
  232. data/samples/po/es/hello_glade2.po +28 -0
  233. data/samples/po/es/hello_gtk.po +20 -0
  234. data/samples/po/es/hello_noop.po +24 -0
  235. data/samples/po/es/hello_plural.po +23 -0
  236. data/samples/po/es/hello_tk.po +20 -0
  237. data/samples/po/fr/hello.po +18 -0
  238. data/samples/po/fr/hello2.po +26 -0
  239. data/samples/po/fr/hello_glade2.po +27 -0
  240. data/samples/po/fr/hello_gtk.po +18 -0
  241. data/samples/po/fr/hello_noop.po +22 -0
  242. data/samples/po/fr/hello_plural.po +21 -0
  243. data/samples/po/fr/hello_tk.po +18 -0
  244. data/samples/po/hello.pot +23 -0
  245. data/samples/po/hello2.pot +31 -0
  246. data/samples/po/hello_glade2.pot +32 -0
  247. data/samples/po/hello_gtk.pot +23 -0
  248. data/samples/po/hello_noop.pot +27 -0
  249. data/samples/po/hello_plural.pot +26 -0
  250. data/samples/po/hello_tk.pot +24 -0
  251. data/samples/po/hr/hello.po +23 -0
  252. data/samples/po/hr/hello2.po +31 -0
  253. data/samples/po/hr/hello_glade2.po +31 -0
  254. data/samples/po/hr/hello_gtk.po +23 -0
  255. data/samples/po/hr/hello_noop.po +27 -0
  256. data/samples/po/hr/hello_plural.po +26 -0
  257. data/samples/po/hr/hello_tk.po +23 -0
  258. data/samples/po/hu/hello.po +22 -0
  259. data/samples/po/hu/hello2.po +30 -0
  260. data/samples/po/hu/hello_glade2.po +31 -0
  261. data/samples/po/hu/hello_gtk.po +22 -0
  262. data/samples/po/hu/hello_noop.po +26 -0
  263. data/samples/po/hu/hello_plural.po +25 -0
  264. data/samples/po/hu/hello_tk.po +23 -0
  265. data/samples/po/it/hello.po +20 -0
  266. data/samples/po/it/hello2.po +28 -0
  267. data/samples/po/it/hello_glade2.po +28 -0
  268. data/samples/po/it/hello_gtk.po +21 -0
  269. data/samples/po/it/hello_noop.po +24 -0
  270. data/samples/po/it/hello_plural.po +23 -0
  271. data/samples/po/it/hello_tk.po +21 -0
  272. data/samples/po/ja/hello.po +20 -0
  273. data/samples/po/ja/hello2.po +28 -0
  274. data/samples/po/ja/hello_glade2.po +26 -0
  275. data/samples/po/ja/hello_gtk.po +19 -0
  276. data/samples/po/ja/hello_noop.po +23 -0
  277. data/samples/po/ja/hello_plural.po +21 -0
  278. data/samples/po/ja/hello_tk.po +19 -0
  279. data/samples/po/ko/hello.po +18 -0
  280. data/samples/po/ko/hello2.po +26 -0
  281. data/samples/po/ko/hello_glade2.po +29 -0
  282. data/samples/po/ko/hello_gtk.po +18 -0
  283. data/samples/po/ko/hello_noop.po +22 -0
  284. data/samples/po/ko/hello_plural.po +25 -0
  285. data/samples/po/ko/hello_tk.po +19 -0
  286. data/samples/po/lv/hello.po +24 -0
  287. data/samples/po/lv/hello2.po +32 -0
  288. data/samples/po/lv/hello_glade2.po +38 -0
  289. data/samples/po/lv/hello_gtk.po +24 -0
  290. data/samples/po/lv/hello_noop.po +28 -0
  291. data/samples/po/lv/hello_plural.po +26 -0
  292. data/samples/po/lv/hello_tk.po +24 -0
  293. data/samples/po/nb/hello.po +23 -0
  294. data/samples/po/nb/hello2.po +31 -0
  295. data/samples/po/nb/hello_glade2.po +31 -0
  296. data/samples/po/nb/hello_gtk.po +23 -0
  297. data/samples/po/nb/hello_noop.po +27 -0
  298. data/samples/po/nb/hello_plural.po +26 -0
  299. data/samples/po/nb/hello_tk.po +24 -0
  300. data/samples/po/nl/hello.po +24 -0
  301. data/samples/po/nl/hello2.po +32 -0
  302. data/samples/po/nl/hello_glade2.po +31 -0
  303. data/samples/po/nl/hello_gtk.po +24 -0
  304. data/samples/po/nl/hello_noop.po +28 -0
  305. data/samples/po/nl/hello_plural.po +25 -0
  306. data/samples/po/nl/hello_tk.po +24 -0
  307. data/samples/po/pt_BR/hello.po +21 -0
  308. data/samples/po/pt_BR/hello2.po +29 -0
  309. data/samples/po/pt_BR/hello_glade2.po +29 -0
  310. data/samples/po/pt_BR/hello_gtk.po +21 -0
  311. data/samples/po/pt_BR/hello_noop.po +25 -0
  312. data/samples/po/pt_BR/hello_plural.po +23 -0
  313. data/samples/po/pt_BR/hello_tk.po +21 -0
  314. data/samples/po/ru/hello.po +22 -0
  315. data/samples/po/ru/hello2.po +30 -0
  316. data/samples/po/ru/hello_glade2.po +30 -0
  317. data/samples/po/ru/hello_gtk.po +22 -0
  318. data/samples/po/ru/hello_noop.po +26 -0
  319. data/samples/po/ru/hello_plural.po +28 -0
  320. data/samples/po/ru/hello_tk.po +22 -0
  321. data/samples/po/sr/hello.po +22 -0
  322. data/samples/po/sr/hello2.po +30 -0
  323. data/samples/po/sr/hello_glade2.po +32 -0
  324. data/samples/po/sr/hello_gtk.po +22 -0
  325. data/samples/po/sr/hello_noop.po +26 -0
  326. data/samples/po/sr/hello_plural.po +26 -0
  327. data/samples/po/sr/hello_tk.po +24 -0
  328. data/samples/po/sv/hello.po +20 -0
  329. data/samples/po/sv/hello2.po +28 -0
  330. data/samples/po/sv/hello_glade2.po +28 -0
  331. data/samples/po/sv/hello_gtk.po +20 -0
  332. data/samples/po/sv/hello_noop.po +24 -0
  333. data/samples/po/sv/hello_plural.po +23 -0
  334. data/samples/po/sv/hello_tk.po +20 -0
  335. data/samples/po/test.rb +11 -0
  336. data/samples/po/ua/hello.po +22 -0
  337. data/samples/po/ua/hello2.po +30 -0
  338. data/samples/po/ua/hello_glade2.po +34 -0
  339. data/samples/po/ua/hello_gtk.po +22 -0
  340. data/samples/po/ua/hello_noop.po +26 -0
  341. data/samples/po/ua/hello_plural.po +29 -0
  342. data/samples/po/ua/hello_tk.po +26 -0
  343. data/samples/po/vi/hello.po +23 -0
  344. data/samples/po/vi/hello2.po +31 -0
  345. data/samples/po/vi/hello_glade2.po +38 -0
  346. data/samples/po/vi/hello_gtk.po +23 -0
  347. data/samples/po/vi/hello_noop.po +27 -0
  348. data/samples/po/vi/hello_plural.po +26 -0
  349. data/samples/po/vi/hello_tk.po +24 -0
  350. data/samples/po/zh/hello.po +23 -0
  351. data/samples/po/zh/hello2.po +31 -0
  352. data/samples/po/zh/hello_glade2.po +31 -0
  353. data/samples/po/zh/hello_gtk.po +23 -0
  354. data/samples/po/zh/hello_noop.po +27 -0
  355. data/samples/po/zh/hello_plural.po +25 -0
  356. data/samples/po/zh/hello_tk.po +23 -0
  357. data/samples/po/zh_TW/hello.po +26 -0
  358. data/samples/po/zh_TW/hello2.po +34 -0
  359. data/samples/po/zh_TW/hello_glade2.po +40 -0
  360. data/samples/po/zh_TW/hello_gtk.po +25 -0
  361. data/samples/po/zh_TW/hello_noop.po +30 -0
  362. data/samples/po/zh_TW/hello_plural.po +28 -0
  363. data/samples/po/zh_TW/hello_tk.po +26 -0
  364. data/test/README +1 -0
  365. data/test/Rakefile +17 -0
  366. data/test/po/cr/plural.po +23 -0
  367. data/test/po/da/plural.po +22 -0
  368. data/test/po/da/plural_error.po +22 -0
  369. data/test/po/fr/plural.po +28 -0
  370. data/test/po/fr/plural_error.po +20 -0
  371. data/test/po/fr/test1.po +23 -0
  372. data/test/po/fr/test2.po +19 -0
  373. data/test/po/ir/plural.po +23 -0
  374. data/test/po/ja/npgettext.po +46 -0
  375. data/test/po/ja/nsgettext.po +65 -0
  376. data/test/po/ja/pgettext.po +41 -0
  377. data/test/po/ja/plural.po +28 -0
  378. data/test/po/ja/plural_error.po +20 -0
  379. data/test/po/ja/rubyparser.po +43 -0
  380. data/test/po/ja/sgettext.po +47 -0
  381. data/test/po/ja/test1.po +23 -0
  382. data/test/po/ja/test2.po +19 -0
  383. data/test/po/ja/test3.po +19 -0
  384. data/test/po/la/plural.po +23 -0
  385. data/test/po/la/plural_error.po +21 -0
  386. data/test/po/li/plural.po +23 -0
  387. data/test/po/li/plural_error.po +27 -0
  388. data/test/po/po/plural.po +23 -0
  389. data/test/po/sl/plural.po +24 -0
  390. data/test/test_class_info.rb +83 -0
  391. data/test/test_gettext.rb +311 -0
  392. data/test/test_locale_path.rb +50 -0
  393. data/test/test_parser.rb +157 -0
  394. data/test/test_po_generation.rb +20 -0
  395. data/test/test_string.rb +65 -0
  396. data/test/test_textdomain_bind.rb +37 -0
  397. data/test/test_textdomain_multi.rb +80 -0
  398. data/test/test_textdomain_toplevel.rb +42 -0
  399. data/test/test_thread.rb +41 -0
  400. data/test/test_translation_target.rb +29 -0
  401. data/test/testlib/N_.rb +66 -0
  402. data/test/testlib/erb.rhtml +15 -0
  403. data/test/testlib/erb.rxml +16 -0
  404. data/test/testlib/gettext.rb +113 -0
  405. data/test/testlib/gladeparser.glade +183 -0
  406. data/test/testlib/helper.rb +11 -0
  407. data/test/testlib/multi_textdomain.rb +131 -0
  408. data/test/testlib/ngettext.rb +79 -0
  409. data/test/testlib/npgettext.rb +31 -0
  410. data/test/testlib/nsgettext.rb +42 -0
  411. data/test/testlib/pgettext.rb +36 -0
  412. data/test/testlib/sgettext.rb +46 -0
  413. data/test/testlib/simple.rb +14 -0
  414. data/test/tools/files/app.pot +0 -0
  415. data/test/tools/files/de/app.po +0 -0
  416. data/test/tools/files/en/app.po +0 -0
  417. data/test/tools/files/en/test.po +21 -0
  418. data/test/tools/files/simple_1.po +2 -0
  419. data/test/tools/files/simple_2.po +2 -0
  420. data/test/tools/files/simple_translation.rb +1 -0
  421. data/test/tools/files/version.po +7 -0
  422. data/test/tools/test.pot +21 -0
  423. data/test/tools/test_tools.rb +61 -0
  424. metadata +510 -0
@@ -0,0 +1,195 @@
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
+ # Currently, GNU msgmerge doesn't accept BOM.
28
+ # This mesthod remove the UTF-8 BOM from the po-file.
29
+ def remove_bom(path) #:nodoc:
30
+ bom = IO.read(path, 3)
31
+ if bom == BOM_UTF8
32
+ data = IO.read(path)[3..-1]
33
+ File.open(path, "w") {|f| f.write(data)}
34
+ end
35
+ end
36
+
37
+ # Merges two Uniforum style .po files together.
38
+ #
39
+ # *Note* This function requires "msgmerge" tool included in GNU GetText. So you need to install GNU GetText.
40
+ #
41
+ # The def.po file is an existing PO file with translations which will be taken
42
+ # over to the newly created file as long as they still match; comments will be preserved,
43
+ # but extracted comments and file positions will be discarded.
44
+ #
45
+ # The ref.pot file is the last created PO file with up-to-date source references but
46
+ # old translations, or a PO Template file (generally created by rgettext);
47
+ # any translations or comments in the file will be discarded, however dot
48
+ # comments and file positions will be preserved. Where an exact match
49
+ # cannot be found, fuzzy matching is used to produce better results.
50
+ #
51
+ # Usually you don't need to call this function directly. Use GetText.update_pofiles instead.
52
+ #
53
+ # * defpo: a po-file. translations referring to old sources
54
+ # * refpo: a po-file. references to new sources
55
+ # * app_version: the application information which appears "Project-Id-Version: #{app_version}" in the pot/po-files.
56
+ # * Returns: self
57
+ def msgmerge(defpo, refpo, app_version, options={})
58
+ verbose = options.delete(:verbose)
59
+ puts "msgmerge called" if verbose
60
+ $stderr.print defpo + " "
61
+
62
+ content = merge_po_files(defpo,refpo,options.delete(:msgmerge),verbose)
63
+
64
+ if content.empty?
65
+ # report failure
66
+ failed_filename = refpo + "~"
67
+ FileUtils.cp(refpo, failed_filename)
68
+ $stderr.puts _("Failed to merge with %{defpo}") % {:defpo => defpo}
69
+ $stderr.puts _("New .pot was copied to %{failed_filename}") %{:failed_filename => failed_filename}
70
+ raise _("Check these po/pot-files. It may have syntax errors or something wrong.")
71
+ else
72
+ # update version and save merged data
73
+ content.sub!(/(Project-Id-Version\:).*$/, "\\1 #{app_version}\\n\"")
74
+ File.open(defpo, "w") {|f|f.write(content)}
75
+ end
76
+
77
+ self
78
+ end
79
+
80
+ # Creates mo-files using #{po_root}/#{lang}/*.po an put them to
81
+ # #{targetdir}/#{targetdir_rule}/.
82
+ #
83
+ # This is a convenience function of GetText.rmsgfmt for multiple target files.
84
+ # * options: options as a Hash.
85
+ # * verbose: true if verbose mode, otherwise false
86
+ # * po_root: the root directory of po-files.
87
+ # * mo_root: the target root directory where the mo-files are stored.
88
+ # * mo_path_rule: the target directory for each mo-files.
89
+ def create_mofiles(options = {})
90
+ options = {:po_root => "./po"}.merge(options)
91
+
92
+ Dir.glob(File.join(options[:po_root], "*/*.po")) do |po_file|
93
+ mo_file = mo_file_from_po_file(po_file,options)
94
+ $stderr.print %Q[#{po_file} -> #{mo_file} ... ] if options[:verbose]
95
+ FileUtils.mkdir_p(File.dirname(mo_file))
96
+ rmsgfmt(po_file, mo_file)
97
+ $stderr.puts "Done." if options[:verbose]
98
+ end
99
+ end
100
+
101
+
102
+ # At first, this creates the #{po_root}/#{domainname}.pot file using GetText.rgettext.
103
+ # In the second step, this updates(merges) the #{po_root}/#{domainname}.pot and all of the
104
+ # #{po_root}/#{lang}/#{domainname}.po files under "po_root" using "msgmerge".
105
+ #
106
+ # *Note* "msgmerge" tool is included in GNU GetText. So you need to install GNU GetText.
107
+ #
108
+ # See <HOWTO maintain po/mo files(http://www.yotabanana.com/hiki/ruby-gettext-howto-manage.html)> for more detals.
109
+ # * domainname: the textdomain name.
110
+ # * targetfiles: An Array of target files, that should be parsed for messages (See GetText.rgettext for more details).
111
+ # * app_version: the application information which appears "Project-Id-Version: #{app_version}" in the pot/po-files.
112
+ # * options: a hash with following possible settings
113
+ # :lang - update files only for one language - the language specified by this option
114
+ # :po_root - the root directory of po-files
115
+ # :msgmerge - an array with the options, passed through to the gnu msgmerge tool
116
+ # symbols are automatically translated to options with dashes,
117
+ # example: [:no_wrap, :no_fuzzy_matching, :sort_output] translated to '--no-fuzzy-matching --sort-output'
118
+ # :verbose - true to show verbose messages. default is false.
119
+ #
120
+ # Example: GetText.update_pofiles("myapp", Dir.glob("lib/*.rb"), "myapp 1.0.0", :verbose => true)
121
+ def update_pofiles(textdomain, files, app_version, options = {})
122
+ puts options.inspect if options[:verbose]
123
+
124
+ #write found messages to tmp.pot
125
+ temp_pot = "tmp.pot"
126
+ rgettext(files, temp_pot)
127
+
128
+ #merge tmp.pot and existing pot
129
+ po_root = options.delete(:po_root) || "po"
130
+ FileUtils.mkdir_p(po_root)
131
+ msgmerge("#{po_root}/#{textdomain}.pot", temp_pot, app_version, options.dup)
132
+
133
+ #update local po-files
134
+ only_one_language = options.delete(:lang)
135
+ if only_one_language
136
+ msgmerge("#{po_root}/#{only_one_language}/#{textdomain}.po", temp_pot, app_version, options.dup)
137
+ else
138
+ Dir.glob("#{po_root}/*/#{textdomain}.po") do |po_file|
139
+ msgmerge(po_file, temp_pot, app_version, options.dup)
140
+ end
141
+ end
142
+
143
+ File.delete(temp_pot)
144
+ end
145
+
146
+ private
147
+
148
+ # Merge 2 po files, using msgmerge
149
+ def merge_po_files(po_a,po_b,msgmerge_options=[],verbose=false)
150
+ return File.read(po_b) unless FileTest.exist? po_a
151
+
152
+ cmd = ENV["MSGMERGE_PATH"] || "msgmerge"
153
+ ensure_command_exists(cmd)
154
+
155
+ remove_bom(po_a)
156
+
157
+ cmd_params = array_to_cli_options(msgmerge_options)
158
+ to_run = "#{cmd} #{cmd_params} #{po_a} #{po_b}"
159
+ puts "\nrunning #{to_run}" if verbose
160
+ `#{to_run}`
161
+ end
162
+
163
+ # convert an array of String/Symbol to cli options
164
+ def array_to_cli_options(array)
165
+ [*array].map do |o|
166
+ o.kind_of?(Symbol) ? "--#{o}".gsub('_','-') : o.to_s
167
+ end.join(' ')
168
+ end
169
+
170
+ def ensure_command_exists(cmd)
171
+ `#{cmd} --help`
172
+ unless $? && $?.success?
173
+ raise _("`%{cmd}' can not be found. \nInstall GNU Gettext then set PATH or MSGMERGE_PATH correctly.") % {:cmd => cmd}
174
+ end
175
+ end
176
+
177
+ # where lies the mo file for a given po_file
178
+ # generare directory unless it exists
179
+ def mo_file_from_po_file(po_file,options)
180
+ options = {
181
+ :mo_root => "./data/locale",
182
+ :mo_path_rule => "%{lang}/LC_MESSAGES"
183
+ }.merge(options)
184
+
185
+ lang, textdomain = %r[/([^/]+?)/(.*)\.po].match(po_file[options[:po_root].size..-1]).to_a[1,2]
186
+
187
+ mo_dir_rule = File.join(options[:mo_root], options[:mo_path_rule])
188
+ mo_dir = mo_dir_rule % {:lang => lang}
189
+ File.join(mo_dir, "#{textdomain}.mo")
190
+ end
191
+ end
192
+
193
+ if __FILE__ == $0
194
+ GetText.update_pofiles("foo", ARGV, "foo 1.1.0")
195
+ end
@@ -0,0 +1,93 @@
1
+ module GetText
2
+ class ParseError < StandardError
3
+ end
4
+
5
+ # Contains data related to the expression or sentence that
6
+ # is to be translated (translation target).
7
+ # Implements a sort of state machine to assist the parser.
8
+ class TranslationTarget
9
+ attr_accessor :type, :msgid, :occurrences # obligatory attributes
10
+ attr_accessor :plural, :msgctxt, :extracted_comment # optional attributes
11
+
12
+ def initialize(new_type)
13
+ @type = new_type
14
+ @occurrences = Array.new
15
+ @param_number = 0
16
+ end
17
+
18
+ # Supports parsing by setting attributes by and by.
19
+ def set_current_attribute(str)
20
+ case @param_number
21
+ when 0
22
+ set_string_value :msgid, str
23
+ when 1
24
+ case type
25
+ when :plural
26
+ set_string_value :plural, str
27
+ when :msgctxt, :msgctxt_plural
28
+ set_string_value :msgctxt, str
29
+ else
30
+ raise ParseError, 'no more string parameters expected'
31
+ end
32
+ when 2
33
+ if :msgctxt_plural
34
+ set_string_value plural, str
35
+ else
36
+ raise ParseError, 'no more string parameters expected'
37
+ end
38
+ end
39
+ end
40
+
41
+ def advance_to_next_attribute
42
+ @param_number += 1
43
+ end
44
+
45
+ # Support for extracted comments. Explanation s.
46
+ # http://www.gnu.org/software/gettext/manual/gettext.html#Names
47
+ def add_extracted_comment(new_comment)
48
+ @extracted_comment = @extracted_comment.to_s + new_comment
49
+ to_s
50
+ end
51
+
52
+ # Returns a parameter representation suitable for po-files
53
+ # and other purposes.
54
+ def escaped(param_name)
55
+ orig = self.send param_name
56
+ orig.gsub(/"/, '\"').gsub(/\r/, '')
57
+ end
58
+
59
+ # Checks if the other translation target is mergeable with
60
+ # the current one. Relevant are msgid and translation context (msgctxt).
61
+ def matches?(other)
62
+ other.msgid == self.msgid && other.msgctxt == self.msgctxt
63
+ end
64
+
65
+ # Merges two translation targets with the same msgid and returns the merged
66
+ # result. If one is declared as plural and the other not, then the one
67
+ # with the plural wins.
68
+ def merge(other)
69
+ return self if other.nil?
70
+ raise ParseError, "Translation targets do not match: \n" \
71
+ " self: #{self.inspect}\n other: '#{other.inspect}'" unless matches?(other)
72
+ if other.plural && !self.plural
73
+ res = other
74
+ res.occurrences.concat self.occurrences
75
+ else
76
+ res = self
77
+ res.occurrences.concat other.occurrences
78
+ end
79
+ res
80
+ end
81
+
82
+ private
83
+
84
+ # sets or extends the value of a translation target params like msgid,
85
+ # msgctxt etc.
86
+ # param is symbol with the name of param
87
+ # value - new value
88
+ def set_string_value(param, value)
89
+ send "#{param}=", (send(param) || '') + value.gsub(/\n/, '\n')
90
+ end
91
+ end
92
+
93
+ end
@@ -0,0 +1,37 @@
1
+ =begin
2
+ utils.rb - Utility functions
3
+
4
+ Copyright (C) 2005,2006 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 'gettext/tools'
11
+
12
+ warn "'gettext/utils.rb' is deprecated. Use gettext/tools.rb."
13
+
14
+ module GetText
15
+
16
+ alias :create_mofiles_org :create_mofiles #:nodoc:
17
+ alias :update_pofiles_org :update_pofiles #:nodoc:
18
+
19
+
20
+ # Deprecated. Use gettext/tools instead.
21
+ def create_mofiles(verbose = false,
22
+ podir = "./po", targetdir = "./data/locale",
23
+ targetpath_rule = "%s/LC_MESSAGES") # :nodoc:
24
+ warn "'gettext/utils.rb' is deprecated. Use gettext/tools.rb."
25
+ create_mofiles_org(:verbose => verbose,
26
+ :po_root => podir,
27
+ :mo_root => targetdir,
28
+ :mo_root_rule => targetpath_rule)
29
+ end
30
+
31
+ # Deprecated. Use gettext/tools instead.
32
+ def update_pofiles(textdomain, files, app_version, po_root = "po", refpot = "tmp.pot") # :nodoc:
33
+ warn "'gettext/utils.rb' is deprecated. Use gettext/tools.rb."
34
+ options = {:po_root => po_root}
35
+ update_pofiles_org(textdomain, files, app_version, options)
36
+ end
37
+ end
@@ -0,0 +1,12 @@
1
+ #! /usr/bin/ruby
2
+ =begin
3
+ version - version information of Ruby-GetText-Package
4
+
5
+ Copyright (C) 2005-2009 Masao Mutoh
6
+
7
+ You may redistribute it and/or modify it under the same
8
+ license terms as Ruby.
9
+ =end
10
+ module GetText
11
+ VERSION = "2.0.4"
12
+ end
data/lib/gettext.rb ADDED
@@ -0,0 +1,312 @@
1
+ =begin
2
+ gettext.rb - GetText module
3
+
4
+ Copyright (C) 2001-2009 Masao Mutoh
5
+ Copyright (C) 2001-2003 Masahiro Sakai
6
+
7
+ Masao Mutoh <mutomasa at gmail.com>
8
+ Masahiro Sakai <s01397ms@sfc.keio.ac.jp>
9
+
10
+ You may redistribute it and/or modify it under the same
11
+ license terms as Ruby.
12
+
13
+ $Id: gettext.rb,v 1.46 2008/09/13 18:23:55 mutoh Exp $
14
+ =end
15
+
16
+ if Object.constants.include? "Gem"
17
+ begin
18
+ begin
19
+ gem 'locale', '>=2.0.4'
20
+ rescue Gem::LoadError
21
+ end
22
+ rescue NoMethodError
23
+ else LoadError
24
+ end
25
+ end
26
+
27
+ require 'locale'
28
+ raise "Install locale as gem or uninstall old gettext" unless Locale.respond_to? :candidates
29
+
30
+ require 'gettext/version'
31
+ require 'gettext/textdomain_manager'
32
+
33
+ module GetText
34
+ # If the textdomain isn't bound when calling GetText.textdomain, this error is raised.
35
+ class NoboundTextDomainError < RuntimeError
36
+ def initialize(domainname)
37
+ @domainname = domainname
38
+ end
39
+ def message
40
+ "#{@domainname} is not bound."
41
+ end
42
+ end
43
+
44
+ extend self
45
+
46
+ def self.included(mod) #:nodoc:
47
+ mod.extend self
48
+ end
49
+
50
+ # bindtextdomain(domainname, options = {})
51
+ #
52
+ # Bind a textdomain(%{path}/%{locale}/LC_MESSAGES/%{domainname}.mo) to
53
+ # your program.
54
+ # Normally, the texdomain scope becomes the class/module(and parent
55
+ # classes/included modules).
56
+ #
57
+ # * domainname: the textdomain name.
58
+ # * options: options as an Hash.
59
+ # * :path - the path to the mo-files. When the value is nil, it will search default paths such as
60
+ # /usr/share/locale, /usr/local/share/locale)
61
+ # * :output_charset - The output charset. Same with GetText.set_output_charset. Usually, L10n
62
+ # library doesn't use this option. Application may use this once.
63
+ # * Returns: the GetText::TextDomainManager.
64
+ #
65
+ def bindtextdomain(domainname, *options)
66
+ bindtextdomain_to(self, domainname, *options)
67
+ end
68
+
69
+ # Includes GetText module and bind a textdomain to a class.
70
+ # * klass: the target ruby class.
71
+ # * domainname: the textdomain name.
72
+ # * options: options as an Hash. See GetText.bindtextdomain.
73
+ def bindtextdomain_to(klass, domainname, *options)
74
+ if options[0].kind_of? Hash
75
+ opts = options[0]
76
+ else
77
+ # for backward compatibility.
78
+ opts = {}
79
+ opts[:path] = options[0] if options[0]
80
+ opts[:output_charset] = options[2] if options[2]
81
+ end
82
+ unless (klass.kind_of? GetText or klass.include? GetText)
83
+ klass.__send__(:include, GetText)
84
+ end
85
+ TextDomainManager.bind_to(klass, domainname, opts)
86
+ end
87
+
88
+ # Binds a existed textdomain to your program.
89
+ # This is the same function with GetText.bindtextdomain but simpler(and faster) than bindtextdomain.
90
+ # Note that you need to call GetText.bindtextdomain first. If the domainname hasn't bound yet,
91
+ # raises GetText::NoboundTextDomainError.
92
+ # * domainname: a textdomain name.
93
+ # * Returns: the GetText::TextDomainManager.
94
+ def textdomain(domainname) #:nodoc:
95
+ textdomain_to(self, domainname)
96
+ end
97
+
98
+ # Includes GetText module and bind an exsited textdomain to a class.
99
+ # See textdomain for more detail.
100
+ # * klass: the target ruby class.
101
+ # * domainname: the textdomain name.
102
+
103
+ def textdomain_to(klass, domainname) #:nodoc:
104
+ domain = TextDomainManager.textdomain_pool(domainname)
105
+ raise NoboundTextDomainError.new(domainname) unless domain
106
+ bindtextdomain_to(klass, domainname)
107
+ end
108
+
109
+ # call-seq:
110
+ # gettext(msgid)
111
+ # _(msgid)
112
+ #
113
+ # Translates msgid and return the message.
114
+ # This doesn't make a copy of the message.
115
+ #
116
+ # You need to use String#dup if you want to modify the return value
117
+ # with destructive functions.
118
+ #
119
+ # (e.g.1) _("Hello ").dup << "world"
120
+ #
121
+ # But e.g.1 should be rewrite to:
122
+ #
123
+ # (e.g.2) _("Hello %{val}") % {:val => "world"}
124
+ #
125
+ # Because the translator may want to change the position of "world".
126
+ #
127
+ # * msgid: the message id.
128
+ # * Returns: localized text by msgid. If there are not binded mo-file, it will return msgid.
129
+ def gettext(msgid)
130
+ TextDomainManager.translate_singluar_message(self, msgid)
131
+ end
132
+
133
+ # call-seq:
134
+ # sgettext(msgid, div = '|')
135
+ # s_(msgid, div = '|')
136
+ #
137
+ # Translates msgid, but if there are no localized text,
138
+ # it returns a last part of msgid separeted "div".
139
+ #
140
+ # * msgid: the message id.
141
+ # * separator: separator or nil for no seperation.
142
+ # * Returns: the localized text by msgid. If there are no localized text,
143
+ # it returns a last part of the msgid separeted by "seperator".
144
+ # <tt>Movie|Location -> Location</tt>
145
+ # See: http://www.gnu.org/software/gettext/manual/html_mono/gettext.html#SEC151
146
+ def sgettext(msgid, seperator = "|")
147
+ TextDomainManager.translate_singluar_message(self, msgid, seperator)
148
+ end
149
+
150
+ # call-seq:
151
+ # pgettext(msgctxt, msgid)
152
+ # p_(msgctxt, msgid)
153
+ #
154
+ # Translates msgid with msgctxt. This methods is similer with s_().
155
+ # e.g.) p_("File", "New") == s_("File|New")
156
+ # p_("File", "Open") == s_("File|Open")
157
+ #
158
+ # * msgctxt: the message context.
159
+ # * msgid: the message id.
160
+ # * Returns: the localized text by msgid. If there are no localized text,
161
+ # it returns msgid.
162
+ # See: http://www.gnu.org/software/autoconf/manual/gettext/Contexts.html
163
+ def pgettext(msgctxt, msgid)
164
+ TextDomainManager.translate_singluar_message(self, "#{msgctxt}\004#{msgid}", "\004")
165
+ end
166
+
167
+ # call-seq:
168
+ # ngettext(msgid, msgid_plural, n)
169
+ # ngettext(msgids, n) # msgids = [msgid, msgid_plural]
170
+ # n_(msgid, msgid_plural, n)
171
+ # n_(msgids, n) # msgids = [msgid, msgid_plural]
172
+ #
173
+ # The ngettext is similar to the gettext function as it finds the message catalogs in the same way.
174
+ # But it takes two extra arguments for plural form.
175
+ #
176
+ # * msgid: the singular form.
177
+ # * msgid_plural: the plural form.
178
+ # * n: a number used to determine the plural form.
179
+ # * Returns: the localized text which key is msgid_plural if n is plural(follow plural-rule) or msgid.
180
+ # "plural-rule" is defined in po-file.
181
+ def ngettext(msgid, msgid_plural, n = nil)
182
+ TextDomainManager.translate_plural_message(self, msgid, msgid_plural, n)
183
+ end
184
+
185
+ # call-seq:
186
+ # nsgettext(msgid, msgid_plural, n, div = "|")
187
+ # nsgettext(msgids, n, div = "|") # msgids = [msgid, msgid_plural]
188
+ # ns_(msgid, msgid_plural, n, div = "|")
189
+ # ns_(msgids, n, div = "|") # msgids = [msgid, msgid_plural]
190
+ #
191
+ # The nsgettext is similar to the ngettext.
192
+ # But if there are no localized text,
193
+ # it returns a last part of msgid separeted "div".
194
+ #
195
+ # * msgid: the singular form with "div". (e.g. "Special|An apple")
196
+ # * msgid_plural: the plural form. (e.g. "%{num} Apples")
197
+ # * n: a number used to determine the plural form.
198
+ # * Returns: the localized text which key is msgid_plural if n is plural(follow plural-rule) or msgid.
199
+ # "plural-rule" is defined in po-file.
200
+ def nsgettext(msgid, msgid_plural, n="|", seperator = "|")
201
+ TextDomainManager.translate_plural_message(self, msgid, msgid_plural, n, seperator)
202
+ end
203
+
204
+ # call-seq:
205
+ # npgettext(msgctxt, msgid, msgid_plural, n)
206
+ # npgettext(msgctxt, msgids, n) # msgids = [msgid, msgid_plural]
207
+ # np_(msgctxt, msgid, msgid_plural, n)
208
+ # np_(msgctxt, msgids, n) # msgids = [msgid, msgid_plural]
209
+ #
210
+ # The npgettext is similar to the nsgettext function.
211
+ # e.g.) np_("Special", "An apple", "%{num} Apples", num) == ns_("Special|An apple", "%{num} Apples", num)
212
+ # * msgctxt: the message context.
213
+ # * msgid: the singular form.
214
+ # * msgid_plural: the plural form.
215
+ # * n: a number used to determine the plural form.
216
+ # * Returns: the localized text which key is msgid_plural if n is plural(follow plural-rule) or msgid.
217
+ # "plural-rule" is defined in po-file.
218
+ def npgettext(msgctxt, msgids, arg2 = nil, arg3 = nil)
219
+ if msgids.kind_of?(Array)
220
+ msgid = msgids[0]
221
+ msgid_ctxt = "#{msgctxt}\004#{msgid}"
222
+ msgid_plural = msgids[1]
223
+ opt1 = arg2
224
+ opt2 = arg3
225
+ else
226
+ msgid = msgids
227
+ msgid_ctxt = "#{msgctxt}\004#{msgid}"
228
+ msgid_plural = arg2
229
+ opt1 = arg3
230
+ opt2 = nil
231
+ end
232
+
233
+ msgstr = TextDomainManager.translate_plural_message(self, msgid_ctxt, msgid_plural, opt1, opt2)
234
+ if msgstr == msgid_ctxt
235
+ msgid
236
+ else
237
+ msgstr
238
+ end
239
+ end
240
+
241
+ # makes dynamic translation messages readable for the gettext parser.
242
+ # <tt>_(fruit)</tt> cannot be understood by the gettext parser. To help the parser find all your translations,
243
+ # you can add <tt>fruit = N_("Apple")</tt> which does not translate, but tells the parser: "Apple" needs translation.
244
+ # * msgid: the message id.
245
+ # * Returns: msgid.
246
+ def N_(msgid)
247
+ msgid
248
+ end
249
+
250
+ # This is same function as N_ but for ngettext.
251
+ # * msgid: the message id.
252
+ # * msgid_plural: the plural message id.
253
+ # * Returns: msgid.
254
+ def Nn_(msgid, msgid_plural)
255
+ [msgid, msgid_plural]
256
+ end
257
+
258
+ # Sets charset(String) such as "euc-jp", "sjis", "CP932", "utf-8", ...
259
+ # You shouldn't use this in your own Libraries.
260
+ # * charset: an output_charset
261
+ # * Returns: self
262
+ def set_output_charset(charset)
263
+ TextDomainManager.output_charset = charset
264
+ self
265
+ end
266
+
267
+ # Gets the current output_charset which is set using GetText.set_output_charset.
268
+ # * Returns: output_charset.
269
+ def output_charset
270
+ TextDomainManager.output_charset
271
+ end
272
+
273
+ # Set the locale. This value forces the locale whole the programs.
274
+ # This method calls Locale.set_app_language_tags, Locale.default, Locale.current.
275
+ # Use Locale methods if you need to handle locales more flexible.
276
+ def set_locale(lang)
277
+ Locale.set_app_language_tags(lang)
278
+ Locale.default = lang
279
+ Locale.current = lang
280
+ end
281
+
282
+ # Set the locale to the current thread.
283
+ # Note that if #set_locale is set, this value is ignored.
284
+ # If you need, set_locale(nil); set_current_locale(lang)
285
+ def set_current_locale(lang)
286
+ Locale.current = lang
287
+ end
288
+
289
+ def locale
290
+ Locale.current[0]
291
+ end
292
+
293
+ alias :locale= :set_locale #:nodoc:
294
+ alias :current_locale= :set_current_locale #:nodoc:
295
+ alias :_ :gettext #:nodoc:
296
+ alias :n_ :ngettext #:nodoc:
297
+ alias :s_ :sgettext #:nodoc:
298
+ alias :ns_ :nsgettext #:nodoc:
299
+ alias :np_ :npgettext #:nodoc:
300
+
301
+ alias :output_charset= :set_output_charset #:nodoc:
302
+
303
+ unless defined? XX
304
+ # This is the workaround to conflict p_ methods with the xx("double x") library.
305
+ # http://rubyforge.org/projects/codeforpeople/
306
+ alias :p_ :pgettext #:nodoc:
307
+ end
308
+
309
+ # for backward compatibility
310
+ alias :set_locale_all :set_locale #:nodoc:
311
+ alias :setlocale :set_locale #:nodoc:
312
+ end