summaryrefslogtreecommitdiff
path: root/framework/I18N/TGlobalization.php
blob: 9a57ec3b6157eb200a32cb540494e245940b4b7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
<?php
/**
 * TGlobalization class file.
 *
 * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
 * @link https://github.com/pradosoft/prado
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
 * @license https://github.com/pradosoft/prado/blob/master/COPYRIGHT
 * @package System.I18N
 */


/**
 * TGlobalization contains settings for Culture, Charset
 * and TranslationConfiguration.
 *
 * TGlobalization can be subclassed to change how the Culture, Charset
 * are determined. See TGlobalizationAutoDetect for example of
 * setting the Culture based on browser settings.
 *
 * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
 * @version $Revision: 1.66 $  $Date: ${DATE} ${TIME} $
 * @package System.I18N
 * @since 3.0
 */
class TGlobalization extends TModule
{
	/**
	 * Default character set is 'UTF-8'.
	 * @var string
	 */
	private $_defaultCharset = 'UTF-8';

	/**
	 * Default culture is 'en'.
	 * @var string
	 */
	private $_defaultCulture = 'en';

	/**
	 * The current charset.
	 * @var string
	 */
	private $_charset=null;

	/**
	 * The current culture.
	 * @var string
	 */
	private $_culture=null;

	/**
	 * Translation source parameters.
	 * @var TMap
	 */
	private $_translation;

	/**
	 * @var boolean whether we should translate the default culture
	 */
	private $_translateDefaultCulture=true;

	/**
	 * Initialize the Culture and Charset for this application.
	 * You should override this method if you want a different way of
	 * setting the Culture and/or Charset for your application.
	 * If you override this method, call parent::init($xml) first.
	 * @param mixed application configuration
	 */
	public function init($config)
	{
		if($this->_charset===null)
			$this->_charset=$this->getDefaultCharset();
		if($this->_culture===null)
			$this->_culture=$this->getDefaultCulture();

		if($config!==null)
		{
			if($this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)
				$translation = isset($config['translate'])?$config['translate']:null;
			else
			{
				$t = $config->getElementByTagName('translation');
				$translation = ($t)?$t->getAttributes():null;
			}
			if($translation)
				$this->setTranslationConfiguration($translation);
		}
		$this->getApplication()->setGlobalization($this);
	}

	/**
	 * @return string default culture
	 */
	public function getTranslateDefaultCulture()
	{
		return $this->_translateDefaultCulture;
	}

	/**
	 * @param bool default culture, e.g. <tt>en_US</tt> for American English
	 */
	public function setTranslateDefaultCulture($value)
	{
		$this->_translateDefaultCulture = TPropertyValue::ensureBoolean($value);
	}

	/**
	 * @return string default culture
	 */
	public function getDefaultCulture()
	{
		return $this->_defaultCulture;
	}

	/**
	 * @param string default culture, e.g. <tt>en_US</tt> for American English
	 */
	public function setDefaultCulture($culture)
	{
		$this->_defaultCulture = str_replace('-','_',$culture);
	}

	/**
	 * @return string default charset set
	 */
	public function getDefaultCharset()
	{
		return $this->_defaultCharset;
	}

	/**
	 * @param string default localization charset, e.g. <tt>UTF-8</tt>
	 */
	public function setDefaultCharset($charset)
	{
		$this->_defaultCharset = $charset;
	}

	/**
	 * @return string current application culture
	 */
	public function getCulture()
	{
		return $this->_culture;
	}

	/**
	 * @param string culture, e.g. <tt>en_US</tt> for American English
	 */
	public function setCulture($culture)
	{
		$this->_culture = str_replace('-','_',$culture);
	}

	/**
	 * @return string localization charset
	 */
	public function getCharset()
	{
		return $this->_charset;
	}

	/**
	 * @param string localization charset, e.g. <tt>UTF-8</tt>
	 */
	public function setCharset($charset)
	{
		$this->_charset = $charset;
	}

	/**
	 * @return TMap translation source configuration.
	 */
	public function getTranslationConfiguration()
	{
		return (!$this->_translateDefaultCulture && ($this->getDefaultCulture() == $this->getCulture()))
			? null
			: $this->_translation;
	}

