1: <?php
2: /**
3: * @author Jefferson González
4: * @license MIT
5: * @link http://github.com/peg-org/peg-custom Source code.
6: */
7:
8: namespace Peg\Custom\Localization;
9:
10: /**
11: * Defines the language class used for translating system strings by using
12: * po files for different languages.
13: */
14: class Language
15: {
16:
17: /**
18: * One of the language codes from \Peg\Custom\Localization\LanguageCode
19: * @var string
20: */
21: private $language;
22:
23: /**
24: * Directory that holds po files for each language.
25: * @var string
26: */
27: private $directory;
28:
29: /**
30: * Stores the translation strings parsed from po files.
31: * @var array
32: */
33: private $translations;
34:
35: /**
36: * Initialize the language class for translating strings.
37: * @param string $directory Path to directory that holds po files.
38: * @param string $language The language code from \Peg\Custom\Localization\LanguageCode
39: * @throws \Exception If language directory doesn't exists.
40: */
41: public function __construct($directory, $language = null)
42: {
43: if(!file_exists($directory))
44: throw new \Exception("Languages directory not found.");
45:
46: $this->translations = null;
47:
48: $this->directory = $directory;
49:
50: $this->SetLanguage($language);
51: }
52:
53: /**
54: * Current language used for translation output.
55: * @return string One of the values from \Peg\Custom\Localization\LanguageCode
56: */
57: public function GetLanguage()
58: {
59: return $this->language;
60: }
61:
62: /**
63: * Gets the current system language.
64: * @todo Implement also for microsoft windows.
65: * @return string One of the values from \Peg\Custom\Localization\LanguageCode
66: */
67: public function GetSystemLangauge()
68: {
69: $language_parts = explode(":", $_SERVER["LANGUAGE"]);
70:
71: return $language_parts[0];
72: }
73:
74: /**
75: * Assings the language for translation output. If no language is given
76: * the system one is assigned.
77: * @param string $language One of the values from \Peg\Custom\Localization\LanguageCode
78: */
79: public function SetLanguage($language = null)
80: {
81: $this->translations = null;
82:
83: if(!$language)
84: {
85: $this->language = $this->GetSystemLangauge();
86: }
87: else
88: {
89: $this->language = $language;
90: }
91:
92: // If language files does not exists and a sublanguage was used
93: // like en_US then use 'en' to see if it is available.
94: if(!file_exists($this->directory . "/" . $this->language))
95: {
96: $language_parts = explode("_", $this->language);
97:
98: if(count($language_parts) > 1)
99: {
100: $this->language = $language_parts[0];
101: }
102: }
103: }
104:
105: /**
106: * Translates a given text to the currently language set.
107: * @param string $text String to translate.
108: * @return string Translated text or original if no translation found.
109: */
110: public function Translate($text)
111: {
112: $text = trim($text);
113:
114: $translation = $text;
115:
116: if(!$this->translations)
117: {
118: $this->translations = $this->PoParser($this->directory . "/" . $this->language . ".po");
119: }
120:
121: if($text != "")
122: {
123: if(isset($this->translations[$text]))
124: {
125: $available_translation = $this->translations[$text];
126:
127: if($available_translation != "")
128: {
129: $translation = $available_translation;
130: }
131: }
132: }
133:
134: return $translation;
135: }
136:
137: /**
138: * Parses a .po file generated by gettext tools.
139: * @param string $file The path of the po translations file.
140: * @return array In the format array["original text"] = "translation"
141: */
142: public function PoParser($file)
143: {
144: if(!file_exists($file))
145: {
146: return false;
147: }
148:
149: $file_rows = file($file);
150:
151: $original_string = "";
152: $translations = array();
153:
154: $found_original = false;
155:
156: foreach($file_rows as $row_position=>$row)
157: {
158: if(!$found_original)
159: {
160: if(substr(trim($row), 0, 6) == "msgid ")
161: {
162: $found_original = true;
163: $string = str_replace("msgid ", "", trim($row));
164: $pattern = "/(\")(.*)(\")/";
165: $replace = "\$2";
166:
167: if($string != '""')
168: {
169: $string = preg_replace($pattern, $replace, $string);
170:
171: $string = str_replace(
172: array("\\t", "\\n", "\\r", "\\0", "\\v", "\\f", "\\\\", "\\\""),
173: array("\t", "\n", "\r", "\0", "\v", "\f", "\\", "\""),
174: $string
175: );
176:
177: $original_string = $string;
178: }
179: else
180: {
181: $original_string = "";
182:
183: $row_position++;
184: $string = trim($file_rows[$row_position]);
185:
186: while($string{0} == '"')
187: {
188: $original_string .= preg_replace(
189: $pattern,
190: $replace,
191: $string
192: );
193:
194: $row_position++;
195: $string = trim($file_rows[$row_position]);
196: }
197:
198: $original_string = str_replace(
199: array("\\t", "\\n", "\\r", "\\0", "\\v", "\\f", "\\\\", "\\\""),
200: array("\t", "\n", "\r", "\0", "\v", "\f", "\\", "\""),
201: $original_string
202: );
203: }
204: }
205: }
206: else
207: {
208: if(substr(trim($row), 0, 7) == "msgstr ")
209: {
210: $found_original = false;
211: $string = str_replace("msgstr ", "", trim($row));
212:
213: $pattern = "/(\")(.*)(\")/";
214: $replace = "\$2";
215:
216: if($string != '""')
217: {
218: $string = preg_replace($pattern, $replace, $string);
219:
220: $string = str_replace(
221: array("\\t", "\\n", "\\r", "\\0", "\\v", "\\f", "\\\\", "\\\""),
222: array("\t", "\n", "\r", "\0", "\v", "\f", "\\", "\""),
223: $string
224: );
225:
226: $translations[$original_string] = $string;
227: }
228: else
229: {
230: $translation_string = "";
231:
232: $row_position++;
233: $string = trim($file_rows[$row_position]);
234:
235: while($string{0} == '"')
236: {
237: $translation_string .= preg_replace(
238: $pattern,
239: $replace,
240: $string
241: );
242:
243: $row_position++;
244: $string = trim($file_rows[$row_position]);
245: }
246:
247: $translation_string = str_replace(
248: array("\\t", "\\n", "\\r", "\\0", "\\v", "\\f", "\\\\", "\\\""),
249: array("\t", "\n", "\r", "\0", "\v", "\f", "\\", "\""),
250: $translation_string
251: );
252:
253: $translations[$original_string] = $translation_string;
254: }
255: }
256: }
257: }
258:
259: unset($file_rows);
260:
261: return $translations;
262: }
263:
264: }