1. sfMessageSource_gettext.class.php
  2. /** * sfMessageSource_gettext class. * * Using Gettext MO format as the message source for translation. * The gettext classes are based on PEAR's gettext MO and PO classes. * * See the MessageSource::factory() method to instantiate this class. * * @author Xiang Wei Zhuo * @version v1.0, last update on Fri Dec 24 16:18:44 EST 2004 * @package symfony * @subpackage i18n */
  3. class sfMessageSource_gettext extends sfMessageSource_File
  4. {
  5. /**
  6. * Message data filename extension.
  7. * @var string
  8. */
  9. protected $dataExt = '.mo';
  10. /**
  11. * PO data filename extension
  12. * @var string
  13. */
  14. protected $poExt = '.po';
  15. /**
  16. * Loads the messages from a MO file.
  17. *
  18. * @param string $filename MO file.
  19. * @return array of messages.
  20. */
  21. public function &loadData($filename)
  22. {
  23. $mo = TGettext::factory('MO',$filename);
  24. $mo->load();
  25. $result = $mo->toArray();
  26. $results = array();
  27. $count = 0;
  28. foreach ($result['strings'] as $source => $target)
  29. {
  30. $results[$source][] = $target; //target
  31. $results[$source][] = $count++; //id
  32. $results[$source][] = ''; //comments
  33. }
  34. return $results;
  35. }
  36. /**
  37. * Gets the variant for a catalogue depending on the current culture.
  38. *
  39. * @param string $catalogue catalogue
  40. * @return string the variant.
  41. * @see save()
  42. * @see update()
  43. * @see delete()
  44. */
  45. protected function getVariants($catalogue = 'messages')
  46. {
  47. if (empty($catalogue))
  48. {
  49. $catalogue = 'messages';
  50. }
  51. foreach ($this->getCatalogueList($catalogue) as $variant)
  52. {
  53. $file = $this->getSource($variant);
  54. $po = $this->getPOFile($file);
  55. if (is_file($file) || is_file($po))
  56. {
  57. return array($variant, $file, $po);
  58. }
  59. }
  60. return false;
  61. }
  62. protected function getPOFile($MOFile)
  63. {
  64. return substr($MOFile, 0, strlen($MOFile) - strlen($this->dataExt)).$this->poExt;
  65. }
  66. /**
  67. * Saves the list of untranslated blocks to the translation source.
  68. * If the translation was not found, you should add those
  69. * strings to the translation source via the <b>append()</b> method.
  70. *
  71. * @param string $catalogue the catalogue to add to
  72. * @return boolean true if saved successfuly, false otherwise.
  73. */
  74. function save($catalogue = 'messages')
  75. {
  76. $messages = $this->untranslated;
  77. if (count($messages) <= 0)
  78. {
  79. return false;
  80. }
  81. $variants = $this->getVariants($catalogue);
  82. if ($variants)
  83. {
  84. list($variant, $MOFile, $POFile) = $variants;
  85. }
  86. else
  87. {
  88. list($variant, $MOFile, $POFile) = $this->createMessageTemplate($catalogue);
  89. }
  90. if (is_writable($MOFile) == false)
  91. {
  92. throw new sfException(sprintf("Unable to save to file %s, file must be writable.", $MOFile));
  93. }
  94. if (is_writable($POFile) == false)
  95. {
  96. throw new sfException(sprintf("Unable to save to file %s, file must be writable.", $POFile));
  97. }
  98. // set the strings as untranslated.
  99. $strings = array();
  100. foreach ($messages as $message)
  101. {
  102. $strings[$message] = '';
  103. }
  104. // load the PO
  105. $po = TGettext::factory('PO',$POFile);
  106. $po->load();
  107. $result = $po->toArray();
  108. $existing = count($result['strings']);
  109. // add to strings to the existing message list
  110. $result['strings'] = array_merge($result['strings'],$strings);
  111. $new = count($result['strings']);
  112. if ($new > $existing)
  113. {
  114. // change the date 2004-12-25 12:26
  115. $result['meta']['PO-Revision-Date'] = @date('Y-m-d H:i:s');
  116. $po->fromArray($result);
  117. $mo = $po->toMO();
  118. if ($po->save() && $mo->save($MOFile))
  119. {
  120. if ($this->cache)
  121. {
  122. $this->cache->remove($variant.':'.$this->culture);
  123. }
  124. return true;
  125. }
  126. else
  127. {
  128. return false;
  129. }
  130. }
  131. return false;
  132. }
  133. /**
  134. * Deletes a particular message from the specified catalogue.
  135. *
  136. * @param string $message the source message to delete.
  137. * @param string $catalogue the catalogue to delete from.
  138. * @return boolean true if deleted, false otherwise.
  139. */
  140. function delete($message, $catalogue = 'messages')
  141. {
  142. $variants = $this->getVariants($catalogue);
  143. if ($variants)
  144. {
  145. list($variant, $MOFile, $POFile) = $variants;
  146. }
  147. else
  148. {
  149. return false;
  150. }
  151. if (is_writable($MOFile) == false)
  152. {
  153. throw new sfException(sprintf("Unable to modify file %s, file must be writable.", $MOFile));
  154. }
  155. if (is_writable($POFile) == false)
  156. {
  157. throw new sfException(sprintf("Unable to modify file %s, file must be writable.", $POFile));
  158. }
  159. $po = TGettext::factory('PO', $POFile);
  160. $po->load();
  161. $result = $po->toArray();
  162. foreach ($result['strings'] as $string => $value)
  163. {
  164. if ($string == $message)
  165. {
  166. $result['meta']['PO-Revision-Date'] = @date('Y-m-d H:i:s');
  167. unset($result['strings'][$string]);
  168. $po->fromArray($result);
  169. $mo = $po->toMO();
  170. if ($po->save() && $mo->save($MOFile))
  171. {
  172. if ($this->cache)
  173. {
  174. $this->cache->remove($variant.':'.$this->culture);
  175. }
  176. return true;
  177. }
  178. else
  179. {
  180. return false;
  181. }
  182. }
  183. }
  184. return false;
  185. }
  186. /**
  187. * Updates the translation.
  188. *
  189. * @param string $text the source string.
  190. * @param string $target the new translation string.
  191. * @param string $comments comments
  192. * @param string $catalogue the catalogue of the translation.
  193. * @return boolean true if translation was updated, false otherwise.
  194. */
  195. function update($text, $target, $comments, $catalogue = 'messages')
  196. {
  197. $variants = $this->getVariants($catalogue);
  198. if ($variants)
  199. {
  200. list($variant, $MOFile, $POFile) = $variants;
  201. }
  202. else
  203. {
  204. return false;
  205. }
  206. if (is_writable($MOFile) == false)
  207. {
  208. throw new sfException(sprintf("Unable to update file %s, file must be writable.", $MOFile));
  209. }
  210. if (is_writable($POFile) == false)
  211. {
  212. throw new sfException(sprintf("Unable to update file %s, file must be writable.", $POFile));
  213. }
  214. $po = TGettext::factory('PO',$POFile);
  215. $po->load();
  216. $result = $po->toArray();
  217. foreach ($result['strings'] as $string => $value)
  218. {
  219. if ($string == $text)
  220. {
  221. $result['strings'][$string] = $target;
  222. $result['meta']['PO-Revision-Date'] = @date('Y-m-d H:i:s');
  223. $po->fromArray($result);
  224. $mo = $po->toMO();
  225. if ($po->save() && $mo->save($MOFile))
  226. {
  227. if ($this->cache)
  228. {
  229. $this->cache->remove($variant.':'.$this->culture);
  230. }
  231. return true;
  232. }
  233. else
  234. {
  235. return false;
  236. }
  237. }
  238. }
  239. return false;
  240. }
  241. protected function createMessageTemplate($catalogue)
  242. {
  243. if (null === $catalogue)
  244. {
  245. $catalogue = 'messages';
  246. }
  247. $variants = $this->getCatalogueList($catalogue);
  248. $variant = array_shift($variants);
  249. $mo_file = $this->getSource($variant);
  250. $po_file = $this->getPOFile($mo_file);
  251. $dir = dirname($mo_file);
  252. if (!is_dir($dir))
  253. {
  254. @mkdir($dir);
  255. @chmod($dir, 0777);
  256. }
  257. if (!is_dir($dir))
  258. {
  259. throw new sfException(sprintf("Unable to create directory %s.", $dir));
  260. }
  261. $po = TGettext::factory('PO', $po_file);
  262. $result['meta']['PO-Revision-Date'] = date('Y-m-d H:i:s');
  263. $result['strings'] = array();
  264. $po->fromArray($result);
  265. $mo = $po->toMO();
  266. if ($po->save() && $mo->save($mo_file))
  267. {
  268. return array($variant, $mo_file, $po_file);
  269. }
  270. else
  271. {
  272. throw new sfException(sprintf("Unable to create file %s and %s.", $po_file, $mo_file));
  273. }
  274. }
  275. }

Debug toolbar