source: branches/version-2_12-multilang/data/class/helper/SC_Helper_Locale.php @ 22226

Revision 22226, 10.1 KB checked in by Seasoft, 11 years ago (diff)

#1988 (国際化テンプレート:エスケープ処理) 現状コミット。

  • PHP 関数の t() の動作に影響が及んでいたので回避。
  • 文字列エスケープ処理を分離。SC_Helper_Locale#escape
  • デフォルトのエスケープに nl2br を追加。
  • 吉本様からご指示いただきました仕様を適用。
    後述されている仕様での実装をお願いしたく思います。
    懸念されています「po の中で HTML エスケープを意識する」といった必要が生じる箇所は
    それほど多くない事、現時点ではβ版リリースという事を踏まえて
    今後修正を掛けていければと考えております。
    取り急ぎ最小限の実装で対応できればと考えておりますので
    懸念は残す形となりますが、やはり以下の様な実装で対応できればと思います。
    <!--{t string="tpl_465" escape="none"}-->
    <!--{t string="tpl_465"}-->
    
    escape=""は「指定なし」と同様の振る舞いの方が分かりやすいかと思います。
    
Line 
1<?php
2/*
3 * This file is part of EC-CUBE
4 *
5 * Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
6 *
7 * http://www.lockon.co.jp/
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 */
23
24require DATA_REALDIR . 'module/Locale/streams.php';
25require DATA_REALDIR . 'module/Locale/gettext.php';
26
27/**
28 * Helper class for localization.
29 * Library of static method.
30 *
31 * @package Helper
32 * @author LOCKON CO.,LTD.
33 * @version $Id$
34 */
35class SC_Helper_Locale {
36
37    /**
38     * Store the instance of SC_Helper_Locale_Ex.
39     * @var SC_Helper_Locale
40     */
41    static $_instance = NULL;
42
43    public $_translations = array();
44
45     /**
46     * Return a string which corresponding with message alias.
47     *
48     * @param   string  $string     message alias
49     * @param   array   $options    options
50     * @return  string  a string corresponding with message alias
51     */
52    public static function get_locale($string, &$options) {
53        is_null(SC_Helper_Locale_Ex::$_instance) and SC_Helper_Locale_Ex::$_instance = new SC_Helper_Locale_Ex();
54
55        // If language code is not specified, use site default.
56        if (empty($options['lang_code'])) {
57            $lang_code = $options['lang_code'] = defined('LANG_CODE') ? LANG_CODE : 'en';
58        } else {
59            $lang_code = $options['lang_code'];
60        }
61        // If device type ID is not specified, detect the viewing device.
62        if (!isset($options['device_type_id']) || ($options['device_type_id'] !== FALSE && !strlen($options['device_type_id']))) {
63            if (method_exists('SC_Display_Ex', 'detectDevice')) {
64                $device_type_id = SC_Display_Ex::detectDevice();
65            } else {
66                $device_type_id = FALSE;
67            }
68        } else {
69            $device_type_id = $options['device_type_id'];
70        }
71
72        $return = $string;
73
74        // Get string list of specified language.
75        if ($lang_code != 'en') {
76            $translations = SC_Helper_Locale_Ex::$_instance->get_translations($lang_code, $device_type_id);
77            // Whether a string which corresponding with alias is exist.
78            if (isset($translations[$return])) {
79                $return = $translations[$return];
80            }
81        }
82
83        if (is_array($options['escape'])) {
84            foreach ($options['escape'] as $esc_type) {
85                $return = SC_Helper_Locale_Ex::escape($return, $esc_type);
86            }
87        }
88
89        return $return;
90    }
91
92    /**
93     * Return a string which corresponding with message alias.
94     *
95     * @param   string  $single     message alias (single)
96     * @param   string  $plural     message alias (plural)
97     * @param   array   $options    options
98     * @return  array
99     */
100    public static function get_locale_plural($single, $plural, &$options) {
101        // Plural strings are coupled with a null character.
102        $key = $single . chr(0) . $plural;
103        // Get a string of specified language which corresponds to the message alias.
104        $translated = SC_Helper_Locale_Ex::get_locale($key, $options);
105        // Divide with a null character.
106        return explode(chr(0), $translated);
107    }
108
109    /**
110     * Get the strings of specified language from locale files.
111     *
112     * @param   string  $lang_code      language code
113     * @param   integer $device_type_id device type ID
114     * @return  array   strings
115     */
116    function get_translations($lang_code, $device_type_id = FALSE) {
117        $translations_key = "translations_" . $lang_code . "_" . $device_type_id;
118        // If the strings of specified language is not loaded
119        if (empty($this->_translations[$translations_key])) {
120            $translations = array();
121
122            // Get a list of files to load.
123            $file_list = $this->get_locale_file_list($lang_code, $device_type_id);
124
125            // Get the strings from each locale file using php_gettext.
126            foreach ($file_list as $locale_file) {
127                $stream = new FileReader($locale_file);
128                $gettext = new gettext_reader($stream);
129
130                $gettext->load_tables();
131                $translations = array_merge($translations, $gettext->cache_translations);
132            }
133
134            $this->_translations[$translations_key] = $translations;
135        }
136
137        return $this->_translations[$translations_key];
138    }
139
140    /**
141     * Get a list of locale files.
142     *
143     * @param   string  $lang_code      language code
144     * @param   integer $device_type_id device type ID
145     * @return  array   file list
146     */
147    function get_locale_file_list($lang_code, $device_type_id = FALSE) {
148        $file_list = array();
149
150        // Path to the EC-CUBE Core locale file.
151        $core_locale_path = DATA_REALDIR . "locales/{$lang_code}.mo";
152        // If a locale file of specified language is exist, add to the file list.
153        if (file_exists($core_locale_path)) {
154            $file_list[] = $core_locale_path;
155        }
156
157        // Get a list of enabled plugins.
158        if (defined(PLUGIN_UPLOAD_REALDIR)) {
159            $arrPluginDataList = SC_Plugin_Util_Ex::getEnablePlugin();
160            // Get the plugins directory.
161            $arrPluginDirectory = SC_Plugin_Util_Ex::getPluginDirectory();
162            foreach ($arrPluginDataList as $arrPluginData) {
163                // Check that the plugin filename is contained in the list of plugins directory.
164                if (array_search($arrPluginData['plugin_code'], $arrPluginDirectory) !== false) {
165                    // Path to the plugin locale file.
166                    $plugin_locale_path = PLUGIN_UPLOAD_REALDIR . $arrPluginData['plugin_code'] . "/locales/{$lang_code}.mo";
167                    // If a locale file of specified language is exist, add to the file list.
168                    if (file_exists($plugin_locale_path)) {
169                        $file_list[] = $plugin_locale_path;
170                    }
171                }
172            }
173        }
174
175        // Path to the template locale file.
176        if ($device_type_id !== FALSE) {
177            $template_locale_path = HTML_REALDIR . SC_Helper_PageLayout_Ex::getUserDir($device_type_id, true) . "locales/{$lang_code}.mo";
178            // If a locale file of specified language is exist, add to the file list.
179            if (file_exists($template_locale_path)) {
180                $file_list[] = $template_locale_path;
181            }
182        }
183
184        return $file_list;
185    }
186
187    /**
188     * 文字列のエスケープを行う
189     *
190     * @param   string  $string     エスケープを行う文字列
191     * @param   string  $esc_type   エスケープの種類
192     * @return  string  エスケープを行った文字列
193     */
194    static function escape($string, $esc_type) {
195        $return = $string;
196
197        switch ($esc_type) {
198            case 'h':
199            case 'html':
200                $return = htmlspecialchars($return, ENT_QUOTES);
201                break;
202
203            case 'j':
204            case 'javascript':
205                // escape quotes and backslashes, newlines, etc.
206                $return = strtr($return, array('\\'=>'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n','</'=>'<\/'));
207                break;
208
209            case 'nl2br':
210                $return = nl2br($return, true);
211                break;
212
213            case '':
214            case 'none':
215                break;
216
217            case 'htmlall':
218                $return = htmlentities($return, ENT_QUOTES);
219                break;
220
221            case 'u':
222            case 'url':
223                $return = rawurlencode($return);
224                break;
225
226            case 'urlpathinfo':
227                $return = str_replace('%2F','/',rawurlencode($return));
228                break;
229
230            case 'quotes':
231                // escape unescaped single quotes
232                $return = preg_replace("%(?<!\\\\)'%", "\\'", $return);
233                break;
234
235            case 'hex':
236                // escape every character into hex
237                $text = '';
238                for ($x=0; $x < strlen($return); $x++) {
239                    $text .= '%' . bin2hex($return[$x]);
240                }
241                $return = $text;
242                break;
243
244            case 'hexentity':
245                $text = '';
246                for ($x=0; $x < strlen($return); $x++) {
247                    $text .= '&#x' . bin2hex($return[$x]) . ';';
248                }
249                $return = $text;
250                break;
251
252            case 'decentity':
253                $text = '';
254                for ($x=0; $x < strlen($return); $x++) {
255                    $text .= '&#' . ord($return[$x]) . ';';
256                }
257                $return = $text;
258                break;
259
260            case 'mail':
261                // safe way to display e-mail address on a web page
262                $return = str_replace(array('@', '.'),array(' [AT] ', ' [DOT] '), $return);
263                break;
264
265            case 'nonstd':
266                // escape non-standard chars, such as ms document quotes
267                $_res = '';
268                for($_i = 0, $_len = strlen($return); $_i < $_len; $_i++) {
269                    $_ord = ord(substr($return, $_i, 1));
270                    // non-standard char, escape it
271                    if($_ord >= 126){
272                        $_res .= '&#' . $_ord . ';';
273                    }
274                    else {
275                        $_res .= substr($return, $_i, 1);
276                    }
277                }
278                $return = $_res;
279                break;
280
281            default:
282                trigger_error('unknown escape type. ' . var_export(func_get_args(), true), E_USER_WARNING);
283                break;
284        }
285
286        return $return;
287    }
288}
Note: See TracBrowser for help on using the repository browser.