我们导航到区块的管理界面,找到“语言切换器(内容)”区块,将它放在主题的“标题”区域中,同时禁用区块标题。默认是这样显示的:
我们调整一下CSS:
.region-header{
float:right;
clear:none;
}
.region-header #block-locale-language-content .language-switcher-locale-url li{
display:block;
float:left;
margin-right:20px;
}
.region-header a {
text-decoration: none;
}
这是调整后的样子:
值得一提的是,如果把新闻翻译好了以后,在新闻列表页面的英文版本下,显示也是基本正常的,这是en/news/4路经下的样子:
除了节点和分类术语以外,我们还有很多工作要做,比如菜单、区块、系统变量,字段的标签,等等,需要翻译。
我们下载、安装、启用i18n模块,我这里使用的版本是i18n-7.x-1.9。这个模块还依赖于Variable模块,我们还需要先安装Variable模块,我这里使用的版本是variable-7.x-2.2。 i18n模块下面包含很多个子模块,从上到下:
我这里启用了Block languages、Field translation、Internationalization,这里的Contact translation是负责Contact这个核心模块的翻译的,不过我们这个站点没有用到这个模块。
这里,我启用了Menu translation模块;Multilingual content这个是基于content translation的,我们这里没有采用这种方案;Multilingual forum解决的是论坛模块的翻译,我们这里没有使用论坛模块;Multilingual select,这个可能有用,后面我们不妨启用测试一下,看是否能够解决我们前面所说的分类术语选择时的问题。
这里,启用了String translation;Synchronize translations是基于content translation的,我们这里没有采用这种方案;Taxonomy translation,我们已经解决了分类术语的翻译,如果你觉得我们前面的方式不够好的话,可以尝试一下这个模块;Path translation,用于翻译路经,有时候有用。
我们这里启用了Translation sets、Variable translation,前者为多个子模块所依赖,后者用于变量的翻译,很有用;Translation redirect主要用于SEO,我们这里对SEO的要求不高;User mail translation用于用户电子邮件的翻译,我们这个站点用处不大。
首先,我们来看站点名称的翻译,我们站点的名称为“亚艾元”,在英文环境下,我们想显示拼音的形式。怎么翻译呢?导航到admin/config/system/site-information,这是站点名称所在的配置界面:
在这个页面的上面有提示,这个表单中包含多语言的变量,我们将它切换到英文的环境下,admin/config/system/site-information?variable_realm_key_language=en,在这种情况下,输入拼音,保存:
此时,我又遇到了一个问题,那就是虽然我这里输入了变量的英文版本,但是在首页的中英文切换的过程中,站点名称始终是中文。我尝试了比较多的办法,比如分别使用路经:zh-hans/admin/config/system/site-information,和en/admin/config/system/site-information访问,然后输入对应的中文、英文版本,还是不行。
我Google 了一下,找到一篇文档,https://drupal.org/node/1113374,这里讲的就是变量翻译,我的配置没有任何问题。通过这篇文章,我了解到admin/config/regional/i18n的存在,这是i18n的配置界面,变量的多语言设置可以在admin/config/regional/i18n/variable完成。
然后我想到了在预处理函数中,搞定这个问题,在当前主题的template.php文件中添加这么一个函数:
function yaiyuan_preprocess_page(&$variables, $hook) {
global $language;
$lang_name = $language->language ;
$variables['site_name'] = (theme_get_setting('toggle_name') ? filter_xss_admin(i18n_variable_get('site_name', 'en')) : '');
drupal_set_message($lang_name);
}
注意,这里的$lang_name始终都是zh-hans,即便是我切换到了英文下面。我这里使用i18n_variable_get来替代默认的variable_get,以便支持多语言。
昨天晚上一直在想解决方案,如果我能够获取到当前语言,那么通过预处理函数的方式,就能够解决问题,Drupal核心自带的语言切换器区块对应的代码里面,应该有如何获取当前语言的代码。这样一想,感觉问题是可以通过预处理函数的方式解决的。
不过,我突然想到了一件事情,即便是使用en/admin/config/system/site-information访问后台页面的时候,后台显示的也是简体中文。我突然想到,Drupal7中,界面语言和内容语言的检测方法是分开配置的,界面语言的检测方法我们还是用的默认的,很可能是这里出了问题。
我们先沿着第一种方案继续前进,我们去配置“语言切换器(内容)”的时候,可以看出这个区块是由locale模块提供的,这样我们就可以顺藤摸瓜,找到对应的代码。
function locale_block_view($type) {
if (drupal_multilingual()) {
$path = drupal_is_front_page() ? '<front>' : $_GET['q'];
$links = language_negotiation_get_switch_links($type, $path);
这里面,我觉得比较关键是language_negotiation_get_switch_links,通过搜索,找到这个函数的源代码。在这个函数里面,有这么一段代码:
if (count(language_list()) >= 2) {
$language = language_initialize($type);
}
给了我很大的提示,这里的$type有多种情况,我们在前面分析核心源代码的时候,曾经提到过,打开bootstrap.inc文件,找到:
define('LANGUAGE_TYPE_CONTENT', 'language_content');
/**
* The type of language used to select the user interface.
*/
define('LANGUAGE_TYPE_INTERFACE', 'language');
/**
* The type of language used for URLs.
*/
define('LANGUAGE_TYPE_URL', 'language_url');
我们这里使用LANGUAGE_TYPE_CONTENT。根据这些信息,我最终使用下面的代码,解决了这个多语言问题:
function yaiyuan_preprocess_page(&$variables, $hook) {
//global $language;
//$lang_name = $language->language ;
$language = language_initialize(LANGUAGE_TYPE_CONTENT);
$variables['site_name'] = (theme_get_setting('toggle_name') ? filter_xss_admin(i18n_variable_get('site_name', $language->language)) : '');
//drupal_set_message($lang_name);
//print debug($language);
}
这里面,如何获取当前语言,我首先尝试了一下$language,总是不对。使用language_initialize(LANGUAGE_TYPE_CONTENT),则可以成功获取。注意我们这里获取的是当前内容的语言。不是当前的界面语言。此外,我对这个语言变量还debug了一下,查看了它的结构。它的结构是这个样子的:
stdClass::__set_state(array(
'language' => 'en',
'name' => 'English',
'native' => 'English',
'direction' => '0',
'enabled' => '1',
'plurals' => '0',
'formula' => '',
'domain' => '',
'prefix' => 'en',
'weight' => '0',
'javascript' => '',
'provider' => 'locale-url',
))
我们使用预处理函数的方式解决了问题。不过,总不能每次都这样解决吧。或许真的是界面语言的检测与选择的配置问题。导航到admin/config/regional/language/configure,对于界面语言的检测方法,我们与内容的保持一致。
保存这里的配置。注释掉,我们前面所写的预处理函数。站点名称的中英文切换,正常。当然,前面的工作,也不是没有白做,如果你跟着阅读了源代码,会对Drupal7多语言的背后机制有更深的理解。比如这个语言,它分为:内容、界面、路径。我们这里对这个概念有了更深的理解。我们前面的获取当前语言,其实是获取当前内容语言,而不是获取当前界面语言。
如果,我们这里是一个Logo,中文Logo和英文Logo不一样,怎么解决呢?导航到zh-hans/admin/config/regional/i18n/variable,
选中这里的主题设置复选框即可,这样主题的Logo就支持多语言了,分别为每个语言上传一个Logo,解决了Logo的多语言问题。
我们来看一下如何翻译主菜单,导航到主菜单的编辑页面,admin/structure/menu/manage/main-menu/edit。这里面有一个多语言的配置选项:
第一个选项,菜单项没有多语言选项,只有菜单本身可被翻译。菜单本身可被翻译?如何理解,看这个菜单右上角的标签,里面有一个“翻译”标签:
点击这个“翻译”标签,就可以对菜单进行翻译。只是我们这里没有必要。
第二个选项,翻译和本地化。注意,这里的翻译(translate)和本地化(Localize)之间是有区别的。如果一个菜单项,它具有语言属性,此时会允许翻译;如果它没有设置语言,则可被本地化。
第三个选项,固定语言,每个菜单项都有一个语言属性,它们只会显示在自己的语言下。
我们这里选择第二个选项,保存。我们现在对主菜单的菜单项,进行编辑:
点击“首页”菜单项右边的编辑链接。进入菜单项的编辑页面。
此时,右上角有了一个“翻译”标签,我们点击这个标签,就可以对这个菜单项进行翻译了。
点击操作里面的“翻译”链接,我们将菜单项的标题翻译一下:
翻译好了保存结果。这是翻译后的样子:
菜单项的编辑页面,还有一个语言选项:
我们可以设置,这个菜单项是属于哪个语言下的。这样的话,我们可以为每种语言都创建一个对应的菜单项,也能解决问题。
因为,我们这里面,中文、英文的节点ID是相同的,所以我们没有必要创建多个菜单项。直接对菜单项的标题进行翻译即可。
重复前面的操作,直到把主菜单里面剩余的菜单项都翻译完毕为止。需要说明一下的是,当我们翻译到“关于我们”下面的第一个子菜单项“公司历程”的时候,菜单项编辑页面的右上角没有“翻译”标签。如果我们直接输入对应的路径的话,此时会提示没有权限。这是因为,我们还没有翻译菜单项“公司历程”所对应的节点,我们将对应的节点翻译成英文后,这里的菜单项,也可以翻译了。
到最后,只剩下“联系我们”这个webform页面了,这也是一个普通的节点。我们首先让内容类型Webform支持字段翻译,将它的Title替换成字段的形式。这个时候,我们就可以将“联系我们”这个节点的标题和正文翻译成英文了。之后,就可以翻译对应的菜单项了。只不过这个页面的表单还无法翻译,主要是表单元素的标签,在英文环境下还是显示的中文。
我们现在先不管这个,到此,整个主菜单里面的所有菜单项,都被翻译成为了英文。注意,
注意,这里不仅仅是主菜单,左边的Menu block,以及面包屑都变成英文的。这说明了Menu block和Menu Position模块对多语言的支持是比较友好的。
不过,左下角的“联系我们”区块,仍然是中文的,我们来看一下,如何将它翻译成英文。点击它的配置链接,进入它的编辑页面en/admin/structure/block/manage/block/2/configure。在这里,可见性设置里面,多了一个语言选项。
这里有两种方式,第一种方式,是将这个区块标记为可翻译的,也就是选中“Make this block translatable”。选中后,下面的按钮多出来了一个:
我们可以点击“保存并翻译”按钮。
我们点击英文右边的翻译链接,来翻译这个区块:
遗憾的是,我们这里面只能翻译区块标题,不能翻译区块的正文,这是因为区块正文所使用的文本格式不支持多语言。如何让它支持多语言呢?导航到i18n的管理界面,点击右上角的“字符串”标签:
这里有两个配置选项:
和
对于源语言,我们使用默认的简体中文即可。对于可翻译的文本格式,我们这里选中所有的,保存。回到,刚才的区块的翻译页面,现在就可以翻译区块正文了:
在这里,输入对应的英文。注意,对于区块正文,应该保留原来的HTML标签。
我们可以创建两个区块,一个显示在中文下,一个显示在英文下,两个区块显示在同一个区域的同一位置。这也是一种常见的解决方案,我以前就非常喜欢这种方式。
我发现一个问题,面包屑没有正确显示:
具体原因不明。我把新闻、产品所有节点也都翻译了一遍,使用的Google翻译,没有人工校对。
现在,我们重复前面的操作,将“页脚菜单”、“版权信息”也翻译成英文。
令人遗憾的是,我们将所有的菜单项翻译后,在英文环境下,显示的还是中文。这是我的翻译:
原因未明。我们暂时先不管它。来看“版权所有”区块,我们对它进行配置,将它只显示在中文下:
接着,创建一个新的静态区块,是版权所有区块的英文版:
也放在页脚区域,这里只显示在英文环境下;
保存。这个区块的多语言,我们也解决了。来看页脚菜单区块,这个区块我们用的是核心自带的,我们前面讲到左边的菜单区块(menu block)的中英文显示是正常的,我们将这个页脚菜单导航替换成Menu block模块提供的方式显示。
作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
导航到区块的管理界面,创建一个新的menu block(菜单区块),做以下配置:
我们将这个区块放在页脚区域,测试一下。中英文显示正常了。把原来的核心自带的区块禁用。现在页脚也正常了。
我们没有必要去深究,为什么核心自带的对多语言支持不友好,只要解决问题就好。有时候换种方式,绕过去,可能会更好。
我们现在回到新闻列表页面,或者一个新闻节点页面,此时的面包屑是不正常的。我们前面已经提到过了。我想这里之所以显示“新闻”两个字,是因为Views里面的配置问题。我们编辑对应的Views,将标题设置为英文的形式:
现在,在英文环境下,面包屑显示正常了,但是在中文环境下,又不正常了。
可是,这个面包屑是基于菜单的,而我们的菜单项中,已经完成了“新闻”到“News”的翻译。经过测试,发现,新闻节点页面的面包屑,是基于菜单的;新闻列表页面,是基于Views的。
为了解决这个问题,我们下载、安装、启用Internationalization Views模块,我这里使用的版本是i18nviews-7.x-3.x-dev。这个模块只有开发版,不过Drupal7下的开发版的安装量也超过了1万。安装后,报了一个错:
这样的错误消息很多,我们这里不去管它。我最终成功解决这个问题,解决办法如下:
导航到admin/config/regional/translate/translate,在过滤条件中:
将搜索限制在视图上,也就是Views上。这个时候,会列出Views中的很多需要翻译的字符串:
这里的“新闻”,也就是news视图的标题,我们把它翻译一下:
翻译后,测试了一下,发现不行。我又导航到admin/config/regional/translate/i18n_string,在这里刷新了一下字符串:
这样新闻列表的面包屑,就显示正常了。
用同样的版本,解决产品列表的面包屑显示。需要说明的是,上面的刷新字符串在这里没有起作用,真正起作用的是清除缓存。
不过令人遗憾的是,新闻节点页面,在英文环境下的面包屑显示不正常:
但是产品节点的显示就正常。两者之间的配置,我记得没有任何不同。我对这个问题研究了很久,始终找不到解决办法。
我是这样解决的,解决的办法不是很地道。首先是编辑当前主题的info文件yaiyuan.info,取消注释这句代码:
scripts[] = js/script.js
接着向script.js这个文件中添加以下代码:
jQuery.noConflict();
(function($) {
$(function() {
$('.i18n-en .breadcrumb li a').each(function(index){
if($(this).attr('href') == '/yaiyuan1/en/news'){
//$(this).addClass('abc');
$(this).html('News');
}
});
});
})(jQuery);
这段JS的作用,就是将面包屑中“新闻”这个链接的文本替换为“News”。
有时候,问题实在解决不了的话,可以借助于jQuery, Hack一下,也没有关系。