Gettext.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <?php
  2. /**
  3. *
  4. * Ported from Zend Framework
  5. *
  6. * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Cube\Translate\Adapter;
  10. use Cube\Config\AbstractConfig,
  11. Cube\Locale;
  12. /**
  13. * gettext translate adapter
  14. *
  15. * Class Gettext
  16. *
  17. * @package Cube\Translate\Adapter
  18. */
  19. class Gettext extends AbstractAdapter
  20. {
  21. // Internal variables
  22. private $_bigEndian = false;
  23. private $_file = false;
  24. /**
  25. * Read values from the MO file
  26. *
  27. * @param string $bytes
  28. *
  29. * @return array
  30. */
  31. private function _readMOData($bytes)
  32. {
  33. if ($this->_bigEndian === false) {
  34. return unpack('V' . $bytes, fread($this->_file, 4 * $bytes));
  35. }
  36. else {
  37. return unpack('N' . $bytes, fread($this->_file, 4 * $bytes));
  38. }
  39. }
  40. /**
  41. *
  42. * add new translation in the adapter
  43. *
  44. * @param array $options
  45. *
  46. * @throws \RuntimeException
  47. * @throws \InvalidArgumentException
  48. * @return $this
  49. */
  50. public function addTranslation($options = array())
  51. {
  52. if (!is_array($options) && !($options instanceof AbstractConfig)) {
  53. throw new \InvalidArgumentException("The translation object requires an
  54. array or an object of type \Cube\ConfigAbstract.");
  55. }
  56. else {
  57. if ($options instanceof AbstractConfig) {
  58. $options = $options->getData();
  59. }
  60. $file = (isset($options['file'])) ? $options['file'] : null;
  61. $locale = (isset($options['locale'])) ? $options['locale'] : null;
  62. $this->_file = @fopen($file, 'rb');
  63. if (!$this->_file) {
  64. throw new \RuntimeException(
  65. sprintf("Error opening translation file '%s'.", $file));
  66. }
  67. if (@filesize($file) < 10) {
  68. @fclose($this->_file);
  69. throw new \RuntimeException(
  70. sprintf("%s is not a gettext file.", $file));
  71. }
  72. if (Locale::isLocale($locale) === false) {
  73. throw new \InvalidArgumentException(
  74. sprintf("Add translation method error: '%s' is an invalid locale.", $locale));
  75. }
  76. $this->_file = fopen($file, 'rb');
  77. // get Endian
  78. $input = $this->_readMOData(1);
  79. if (strtolower(substr(dechex($input[1]), -8)) == "950412de") {
  80. $this->_bigEndian = false;
  81. }
  82. else if (strtolower(substr(dechex($input[1]), -8)) == "de120495") {
  83. $this->_bigEndian = true;
  84. }
  85. else {
  86. @fclose($this->_file);
  87. throw new \RuntimeException(
  88. sprintf("%s is not a gettext file.", $file));
  89. }
  90. // read revision - not supported for now
  91. $input = $this->_readMOData(1);
  92. // number of bytes
  93. $input = $this->_readMOData(1);
  94. $total = $input[1];
  95. // number of original strings
  96. $input = $this->_readMOData(1);
  97. $OOffset = $input[1];
  98. // number of translation strings
  99. $input = $this->_readMOData(1);
  100. $TOffset = $input[1];
  101. // fill the original table
  102. fseek($this->_file, $OOffset);
  103. $origtemp = $this->_readMOData(2 * $total);
  104. fseek($this->_file, $TOffset);
  105. $transtemp = $this->_readMOData(2 * $total);
  106. for ($count = 0; $count < $total; ++$count) {
  107. if ($origtemp[$count * 2 + 1] != 0) {
  108. fseek($this->_file, $origtemp[$count * 2 + 2]);
  109. $original = @fread($this->_file, $origtemp[$count * 2 + 1]);
  110. $original = explode("\0", $original);
  111. }
  112. else {
  113. $original[0] = '';
  114. }
  115. if ($transtemp[$count * 2 + 1] != 0) {
  116. fseek($this->_file, $transtemp[$count * 2 + 2]);
  117. $translate = fread($this->_file, $transtemp[$count * 2 + 1]);
  118. $translate = explode("\0", $translate);
  119. if ((count($original) > 1)) {
  120. $this->_translate[$locale][$original[0]] = $translate;
  121. array_shift($original);
  122. foreach ($original as $orig) {
  123. $this->_translate[$locale][$orig] = '';
  124. }
  125. }
  126. else {
  127. $this->_translate[$locale][$original[0]] = $translate[0];
  128. }
  129. }
  130. }
  131. @fclose($this->_file);
  132. }
  133. return $this;
  134. }
  135. }