1<?php 2 3namespace Gettext\Generators; 4 5use Gettext\Translations; 6 7class Po extends Generator implements GeneratorInterface 8{ 9 public static $options = [ 10 'noLocation' => false, 11 ]; 12 13 /** 14 * {@parentDoc}. 15 */ 16 public static function toString(Translations $translations, array $options = []) 17 { 18 $options += static::$options; 19 20 $pluralForm = $translations->getPluralForms(); 21 $pluralSize = is_array($pluralForm) ? ($pluralForm[0] - 1) : null; 22 $lines = ['msgid ""', 'msgstr ""']; 23 24 foreach ($translations->getHeaders() as $name => $value) { 25 $lines[] = sprintf('"%s: %s\\n"', $name, $value); 26 } 27 28 $lines[] = ''; 29 30 //Translations 31 foreach ($translations as $translation) { 32 if ($translation->hasComments()) { 33 foreach ($translation->getComments() as $comment) { 34 $lines[] = '# '.$comment; 35 } 36 } 37 38 if ($translation->hasExtractedComments()) { 39 foreach ($translation->getExtractedComments() as $comment) { 40 $lines[] = '#. '.$comment; 41 } 42 } 43 44 if (!$options['noLocation'] && $translation->hasReferences()) { 45 foreach ($translation->getReferences() as $reference) { 46 $lines[] = '#: '.$reference[0].(!is_null($reference[1]) ? ':'.$reference[1] : null); 47 } 48 } 49 50 if ($translation->hasFlags()) { 51 $lines[] = '#, '.implode(',', $translation->getFlags()); 52 } 53 54 $prefix = $translation->isDisabled() ? '#~ ' : ''; 55 56 if ($translation->hasContext()) { 57 $lines[] = $prefix.'msgctxt '.static::convertString($translation->getContext()); 58 } 59 60 static::addLines($lines, $prefix.'msgid', $translation->getOriginal()); 61 62 if ($translation->hasPlural()) { 63 static::addLines($lines, $prefix.'msgid_plural', $translation->getPlural()); 64 static::addLines($lines, $prefix.'msgstr[0]', $translation->getTranslation()); 65 66 foreach ($translation->getPluralTranslations($pluralSize) as $k => $v) { 67 static::addLines($lines, $prefix.'msgstr['.($k + 1).']', $v); 68 } 69 } else { 70 static::addLines($lines, $prefix.'msgstr', $translation->getTranslation()); 71 } 72 73 $lines[] = ''; 74 } 75 76 return implode("\n", $lines); 77 } 78 79 /** 80 * Escapes and adds double quotes to a string. 81 * 82 * @param string $string 83 * 84 * @return string 85 */ 86 protected static function multilineQuote($string) 87 { 88 $lines = explode("\n", $string); 89 $last = count($lines) - 1; 90 91 foreach ($lines as $k => $line) { 92 if ($k === $last) { 93 $lines[$k] = static::convertString($line); 94 } else { 95 $lines[$k] = static::convertString($line."\n"); 96 } 97 } 98 99 return $lines; 100 } 101 102 /** 103 * Add one or more lines depending whether the string is multiline or not. 104 * 105 * @param array &$lines 106 * @param string $name 107 * @param string $value 108 */ 109 protected static function addLines(array &$lines, $name, $value) 110 { 111 $newLines = static::multilineQuote($value); 112 113 if (count($newLines) === 1) { 114 $lines[] = $name.' '.$newLines[0]; 115 } else { 116 $lines[] = $name.' ""'; 117 118 foreach ($newLines as $line) { 119 $lines[] = $line; 120 } 121 } 122 } 123 124 /** 125 * Convert a string to its PO representation. 126 * 127 * @param string $value 128 * 129 * @return string 130 */ 131 public static function convertString($value) 132 { 133 return '"'.strtr( 134 $value, 135 [ 136 "\x00" => '', 137 '\\' => '\\\\', 138 "\t" => '\t', 139 "\r" => '\r', 140 "\n" => '\n', 141 '"' => '\\"', 142 ] 143 ).'"'; 144 } 145} 146