PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/sgl/includes/qcubed/_core/framework/QTranslationPoParser.class.php

http://logisticsouth.googlecode.com/
PHP | 297 lines | 250 code | 43 blank | 4 comment | 66 complexity | 81f2584c47a7a181c35dc2fe7996a1b8 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0
  1. <?php
  2. class QPoParserException extends QCallerException {}
  3. class QTranslationPoParser implements QTranslationBase {
  4. public static function Initialize() {
  5. return self::Load(QApplication::$LanguageCode, QApplication::$CountryCode);
  6. }
  7. public static function Load($strLanguageCode = null, $strCountryCode = null) {
  8. $objLanguageObject = null;
  9. if ($strLanguageCode) {
  10. if ($strCountryCode) {
  11. $strCode = sprintf('%s_%s', $strLanguageCode, $strCountryCode);
  12. $strLanguageFiles = array(
  13. __QCUBED_CORE__ . '/i18n/' . $strLanguageCode . '.po',
  14. __QCUBED_CORE__ . '/i18n/' . $strCode . '.po',
  15. __QI18N_PO_PATH__ . '/' . $strLanguageCode . '.po',
  16. __QI18N_PO_PATH__ . '/' . $strCode . '.po'
  17. );
  18. } else {
  19. $strCode = $strLanguageCode;
  20. $strLanguageFiles = array(
  21. __QCUBED_CORE__ . '/i18n/' . $strLanguageCode . '.po',
  22. __QI18N_PO_PATH__ . '/' . $strLanguageCode . '.po'
  23. );
  24. }
  25. // Setup the LanguageFileObject cache mechanism
  26. $objCache = new QCache('i18n.po', $strCode, 'i18n', $strLanguageFiles);
  27. // If cached data exists and is valid, use it
  28. $strData = $objCache->GetData();
  29. if ($strData) {
  30. $objLanguageObject = unserialize($strData);
  31. // Otherwise, reload all langauge files and update the cache
  32. } else {
  33. $objLanguage = new QTranslationPoParser();
  34. foreach ($strLanguageFiles as $strLanguageFile) {
  35. if (file_exists($strLanguageFile)) {
  36. try {
  37. //print($strLanguageFile.'<BR>');
  38. $objLanguage->ParsePoData(file_get_contents($strLanguageFile));
  39. } catch (QPoParserException $objExc) {
  40. $objExc->setMessage('Invalid Language File: ' . $strLanguageFile . ': ' . $objExc->getMessage());
  41. $objExc->IncrementOffset();
  42. throw $objExc;
  43. }
  44. }
  45. }
  46. $objLanguageObject = $objLanguage;
  47. $objCache->SaveData(serialize($objLanguage));
  48. }
  49. }
  50. return $objLanguageObject;
  51. }
  52. const PoParseStateNone = 0;
  53. const PoParseStateMessageIdStart = 1;
  54. const PoParseStateMessageId = 2;
  55. const PoParseStateMessageStringStart = 3;
  56. const PoParseStateMessageString = 4;
  57. protected static function UnescapeContent($strContent) {
  58. $intLength = strlen($strContent);
  59. $strToReturn = '';
  60. $blnEscape = false;
  61. for ($intIndex = 0; $intIndex < $intLength; $intIndex++) {
  62. if ($blnEscape) {
  63. switch ($strContent[$intIndex]) {
  64. case 'n':
  65. $blnEscape = false;
  66. $strToReturn .= "\n";
  67. break;
  68. case 'r':
  69. $blnEscape = false;
  70. $strToReturn .= "\r";
  71. break;
  72. case 't':
  73. $blnEscape = false;
  74. $strToReturn .= " ";
  75. break;
  76. case '\\':
  77. $blnEscape = false;
  78. $strToReturn .= '\\';
  79. break;
  80. case '"':
  81. $blnEscape = false;
  82. $strToReturn .= '"';
  83. break;
  84. case "'":
  85. $blnEscape = false;
  86. $strToReturn .= "'";
  87. break;
  88. default:
  89. $blnEscape = false;
  90. $strToReturn .= '\\' . $strContent[$intIndex];
  91. break;
  92. }
  93. } else {
  94. if ($strContent[$intIndex] == '\\')
  95. $blnEscape = true;
  96. else
  97. $strToReturn .= $strContent[$intIndex];
  98. }
  99. }
  100. if ($blnEscape)
  101. return false;
  102. $strToReturn = str_replace("\r", '', $strToReturn);
  103. return $strToReturn;
  104. }
  105. protected function ParsePoData($strPoData) {
  106. $strPoData = str_replace("\r", '', trim($strPoData));
  107. $strPoLines = explode("\n", $strPoData);
  108. $strMatches = array();
  109. $intState = QTranslationPoParser::PoParseStateNone;
  110. $intLineCount = count($strPoLines);
  111. if (strlen($strPoLines[0]) == 0)
  112. return;
  113. for ($intLineNumber = 0; $intLineNumber < $intLineCount; $intLineNumber++) {
  114. $strPoLine = $strPoLines[$intLineNumber] = trim($strPoLines[$intLineNumber]);
  115. if (strlen($strPoLine) && (QString::FirstCharacter($strPoLine) != '#')) {
  116. switch ($intState) {
  117. case QTranslationPoParser::PoParseStateNone:
  118. $intCount = preg_match_all('/msgid(_[a-z0-9]+)?[\s]+"([\S ]*)"/i', $strPoLine, $strMatches);
  119. if ($intCount && ($strMatches[0][0] == $strPoLine)) {
  120. $intLineNumber--;
  121. $intState = QTranslationPoParser::PoParseStateMessageIdStart;
  122. } else
  123. throw new QPoParserException('Invalid content for PoParseStateNone on Line ' . ($intLineNumber + 1) . ': ' . $strPoLine);
  124. break;
  125. case QTranslationPoParser::PoParseStateMessageIdStart:
  126. $intCount = preg_match_all('/msgid(_[a-z0-9]+)?[\s]+"([\S ]*)"/i', $strPoLine, $strMatches);
  127. if ($intCount && ($strMatches[0][0] == $strPoLine)) {
  128. $strMessageId = array('', '', '', '', '', '', '');
  129. $strMessageString = array('', '', '', '', '', '', '');
  130. $intArrayIndex = 0;
  131. $strContent = QTranslationPoParser::UnescapeContent($strMatches[2][0]);
  132. if ($strContent === false)
  133. throw new QPoParserException('Invalid content on Line ' . ($intLineNumber + 1));
  134. $strMessageId[$intArrayIndex] = $strContent;
  135. $intState = QTranslationPoParser::PoParseStateMessageId;
  136. } else
  137. throw new QPoParserException('Invalid content for PoParseStateMessageIdStart on Line ' . ($intLineNumber + 1) . ': ' . $strPoLine);
  138. break;
  139. case QTranslationPoParser::PoParseStateMessageId:
  140. $intCount = preg_match_all('/msgid(_[a-z0-9]+)[\s]+"([\S ]*)"/i', $strPoLine, $strMatches);
  141. if ($intCount && ($strMatches[0][0] == $strPoLine)) {
  142. if (strlen(trim($strMessageId[$intArrayIndex])) == 0)
  143. throw new QPoParserException('No MsgId content for current MsgId on Line ' . ($intLineNumber) . ': ' . $strPoLine);
  144. $intArrayIndex++;
  145. $strContent = QTranslationPoParser::UnescapeContent($strMatches[2][0]);
  146. if ($strContent === false)
  147. throw new QPoParserException('Invalid content on Line ' . ($intLineNumber + 1));
  148. $strMessageId[$intArrayIndex] = $strContent;
  149. break;
  150. }
  151. $intCount = preg_match_all('/"([\S ]*)"/', $strPoLine, $strMatches);
  152. if ($intCount && ($strMatches[0][0] == $strPoLine)) {
  153. $strContent = QTranslationPoParser::UnescapeContent($strMatches[1][0]);
  154. if ($strContent === false)
  155. throw new QPoParserException('Invalid content on Line ' . ($intLineNumber + 1));
  156. $strMessageId[$intArrayIndex] .= $strContent;
  157. break;
  158. }
  159. $intCount = preg_match_all('/msgstr(\[[0-9]+\])?[\s]+"([\S ]*)"/i', $strPoLine, $strMatches);
  160. if ($intCount && ($strMatches[0][0] == $strPoLine)) {
  161. if (strlen(trim($strMessageId[$intArrayIndex])) == 0)
  162. throw new QPoParserException('No MsgId content for current MsgId on Line ' . ($intLineNumber) . ': ' . $strPoLine);
  163. $intLineNumber--;
  164. $intState = QTranslationPoParser::PoParseStateMessageStringStart;
  165. break;
  166. }
  167. throw new QPoParserException('Invalid content for PoParseStateMessageId on Line ' . ($intLineNumber + 1) . ': ' . $strPoLine);
  168. case QTranslationPoParser::PoParseStateMessageStringStart:
  169. $intCount = preg_match_all('/msgstr(\[[0-9]+\])?[\s]+"([\S ]*)"/i', $strPoLine, $strMatches);
  170. if ($intCount && ($strMatches[0][0] == $strPoLine)) {
  171. $intArrayIndex = 0;
  172. if (strlen($strMatches[1][0]))
  173. $intArrayIndex = intval(substr($strMatches[1][0], 1, strlen($strMatches[1][0]) - 2));
  174. $strContent = QTranslationPoParser::UnescapeContent($strMatches[2][0]);
  175. if ($strContent === false)
  176. throw new QPoParserException('Invalid content on Line ' . ($intLineNumber + 1));
  177. $strMessageString[$intArrayIndex] = $strContent;
  178. $intState = QTranslationPoParser::PoParseStateMessageString;
  179. } else
  180. throw new QPoParserException('Invalid content for PoParseStateMessageStringStart on Line ' . ($intLineNumber + 1) . ': ' . $strPoLine);
  181. break;
  182. case QTranslationPoParser::PoParseStateMessageString:
  183. $intCount = preg_match_all('/msgid(_[a-z0-9]+)?[\s]+"([\S ]*)"/i', $strPoLine, $strMatches);
  184. if ($intCount && ($strMatches[0][0] == $strPoLine)) {
  185. for ($intIndex = 0; $intIndex < count($strMessageId); $intIndex++)
  186. if (strlen(trim($strMessageId[$intIndex]))) {
  187. if (!strlen(trim($strMessageString[$intIndex]))) {
  188. $this->SetTranslation($strMessageId[$intIndex], "");
  189. }
  190. $this->SetTranslation($strMessageId[$intIndex], $strMessageString[$intIndex]);
  191. }
  192. $intLineNumber--;
  193. $intState = QTranslationPoParser::PoParseStateMessageIdStart;
  194. break;
  195. }
  196. $intCount = preg_match_all('/"([\S ]*)"/', $strPoLine, $strMatches);
  197. if ($intCount && ($strMatches[0][0] == $strPoLine)) {
  198. $strContent = QTranslationPoParser::UnescapeContent($strMatches[1][0]);
  199. if ($strContent === false)
  200. throw new QPoParserException('Invalid content on Line ' . ($intLineNumber + 1));
  201. $strMessageString[$intArrayIndex] .= $strContent;
  202. break;
  203. }
  204. $intCount = preg_match_all('/msgstr(\[[0-9]+\])?[\s]+"([\S ]*)"/i', $strPoLine, $strMatches);
  205. if ($intCount && ($strMatches[0][0] == $strPoLine)) {
  206. if (strlen($strMatches[1][0]))
  207. $intArrayIndex = intval(substr($strMatches[1][0], 1, strlen($strMatches[1][0]) - 2));
  208. else
  209. throw new QPoParserException('No index specified for alternate MsgStr for PoParseStateMessageString on Line ' . ($intLineNumber + 1) . ': ' . $strPoLine);
  210. if (strlen(trim($strMessageId[$intArrayIndex])) == 0)
  211. throw new QPoParserException('No MsgId for MsgStr' . $strMatches[1][0] . ' for PoParseStateMessageString on Line ' . ($intLineNumber + 1) . ': ' . $strPoLine);
  212. $strContent = QTranslationPoParser::UnescapeContent($strMatches[2][0]);
  213. if ($strContent === false)
  214. throw new QPoParserException('Invalid content on Line ' . ($intLineNumber + 1));
  215. $strMessageString[$intArrayIndex] = $strContent;
  216. break;
  217. }
  218. throw new QPoParserException('Invalid content for PoParseStateMessageString on Line ' . ($intLineNumber + 1) . ': ' . $strPoLine);
  219. default:
  220. throw new QPoParserException('Invalid PoParseState on Line ' . ($intLineNumber + 1) . ': ' . $strPoLine);
  221. }
  222. }
  223. }
  224. for ($intIndex = 0; $intIndex < count($strMessageId); $intIndex++) {
  225. if (strlen(trim($strMessageId[$intIndex]))) {
  226. if (!strlen(trim($strMessageString[$intIndex]))) {
  227. $this->SetTranslation($strMessageId[$intIndex], "");
  228. }
  229. $this->SetTranslation($strMessageId[$intIndex], $strMessageString[$intIndex]);
  230. }
  231. }
  232. }
  233. protected $strTranslationArray = array();
  234. protected function SetTranslation($strToken, $strTranslatedText) {
  235. $this->strTranslationArray[$strToken] = $strTranslatedText;
  236. }
  237. public function TranslateToken($strToken) {
  238. $strCleanToken = str_replace("\r", '', $strToken);
  239. if (array_key_exists($strCleanToken, $this->strTranslationArray)) {
  240. return $this->strTranslationArray[$strCleanToken];
  241. } else {
  242. return $strToken;
  243. }
  244. }
  245. public function VarDump() {
  246. $strToReturn = '';
  247. foreach ($this->strTranslationArray as $strKey=>$strValue) {
  248. $strKey = str_replace("\n", '\\n', addslashes(QApplication::HtmlEntities($strKey)));
  249. $strValue = str_replace("\n", '\\n', addslashes(QApplication::HtmlEntities($strValue)));
  250. $strToReturn .= sprintf("\"%s\"\n\"%s\"\n\n", $strKey, $strValue);
  251. }
  252. return $strToReturn;
  253. }
  254. }