	/**
	 * Sets the translation configuration. Example configuration:
	 * <code>
	 * $config['type'] = 'XLIFF'; //XLIFF, gettext, Database or MySQL (deprecated)
	 * $config['source'] = 'Path.to.directory'; // for types XLIFF and gettext
	 * $config['source'] = 'connectionId'; // for type Database
	 * $config['source'] = 'mysql://user:pw@host/db'; // for type MySQL (deprecated)
	 * $config['catalogue'] = 'messages'; //default catalog
	 * $config['autosave'] = 'true'; //save untranslated message
	 * $config['cache'] = 'true'; //cache translated message
	 * $config['marker'] = '@@'; // surround untranslated text with '@@'
	 * </code>
	 * Throws exception is source is not found.
	 * @param TMap|array configuration options
	 */
	protected function setTranslationConfiguration($config)
	{
		if($config['type'] == 'XLIFF' || $config['type'] == 'gettext')
		{
			if($config['source'])
			{
				$config['source'] = Prado::getPathOfNamespace($config['source']);
				if(!is_dir($config['source']))
				{
					if(@mkdir($config['source'])===false)
					throw new TConfigurationException('globalization_source_path_failed',
						$config['source']);
					chmod($config['source'], PRADO_CHMOD); //make it deletable
				}
			}
			else
			{
				throw new TConfigurationException("invalid source dir '{$config['source']}'");
			}
		}
		if(isset($config['cache']) && TPropertyValue::ensureBoolean($config['cache']))
		{
			$config['cache'] = $this->getApplication()->getRunTimePath().'/i18n';
			if(!is_dir($config['cache']))
			{
				if(@mkdir($config['cache'])===false)
					throw new TConfigurationException('globalization_cache_path_failed',
						$config['cache']);
				chmod($config['cache'], PRADO_CHMOD); //make it deletable
			}
		}
		else
		{
			unset($config['cache']);
		}
		$this->_translation = $config;
	}

	/**
	 * @return string current translation catalogue.
	 */
	public function getTranslationCatalogue()
	{
		return $this->_translation['catalogue'];
	}

	/**
	 * @param string update the translation catalogue.
	 */
	public function setTranslationCatalogue($value)
	{
		$this->_translation['catalogue'] = $value;
	}

	/**
	 * Gets all the variants of a specific culture. If the parameter
	 * $culture is null, the current culture is used.
	 * @param string $culture the Culture string
	 * @return array variants of the culture.
	 */
	public function getCultureVariants($culture=null)
	{
		if($culture===null) $culture = $this->getCulture();
		$variants = explode('_', $culture);
		$result = array();
		for(; count($variants) > 0; array_pop($variants))
			$result[] = implode('_', $variants);
		return $result;
	}

	/**
	 * Returns a list of possible localized files. Example
	 * <code>
	 * $files = $app->getLocalizedResource("path/to/Home.page","en_US");
	 * </code>
	 * will return
	 * <pre>
	 * array
	 *   0 => 'path/to/en_US/Home.page'
	 *   1 => 'path/to/en/Home.page'
	 *   2 => 'path/to/Home.en_US.page'
	 *   3 => 'path/to/Home.en.page'
	 *   4 => 'path/to/Home.page'
	 * </pre>
	 * Note that you still need to verify the existance of these files.
	 * @param string filename
	 * @param string culture string, null to use current culture
	 * @return array list of possible localized resource files.
	 */
	public function getLocalizedResource($file,$culture=null)
	{
		$files = array();
		$variants = $this->getCultureVariants($culture);
		$path = pathinfo($file);
		foreach($variants as $variant)
			$files[] = $path['dirname'].DIRECTORY_SEPARATOR.$variant.DIRECTORY_SEPARATOR.$path['basename'];
		$filename = substr($path['basename'],0,strrpos($path['basename'],'.'));
		foreach($variants as $variant)
			$files[] = $path['dirname'].DIRECTORY_SEPARATOR.$filename.'.'.$variant.'.'.$path['extension'];
		$files[] = $file;
		return $files;
	}

}