PoItem.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. <?php
  2. namespace Drupal\Component\Gettext;
  3. /**
  4. * PoItem handles one translation.
  5. *
  6. * @todo: This class contains some really old legacy code.
  7. * @see https://www.drupal.org/node/1637662
  8. */
  9. class PoItem {
  10. /**
  11. * The language code this translation is in.
  12. *
  13. * @var string
  14. */
  15. protected $langcode;
  16. /**
  17. * The context this translation belongs to.
  18. *
  19. * @var string
  20. */
  21. protected $context = '';
  22. /**
  23. * The source string or array of strings if it has plurals.
  24. *
  25. * @var string|array
  26. *
  27. * @see $plural
  28. */
  29. protected $source;
  30. /**
  31. * Flag indicating if this translation has plurals.
  32. *
  33. * @var bool
  34. */
  35. protected $plural;
  36. /**
  37. * The comment of this translation.
  38. *
  39. * @var string
  40. */
  41. protected $comment;
  42. /**
  43. * The translation string or array of strings if it has plurals.
  44. *
  45. * @var string|array
  46. * @see $plural
  47. */
  48. protected $translation;
  49. /**
  50. * Gets the language code of the currently used language.
  51. *
  52. * @return string with langcode
  53. */
  54. public function getLangcode() {
  55. return $this->langcode;
  56. }
  57. /**
  58. * Set the language code of the current language.
  59. *
  60. * @param string $langcode
  61. */
  62. public function setLangcode($langcode) {
  63. $this->langcode = $langcode;
  64. }
  65. /**
  66. * Gets the context this translation belongs to.
  67. *
  68. * @return string $context
  69. */
  70. public function getContext() {
  71. return $this->context;
  72. }
  73. /**
  74. * Set the context this translation belongs to.
  75. *
  76. * @param string $context
  77. */
  78. public function setContext($context) {
  79. $this->context = $context;
  80. }
  81. /**
  82. * Gets the source string or the array of strings if the translation has
  83. * plurals.
  84. *
  85. * @return string or array $translation
  86. */
  87. public function getSource() {
  88. return $this->source;
  89. }
  90. /**
  91. * Set the source string or the array of strings if the translation has
  92. * plurals.
  93. *
  94. * @param string|array $source
  95. */
  96. public function setSource($source) {
  97. $this->source = $source;
  98. }
  99. /**
  100. * Gets the translation string or the array of strings if the translation has
  101. * plurals.
  102. *
  103. * @return string or array $translation
  104. */
  105. public function getTranslation() {
  106. return $this->translation;
  107. }
  108. /**
  109. * Set the translation string or the array of strings if the translation has
  110. * plurals.
  111. *
  112. * @param string|array $translation
  113. */
  114. public function setTranslation($translation) {
  115. $this->translation = $translation;
  116. }
  117. /**
  118. * Set if the translation has plural values.
  119. *
  120. * @param bool $plural
  121. */
  122. public function setPlural($plural) {
  123. $this->plural = $plural;
  124. }
  125. /**
  126. * Get if the translation has plural values.
  127. *
  128. * @return bool
  129. */
  130. public function isPlural() {
  131. return $this->plural;
  132. }
  133. /**
  134. * Gets the comment of this translation.
  135. *
  136. * @return String $comment
  137. */
  138. public function getComment() {
  139. return $this->comment;
  140. }
  141. /**
  142. * Set the comment of this translation.
  143. *
  144. * @param string $comment
  145. */
  146. public function setComment($comment) {
  147. $this->comment = $comment;
  148. }
  149. /**
  150. * Create the PoItem from a structured array.
  151. *
  152. * @param array $values
  153. */
  154. public function setFromArray(array $values = []) {
  155. if (isset($values['context'])) {
  156. $this->setContext($values['context']);
  157. }
  158. if (isset($values['source'])) {
  159. $this->setSource($values['source']);
  160. }
  161. if (isset($values['translation'])) {
  162. $this->setTranslation($values['translation']);
  163. }
  164. if (isset($values['comment'])) {
  165. $this->setComment($values['comment']);
  166. }
  167. if (isset($this->source) &&
  168. strpos($this->source, LOCALE_PLURAL_DELIMITER) !== FALSE) {
  169. $this->setSource(explode(LOCALE_PLURAL_DELIMITER, $this->source));
  170. $this->setTranslation(explode(LOCALE_PLURAL_DELIMITER, $this->translation));
  171. $this->setPlural(count($this->source) > 1);
  172. }
  173. }
  174. /**
  175. * Output the PoItem as a string.
  176. */
  177. public function __toString() {
  178. return $this->formatItem();
  179. }
  180. /**
  181. * Format the POItem as a string.
  182. */
  183. private function formatItem() {
  184. $output = '';
  185. // Format string context.
  186. if (!empty($this->context)) {
  187. $output .= 'msgctxt ' . $this->formatString($this->context);
  188. }
  189. // Format translation.
  190. if ($this->plural) {
  191. $output .= $this->formatPlural();
  192. }
  193. else {
  194. $output .= $this->formatSingular();
  195. }
  196. // Add one empty line to separate the translations.
  197. $output .= "\n";
  198. return $output;
  199. }
  200. /**
  201. * Formats a plural translation.
  202. */
  203. private function formatPlural() {
  204. $output = '';
  205. // Format source strings.
  206. $output .= 'msgid ' . $this->formatString($this->source[0]);
  207. $output .= 'msgid_plural ' . $this->formatString($this->source[1]);
  208. foreach ($this->translation as $i => $trans) {
  209. if (isset($this->translation[$i])) {
  210. $output .= 'msgstr[' . $i . '] ' . $this->formatString($trans);
  211. }
  212. else {
  213. $output .= 'msgstr[' . $i . '] ""' . "\n";
  214. }
  215. }
  216. return $output;
  217. }
  218. /**
  219. * Formats a singular translation.
  220. */
  221. private function formatSingular() {
  222. $output = '';
  223. $output .= 'msgid ' . $this->formatString($this->source);
  224. $output .= 'msgstr ' . (isset($this->translation) ? $this->formatString($this->translation) : '""');
  225. return $output;
  226. }
  227. /**
  228. * Formats a string for output on multiple lines.
  229. */
  230. private function formatString($string) {
  231. // Escape characters for processing.
  232. $string = addcslashes($string, "\0..\37\\\"");
  233. // Always include a line break after the explicit \n line breaks from
  234. // the source string. Otherwise wrap at 70 chars to accommodate the extra
  235. // format overhead too.
  236. $parts = explode("\n", wordwrap(str_replace('\n', "\\n\n", $string), 70, " \n"));
  237. // Multiline string should be exported starting with a "" and newline to
  238. // have all lines aligned on the same column.
  239. if (count($parts) > 1) {
  240. return "\"\"\n\"" . implode("\"\n\"", $parts) . "\"\n";
  241. }
  242. // Single line strings are output on the same line.
  243. else {
  244. return "\"$parts[0]\"\n";
  245. }
  246. }
  247. }