mantis的多语言支持特性分析
mantis是一个支持多种语言的bug管理系统。本文分析mantis是如何支持多语言的。
分析mantis的源码,会发现mantis的每个页面的任何一个字符串输出都是通过lang_get这个函数来实现的。
lang_get函数接受一个字符串id,返回该id对应的文本在当前语言设置下的字符串
例如:
lang_get('all_projects')
在系统设置为英文时,返回的内容是:'All Projects'
在系统设置为中文时,返回的内容是:'所有的项目'
mantis的lang目录下包含了很多txt文件,它们实际上是php文件。每个文件对应一种语言的字典表。字典表的key是变量名,value就是变量的值。
变量名对应的是lang_get的参数。例如上面的例子:
lang_get('all_projects')获取的是lang目录下某一个文件中定义的$s_all_projects这个变量的值。
我们可以在strings_english.txt中看到$s_all_projects = 'All Projects';
而在strings_chinese_simplified.txt中看到$s_all_projects = '所有的项目';
简单的说,就是通过设置(在config_inc.php中设置$g_default_language = {lang})使得mantis系统自动加载lang目录下的
strings_{lang}.txt文件,将很多$s_{word_id}类型的变量载入。然后,在显示的时候通过lang_get({word_id})获取。从而达到支持多语言的目的。
需要添加语言支持时,只需要在lang目录下添加相应的文件定义字典表并修改语言配置即可。
编写插件,添加了新的词语时,比如svn版本,可以这样做:在lang目录下每个文件中添加变量$s_svn_version
例如在strings_english.txt里面定义$s_svn_version = 'SVN Version';
在strings_chinese_simplified.txt里面定义$s_svn_version = 'SVN 版本';
在页面中输出lang_get('svn_version')
#ROOT/core/lang_api.php #lang_get function lang_get( $p_string, $p_lang = null ) { global $g_lang_strings; # If no specific language is requested, we'll # try to determine the language from the users # preferences $t_lang = $p_lang; if( null === $t_lang ) { $t_lang = lang_get_current(); } // Now we'll make sure that the requested language is loaded lang_ensure_loaded( $t_lang ); # note in the current implementation we always return the same value # because we don't have a concept of falling back on a language. The # language files actually *contain* English strings if none has been # defined in the correct language # @todo thraxisp - not sure if this is still true. Strings from last language loaded # may still be in memeory if a new language is loaded. if( lang_exists( $p_string, $t_lang ) ) { return $g_lang_strings[$t_lang][$p_string]; } else { $t_plugin_current = plugin_get_current(); if( !is_null( $t_plugin_current ) ) { lang_load( $t_lang, config_get( 'plugin_path' ) . $t_plugin_current . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR ); if( lang_exists( $p_string, $t_lang ) ) { #comment add by rare------------------------------------ #$t_lang -- lang_id #$p_string -- word_id----------------------------------- return $g_lang_strings[$t_lang][$p_string]; } } if( $t_lang == 'english' ) { error_parameters( $p_string ); trigger_error( ERROR_LANG_STRING_NOT_FOUND, WARNING ); return ''; } else { # if string is not found in a language other than english, then retry using the english language. return lang_get( $p_string, 'english' ); } } } function lang_get_default() { global $g_active_language; $t_lang = false; # Confirm that the user's language can be determined if( function_exists( 'auth_is_user_authenticated' ) && auth_is_user_authenticated() ) { $t_lang = user_pref_get_language( auth_get_current_user_id() ); } # Otherwise fall back to default if( !$t_lang ) { #comment add by rare -------------------------- # get value of $g_default_language # --------------------------------------------- $t_lang = config_get_global( 'default_language' ); } if( $t_lang == 'auto' ) { $t_lang = lang_map_auto(); } # Remember the language $g_active_language = $t_lang; return $t_lang; } function lang_load( $p_lang, $p_dir = null ) { global $g_lang_strings, $g_active_language; $g_active_language = $p_lang; if( isset( $g_lang_strings[$p_lang] ) && is_null( $p_dir ) ) { return; } if( !lang_language_exists( $p_lang ) ) { return; } #comment add by rare ------------------------- # map lang_id to strings_{lang_id}.txt # -------------------------------------------- if( $p_dir === null ) { include_once( config_get( 'language_path' ) . 'strings_' . $p_lang . '.txt' ); } else { if( is_file( $p_dir . 'strings_' . $p_lang . '.txt' ) ) { include_once( $p_dir . 'strings_' . $p_lang . '.txt' ); } } # Allow overriding strings declared in the language file. # custom_strings_inc.php can use $g_active_language $t_custom_strings = config_get( 'absolute_path' ) . 'custom_strings_inc.php'; if( file_exists( $t_custom_strings ) ) { require( $t_custom_strings ); # this may be loaded multiple times, once per language } $t_vars = get_defined_vars(); #comment add by rare ---------------------------------------------- # map word_id to $s_{word_id} # ----------------------------------------------------------------- foreach( array_keys( $t_vars ) as $t_var ) { $t_lang_var = preg_replace( '/^s_/', '', $t_var ); if( $t_lang_var != $t_var ) { $g_lang_strings[$p_lang][$t_lang_var] = $t_var; } else if( 'MANTIS_ERROR' == $t_var ) { if( isset( $g_lang_strings[$p_lang][$t_lang_var] ) ) { foreach( $t_var as $key => $val ) { $g_lang_strings[$p_lang][$t_lang_var][$key] = $val; } } else { $g_lang_strings[$p_lang][$t_lang_var] = $t_var; } } } }