“中国要复兴、富强,必须在开源软件领域起到主导作用,为了国家安全和人类发展,责无旁贷,我们须为此而奋斗”——By:云客
在上篇中讲到了配置覆写,一般在哪些情况下需要进行配置覆写呢?往往是针对不同角色、上下文、域名、组等等,本篇看看语言配置覆写,她是默认安装下系统提供的唯一一个配置覆写,由语言模块提供,服务定义在:\core\modules\language\ language.services.yml中,如下;
language.config_factory_override:
class: Drupal\language\Config\LanguageConfigFactoryOverride
arguments: ['@config.storage', '@event_dispatcher', '@config.typed', '@language.default']
tags:
- { name: config.factory.override, priority: -254 }
容器id:language.config_factory_override
类:Drupal\language\Config\LanguageConfigFactoryOverride
如果单从配置覆写来讲,语言配置覆写是非常简单的:根据语言加载其翻译后的配置信息去覆写原始需要翻译的配置内容,这样就能以翻译过的配置内容去展示,比如站点名。
系统可以有多种语言,其中一种被设定为系统默认语言,配置信息根据不同语言可能是不同的,跟语言相关的部分有对应变体(或者说是翻译),由此根据语言将配置归类到多个集合里,换句话讲即每种语言都是一个配置集Collection(在数据库活动配置储存表config中以collection字段标识,如果是前文提到的针对角色、上下文等进行的覆写,该字段则标识不同的角色、上下文等),完整的配置信息储存在默认配置集里面(默认集的集名为空字符串),每种语言各对应一个配置集(集名为:'language. $langcode'),里面只储存和语言相关的配置信息(和语言无关的其他配置信息储存在默认配置集里),语言配置覆写即是根据对应语言(默认为language.default服务提供的语言)加载覆写数据(和语言相关的配置信息变体)对原配置进行覆写,这里需要注意系统安装时初始指定的默认语言使用默认配置集作为自己的配置集,即便是系统安装后更换默认语言,该语言的配置集依然是默认集,而默认集里的配置信息就是活动配置中保存的原始配置信息,这意味着系统安装时选定的默认语言不会进行覆写,它本身就是原始活动配置,将直接出现在表单中或者可编辑配置对象中,这里强调安装时选定的默认语言,安装后更改选定的默认语言并不使用默认集。
举个列子,配置对象 “system.site”是储存在默认配置集里,该配置对象中的站点名项是可翻译的,所以其他各语言的配置集中将储存站点名项,而和语言无关的其他项将不储存(系统如何知道站点名是可翻译的呢?请看后续的配置schema),当在某种语言下访问站点时,读取的配置信息中的站点名是经过该语言配置集覆写的。
那么各语言集里储存的配置信息是怎么产生的呢?在系统中添加一种语言,此时还不会产生该语言集配置信息,然后导入翻译或者在管理界面(/admin/config/regional/translate)建立翻译时,将产生该语言对应的配置信息集,也就是说语言覆写的配置信息来自于翻译系统,这里需要注意的是所有语言(包括默认语言)的配置集中和语言相关的翻译都是基于初始提供的配置yml文件,由于系统是以英语进行开发的,所以可以看做是基于英语的,如果在翻译界面没有针对该配置原字符进行翻译,则不会有配置覆写值。读者可以做一个实验:添加某种语言到系统中,此时在管理翻译界面(/admin/config/regional/translate)以该语言过滤搜索字符“Drupal”并对其进行一个特殊的翻译,比如翻译为“云客”,然后以该语言访问站点,就会发现站点名被覆写为“云客”了,这是因为初始提供的system.site.yml配置文件中站点名被设置为“Drupal”,在不同语言中通过翻译对其进行了覆写。这里需要注意站点初始安装选择的语言问题:假设站点是以简体中文进行初始安装,那么在翻译管理界面(/admin/config/regional/translate)对简体中文里面的字符“Drupal”进行翻译,翻译的站点名将成为简体中文界面下显示的站点名,但这不是进行了语言配置覆写,而是改写了默认集,也就是活动配置中储存的原始配置信息,此时站点设置(/admin/config/system/site-information)中的站点名称将变为该处翻译的内容,这是由于前文提到的系统安装时初始指定的默认语言使用默认配置集作为自己的配置集,即便是系统安装后更换默认语言,该配置语言的配置集依然是默认集。这里云客发现一个bug,见补充说明
系统提供的这个语言配置覆写服务不仅仅提供覆写功能,她还包括当配置对象变化时(如保存、删除、重命名)对各语言配置集里对应的配置信息进行联动操作,这是通过事件派发机制实现的,因此语言配置覆写服务实现了事件订阅器接口,在事件派发器中注册了针对配置的保存、删除、重命名、添加集事件的侦听器,当有配置发生这几种操作时将会得到通知,从而进行相应操作。
当有配置对象保存时,系统会派发配置保存事件,配置覆写服务监听该事件,会根据正在被保存的配置对象去处理每种语言对应的翻译配置信息,过程如下:
如果对应语言尚未有被翻译的配置覆写内容则不进行任何处理
当系统中该语言已经在自己配置集里储存有被翻译的配置覆写信息时,将该覆写信息包装到语言配置覆写对象中(该对象是一个特殊的配置对象,继承自Drupal\Core\Config\StorableConfigBase,和通常的Drupal\Core\Config\Config配置对象相比,主要区别是不派发保存和删除事件,取而代之的是派发保存覆写和删除覆写事件),比较当前正保存的配置对象和该覆写配置对象并如下处理:
当前配置对象中没有的配置信息,如果存在于覆写配置对象里将被删除
当前配置对象中的某配置键,其值不是数组,而覆写配置对象里该键是数组,在覆写配置对象里该键将被删除
经过以上处理如果覆写配置对象中已经无配置信息,则从该语言集中删除该翻译覆写配置信息,如果还有配置信息,则保存处理过的配置信息。
以上逻辑在Drupal\Core\Config\ConfigFactoryOverrideBase中的filterOverride方法里
配置对象重命名和删除事件的侦听比较简单,这里不多讲,在语言配置覆写信息被保存或删除时会派发language.save_override和language.delete_override事件,容器id为locale.config_subscriber的服务注册了onOverrideChange方法侦听该事件,它做了什么样的处理将在locale模块中讲解
模块在开发其他配置覆写时可以参考语言配置覆写的实现
本节就讲到这里
补充说明:
一、配置集名字符串需要满足正则[a-zA-Z_.].
二、云客发现目前的版本存在以下BUG需要修复:
Bug1:语言配置覆写服务的createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION)中没有考虑到默认集不能得到语言代码可能会抛出异常的问题,修复后提高系统健壮性,该bug严格说也不算是bug,问题不严重,开发者只需要注意这点,希望drupal越来越健壮,不要因为一些无关紧要的问题导致系统异常。
Bug2:以非英语语言作为默认语言安装系统后,系统添加英语,英语界面下站点名无法编辑,该问题是由于英语本身作为开发语言,和显示语言一致,所以在管理翻译界面(/admin/config/regional/translate)默认不提供英语的翻译,但配置对象覆写依赖于语言的翻译,而英语没有提供翻译,恒定为“drupal”,该问题不仅表现在站点名上,所有涉及英语的配置覆写均会出现问题,修复方法是在语言管理界面开启英语的翻译,或者开启核心提供的配置覆写模块以编辑英语的配置覆写
反馈互动