如何跨PHP、JS和模板文件向web应用程序添加多语言支持?
我正在建立一个网站,需要支持不同的语言翻译。我有PHP、JavaScript和Smarty模板文件中的字符串需要翻译 我想使用类似PHP的函数,并为每个语言环境创建一个语言文件 当可翻译字符串位于PHP文件中时,这很容易,但Smarty模板和JavaScript文件中也有需要翻译的文本 我真的想要一个单独的文件来保存所有可翻译的字符串如何跨PHP、JS和模板文件向web应用程序添加多语言支持?,php,language-agnostic,localization,multilingual,Php,Language Agnostic,Localization,Multilingual,我正在建立一个网站,需要支持不同的语言翻译。我有PHP、JavaScript和Smarty模板文件中的字符串需要翻译 我想使用类似PHP的函数,并为每个语言环境创建一个语言文件 当可翻译字符串位于PHP文件中时,这很容易,但Smarty模板和JavaScript文件中也有需要翻译的文本 我真的想要一个单独的文件来保存所有可翻译的字符串 更新: 我想使用gettext(),但真正的问题是它只适用于PHP,而不适用于JavaScript,因为JavaScript是客户端的 我构建的所有web应用程
更新:
我想使用gettext(),但真正的问题是它只适用于PHP,而不适用于JavaScript,因为JavaScript是客户端的 我构建的所有web应用程序都支持3种语言,并且设计用于更多语言。我将所有文本存储在数据库中,并称之为常量
create table constants (
id integer not null,
fk_constant_group integer not null
)
create table constants_group (
id integer not null,
name varchar(32)
)
create table languages (
id integer not null,
name varchar(32),
accronym varchar(3),
/*other fields if necessary*/
)
create table constants_value (
id integer not null,
fk_constant integer,
fk_language integer,
value text
)
常量组用于按模块/页面对它们进行分组。如果要显示一个页面,则需要所有常量,因此可以使用单个查询获取一个页面所需语言的所有数据。组名上的索引是合适的。
在PHP中,我写了如下内容:
public static function SetNames()
{
$info=debug_backtrace(true);
$result=self::GetNames($info);
Factory::getSmarty()->assign("names",$result);
return $result;
}
public static function GetNames($info=false) /*$info is the debug_backtrace result*/
{
if(!$info)
$info=debug_backtrace(true);
$class=$info[1]['class']; /*It's the page name basically*/
if(isset(self::$m_names[$class]))
return self::$m_names[$class]; /*Using a static member for caching*/
global $application;
$langId=$application->langId;
$constants=AppFac::getAdo()->GetAll("SELECT
X.name as constant_name,
XV.value as constant_value
FROM
constants X
LEFT JOIN constants_values XV ON XV.fk_constant=X.id
LEFT JOIN constants_groups XG ON X.fk_constant_group=XG.id
WHERE
XG.name=?
AND XV.fk_language=?",array($class,$langId)); /*Parametrized query*/
$result=array();
foreach($constants as $constant) /*Make constants easily accessible*/
$result[$constant['constant_name']]=$constant['constant_value'];
self::$m_names[$class]=$result;
return $result;
}
从PHP模块中,在获取或显示模板之前,调用SetNames()
方法,该方法将自动确定从中调用的类的名称,并使用该名称查找常量组并在会话中以语言集的形式填充常量。然后,使用模板中的常量,如{$names.label\u name}
,例如,如果您正在为页面查找label\u name
常量
这种方式很好,因为:
1.您可以直接从为应用程序构建的Web界面添加多种语言。
2.当文本存储在数据库中时,您可以轻松地组织它们。
3.您可以从为应用程序构建的界面轻松添加和编辑文本
如果您希望翻译整个页面而不是常量,那么当您只在模板中包含一个资源时,可以使用Smarty资源,并在PHP中定义如何处理该资源。
您可以将字符串存储在CSV文件中,如下所示:
"Welcome","Welcome"
"Total Price","Total Price"
为每种语言制作一个文件。第一个值是用于获取字符串的键,第二个值是用于转换的键。然后,您可以使用加载适当文件、将变量存储在数组中以及根据请求翻译文本的函数构建一个类。例如:
protected function loadTranslation($locale) {
$this->_data=array();
$localeFilePath="locale/" . $locale . "/whatever.csv";
if(file_exists($localeFilePath)){
$localeFileHandle = fopen($localeFilePath, "r");
while (($line = fgetcsv($localeFileHandle, 1000)) !== FALSE) {
$this->_data[$line[0]]=$line[1];
}
fclose($localeFileHandle);
}
return $this;
}
用于加载值和
public function __($label) {
$output=$this->_data[$label];
if(empty($output)) $output=$label;
return $output;
}
翻译。
例如,您可以使用以下方法获得正确的字符串:
echo $this->__('Total Price')
使用CSV的优点是,您不需要为数据库操心,当然,它们可以通过Excel进行编辑,当您需要告诉一些数据输入人员进行翻译时,Excel将非常有用
此外,您还可以编写一个小脚本,在代码中查找_u()函数使用的字符串,然后在CSV文件中写入相应的字符串,这样您就不必浪费时间为代码中使用的每个字符串在每个CSV文件中追加字符串
至于Smarty模板和Javascript文件,您还必须从PHP获取已翻译的字符串。Smarty值来自PHP,因此在为Smarty赋值之前,请使用转换器。至于javascript,它必须由PHP动态创建,以便您可以在适当的位置设置翻译后的字符串。最大的障碍是获取javascript中的语言常量。我已经可以使用gettext()和.po文件完成上面的大部分工作了。这比gettext()更难使用。不调用gettext(),而是访问数组。与构建JS的方式相同。PHP甚至有一个将数组编码为JSON的函数,可以在JS中使用,因此它比gettext()更快更简单。