3 require_once 'HTMLPurifier/Language.php';
4 require_once 'HTMLPurifier/AttrDef/Lang.php';
6 HTMLPurifier_ConfigSchema
::define(
7 'Core', 'Language', 'en', 'string', '
8 ISO 639 language code for localizable things in HTML Purifier to use,
9 which is mainly error reporting. There is currently only an English (en)
10 translation, so this directive is currently useless.
11 This directive has been available since 2.0.0.
15 * Class responsible for generating HTMLPurifier_Language objects, managing
16 * caching and fallbacks.
17 * @note Thanks to MediaWiki for the general logic, although this version
18 * has been entirely rewritten
19 * @todo Serialized cache for languages
21 class HTMLPurifier_LanguageFactory
25 * Cache of language code information used to load HTMLPurifier_Language objects
26 * Structure is: $factory->cache[$language_code][$key] = $value
32 * Valid keys in the HTMLPurifier_Language object. Designates which
33 * variables to slurp out of a message file.
36 var $keys = array('fallback', 'messages', 'errorNames');
39 * Instance of HTMLPurifier_AttrDef_Lang to validate language codes
40 * @value object HTMLPurifier_AttrDef_Lang
45 * Cached copy of dirname(__FILE__), directory of current file without
47 * @value string filename
52 * Keys whose contents are a hash map and can be merged
55 var $mergeable_keys_map = array('messages' => true, 'errorNames' => true);
58 * Keys whose contents are a list and can be merged
61 var $mergeable_keys_list = array();
64 * Retrieve sole instance of the factory.
66 * @param $prototype Optional prototype to overload sole instance with,
67 * or bool true to reset to default factory.
69 function &instance($prototype = null) {
70 static $instance = null;
71 if ($prototype !== null) {
72 $instance = $prototype;
73 } elseif ($instance === null ||
$prototype == true) {
74 $instance = new HTMLPurifier_LanguageFactory();
81 * Sets up the singleton, much like a constructor
82 * @note Prevents people from getting this outside of the singleton
85 $this->validator
= new HTMLPurifier_AttrDef_Lang();
86 $this->dir
= HTMLPURIFIER_PREFIX
. '/HTMLPurifier';
90 * Creates a language object, handles class fallbacks
91 * @param $config Instance of HTMLPurifier_Config
92 * @param $context Instance of HTMLPurifier_Context
93 * @param $code Code to override configuration with. Private parameter.
95 function create($config, &$context, $code = false) {
97 // validate language code
98 if ($code === false) {
99 $code = $this->validator
->validate(
100 $config->get('Core', 'Language'), $config, $context
103 $code = $this->validator
->validate($code, $config, $context);
105 if ($code === false) $code = 'en'; // malformed code becomes English
107 $pcode = str_replace('-', '_', $code); // make valid PHP classname
108 static $depth = 0; // recursion protection
111 $lang = new HTMLPurifier_Language($config, $context);
113 $class = 'HTMLPurifier_Language_' . $pcode;
114 $file = $this->dir
. '/Language/classes/' . $code . '.php';
115 if (file_exists($file)) {
117 $lang = new $class($config, $context);
120 $raw_fallback = $this->getFallbackFor($code);
121 $fallback = $raw_fallback ?
$raw_fallback : 'en';
123 $lang = $this->create($config, $context, $fallback);
124 if (!$raw_fallback) {
137 * Returns the fallback language for language
138 * @note Loads the original language into cache
139 * @param $code string language code
141 function getFallbackFor($code) {
142 $this->loadLanguage($code);
143 return $this->cache
[$code]['fallback'];
147 * Loads language into the cache, handles message file and fallbacks
148 * @param $code string language code
150 function loadLanguage($code) {
151 static $languages_seen = array(); // recursion guard
153 // abort if we've already loaded it
154 if (isset($this->cache
[$code])) return;
157 $filename = $this->dir
. '/Language/messages/' . $code . '.php';
159 // default fallback : may be overwritten by the ensuing include
160 $fallback = ($code != 'en') ?
'en' : false;
162 // load primary localisation
163 if (!file_exists($filename)) {
164 // skip the include: will rely solely on fallback
165 $filename = $this->dir
. '/Language/messages/en.php';
169 $cache = compact($this->keys
);
172 // load fallback localisation
173 if (!empty($fallback)) {
175 // infinite recursion guard
176 if (isset($languages_seen[$code])) {
177 trigger_error('Circular fallback reference in language ' .
178 $code, E_USER_ERROR
);
181 $language_seen[$code] = true;
183 // load the fallback recursively
184 $this->loadLanguage($fallback);
185 $fallback_cache = $this->cache
[$fallback];
187 // merge fallback with current language
188 foreach ( $this->keys
as $key ) {
189 if (isset($cache[$key]) && isset($fallback_cache[$key])) {
190 if (isset($this->mergeable_keys_map
[$key])) {
191 $cache[$key] = $cache[$key] +
$fallback_cache[$key];
192 } elseif (isset($this->mergeable_keys_list
[$key])) {
193 $cache[$key] = array_merge( $fallback_cache[$key], $cache[$key] );
196 $cache[$key] = $fallback_cache[$key];
202 // save to cache for later retrieval
203 $this->cache
[$code] = $cache;