PageRenderTime 27ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/wpml-translation-management/classes/xliff/class-wpml-tm-xliff-writer.php

https://bitbucket.org/oriaxx/wenco
PHP | 290 lines | 150 code | 38 blank | 102 comment | 15 complexity | b543ff5bd6e3309df8a38e87af7d1720 MD5 | raw file
Possible License(s): GPL-2.0, MIT, BSD-3-Clause, LGPL-3.0
  1. <?php
  2. /**
  3. * @package wpml-core
  4. */
  5. class WPML_TM_Xliff_Writer extends WPML_TM_Job_Factory_User {
  6. private $xliff_version;
  7. /**
  8. * WPML_TM_xliff constructor.
  9. *
  10. * @param WPML_Translation_Job_Factory $job_factory
  11. * @param string $xliff_version
  12. */
  13. public function __construct( &$job_factory, $xliff_version = TRANSLATION_PROXY_XLIFF_VERSION ) {
  14. parent::__construct( $job_factory );
  15. $this->xliff_version = $xliff_version;
  16. }
  17. /**
  18. * Generate a XLIFF file for a given job.
  19. *
  20. * @param int $job_id
  21. *
  22. * @return resource XLIFF representation of the job
  23. */
  24. public function get_job_xliff_file( $job_id ) {
  25. return $this->generate_xliff_file( $this->generate_job_xliff( $job_id ) );
  26. }
  27. /**
  28. * Generate a XLIFF string for a given post or external type (e.g. package) job.
  29. *
  30. * @param int $job_id
  31. *
  32. * @return string XLIFF representation of the job
  33. */
  34. public function generate_job_xliff( $job_id ) {
  35. /** @var TranslationManagement $iclTranslationManagement */
  36. global $iclTranslationManagement;
  37. // don't include not-translatable and don't auto-assign
  38. $job = $iclTranslationManagement->get_translation_job( (int) $job_id, false, false, 1 );
  39. $translation_units = $this->get_job_translation_units( $job );
  40. $original = $job_id . '-' . md5( $job_id . $job->original_doc_id );
  41. $external_file_url = $this->get_external_url( $job );
  42. $xliff = $this->generate_xliff( $original,
  43. $job->source_language_code,
  44. $job->language_code,
  45. $translation_units, $external_file_url );
  46. return $xliff;
  47. }
  48. /**
  49. * Generate a XLIFF file for a given set of strings.
  50. *
  51. * @param array $strings
  52. * @param string $source_language
  53. * @param string $target_language
  54. *
  55. * @return resource XLIFF file
  56. */
  57. public function get_strings_xliff_file( $strings, $source_language, $target_language ) {
  58. return $this->generate_xliff_file(
  59. $this->generate_xliff(
  60. uniqid(),
  61. $source_language,
  62. $target_language,
  63. $this->generate_strings_translation_units( $strings ) )
  64. );
  65. }
  66. private function generate_xliff( $original_id, $source_language, $target_language, $translation_units, $external_file_url = null ) {
  67. // Keep unindented to generate a pretty printed xml
  68. $xliff = "";
  69. $xliff .= '<?xml version="1.0" encoding="utf-8" standalone="no"?>';
  70. $xliff .= $this->get_xliff_opening( $this->xliff_version );
  71. $xliff .= $this->get_file_element( $original_id, $source_language, $target_language, $translation_units, $external_file_url );;
  72. $xliff .= "</xliff>" . "\n";
  73. return $xliff;
  74. }
  75. private function get_xliff_opening( $xliff_version ) {
  76. switch ( $xliff_version ) {
  77. case '10':
  78. $xliff = '<!DOCTYPE xliff PUBLIC "-//XLIFF//DTD XLIFF//EN" "http://www.oasis-open.org/committees/xliff/documents/xliff.dtd">' . PHP_EOL;
  79. $xliff .= '<xliff version="1.0">' . "\n";
  80. break;
  81. case '11':
  82. $xliff = '<xliff version="1.1" xmlns="urn:oasis:names:tc:xliff:document:1.1">' . "\n";
  83. break;
  84. case '12':
  85. default:
  86. $xliff = '<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">' . "\n";
  87. break;
  88. }
  89. return $xliff;
  90. }
  91. /**
  92. * Generate translation units for a given set of strings.
  93. *
  94. * The units are the actual content to be translated
  95. * Represented as a source and a target
  96. *
  97. * @param array $strings
  98. *
  99. * @return string The translation units representation
  100. */
  101. private function generate_strings_translation_units( $strings ) {
  102. $translation_units = '';
  103. foreach ( $strings as $string ) {
  104. $id = 'string-' . $string->id;
  105. $translation_units .= $this->get_translation_unit( $id, "string", $string->value, $string->value );
  106. }
  107. return $translation_units;
  108. }
  109. /**
  110. * Generate translation units.
  111. *
  112. * The units are the actual content to be translated
  113. * Represented as a source and a target
  114. *
  115. * @param object $job
  116. *
  117. * @return string The translation units representation
  118. */
  119. private function get_job_translation_units( $job ) {
  120. $translation_units = '';
  121. foreach ( $job->elements as $element ) {
  122. if ( $element->field_translate == '1' ) {
  123. $field_data_translated = base64_decode( $element->field_data_translated );
  124. $field_data = base64_decode( $element->field_data );
  125. if ( substr( $element->field_type, 0, 6 ) === 'field-' ) {
  126. $field_data_translated = apply_filters( 'wpml_tm_xliff_export_translated_cf', $field_data_translated, $element );
  127. $field_data = apply_filters( 'wpml_tm_xliff_export_original_cf', $field_data, $element );
  128. }
  129. // check for untranslated fields and copy the original if required.
  130. if ( ! isset( $field_data_translated ) || $field_data_translated == '' ) {
  131. $field_data_translated = $this->remove_etx_char( $field_data );
  132. }
  133. if ( $this->is_valid_unit_content( $field_data ) ) {
  134. $translation_units .= $this->get_translation_unit( $element->field_type, $element->field_type, $field_data, $field_data_translated );
  135. }
  136. }
  137. }
  138. return $translation_units;
  139. }
  140. private function get_translation_unit( $field_id, $field_name, $field_data, $field_data_translated ) {
  141. global $sitepress;
  142. $field_data = $this->remove_etx_char( $field_data );
  143. $translation_unit = "";
  144. if ( $sitepress->get_setting( 'xliff_newlines' ) == WPML_XLIFF_TM_NEWLINES_REPLACE ) {
  145. $field_data = str_replace( "\n", '<br class="xliff-newline" />', $field_data );
  146. $field_data_translated = str_replace( "\n", '<br class="xliff-newline" />', $field_data_translated );
  147. }
  148. $translation_unit .= ' <trans-unit resname="' . esc_attr( $field_name ) . '" restype="string" datatype="html" id="' . esc_attr( $field_id ) . '">' . "\n";
  149. $translation_unit .= ' <source><![CDATA[' . $field_data . ']]></source>' . "\n";
  150. $translation_unit .= ' <target><![CDATA[' . $field_data_translated . ']]></target>' . "\n";
  151. $translation_unit .= ' </trans-unit>' . "\n";
  152. return $translation_unit;
  153. }
  154. /**
  155. * @param string $string
  156. *
  157. * @return string
  158. */
  159. private function remove_etx_char( $string ) {
  160. return preg_replace('/\x03/', '', $string);
  161. }
  162. /**
  163. * Save a xliff string to a temporary file and return the file ressource
  164. * handle
  165. *
  166. * @param string $xliff_content
  167. *
  168. * @return resource XLIFF
  169. */
  170. private function generate_xliff_file( $xliff_content ) {
  171. $file = fopen( 'php://temp', 'r+' );
  172. fwrite( $file, $xliff_content );
  173. rewind( $file );
  174. return $file;
  175. }
  176. /**
  177. * @param $job
  178. *
  179. * @return false|null|string
  180. */
  181. private function get_external_url( $job ) {
  182. $external_file_url = null;
  183. if ( isset( $job->original_doc_id ) && 'post' === $job->element_type_prefix ) {
  184. $external_file_url = get_permalink( $job->original_doc_id );
  185. return $external_file_url;
  186. }
  187. return $external_file_url;
  188. }
  189. /**
  190. * The <header> element contains metadata relating to the <file> element.
  191. * @link http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#header
  192. *
  193. * @param array $args
  194. *
  195. * @return string
  196. */
  197. private function get_file_element_header( $args ) {
  198. $file_element_header = '<header />';
  199. if ( $args ) {
  200. $file_element_header = '<header>';
  201. if ( array_key_exists( 'reference', $args ) ) {
  202. $file_element_header .= $this->get_file_element_header_reference( $args['reference'] );
  203. }
  204. $file_element_header .= '</header>';
  205. }
  206. return $file_element_header;
  207. }
  208. /**
  209. * A description of the reference material and either exactly one <internal-file> or one <external-file> element.
  210. * @link http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#reference
  211. *
  212. * @param $reference
  213. *
  214. * @return string
  215. */
  216. private function get_file_element_header_reference( $reference ) {
  217. $file_element_header_reference = '<reference>';
  218. if ( array_key_exists( 'external-file', $reference ) ) {
  219. $file_element_header_reference .= '<external-file href="' . esc_attr( $reference['external-file'] ) . '"/>';
  220. } elseif ( array_key_exists( 'internal-file', $reference ) ) {
  221. $file_element_header_reference .= '<internal-file href="' . esc_attr( $reference['internal-file'] ) . '"/>';
  222. }
  223. $file_element_header_reference .= '</reference>';
  224. return $file_element_header_reference;
  225. }
  226. /**
  227. * The <file> element corresponds to a single extracted original document.
  228. * @link http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#file
  229. *
  230. * @param $original_id
  231. * @param $source_language
  232. * @param $target_language
  233. * @param $translation_units
  234. * @param $external_file_url
  235. *
  236. * @return string
  237. */
  238. private function get_file_element( $original_id, $source_language, $target_language, $translation_units, $external_file_url ) {
  239. $header_args = array(
  240. 'reference' => array(
  241. 'external-file' => $external_file_url,
  242. ),
  243. );
  244. $xliff_file = "\t" . '<file original="' . $original_id . '" source-language="' . $source_language . '" target-language="' . $target_language . '" datatype="plaintext">';
  245. $xliff_file .= "\t" . "\t" . $this->get_file_element_header( $header_args ) . "\n";
  246. $xliff_file .= "\t" . "\t" . '<body>' . "\n";
  247. $xliff_file .= "\t" . "\t" . "\t" . $translation_units . "\n";
  248. $xliff_file .= "\t" . "\t" . '</body>' . "\n";
  249. $xliff_file .= "\t" . '</file>' . "\n";
  250. return $xliff_file;
  251. }
  252. }