Liferay中无Portlet模块如何读取自身Language.properties文件
Liferay无Portlet纯工具模块读取自身Language.properties配置方案
根本原因
Liferay的语言资源加载机制默认仅自动注册两类模块的语言包:
- 配置了Portlet的业务模块
- 显式声明了全局资源提供者的公共语言模块
无Portlet的纯工具类模块没有主动向OSGi容器注册自身的语言资源绑定,因此直接调用LanguageUtil.get(locale, key)时,扫描路径不会覆盖B模块的配置文件,只会命中公共language模块的全局键值。
实现步骤
- 第一步:规范语言文件存放路径
确认B模块的所有多语言文件统一存放在src/main/resources/content目录下,默认语言文件命名为Language.properties,其他语种文件遵循Language_语言代码_国家代码.properties命名规范(例如Language_zh_CN.properties、Language_en_US.properties),不要自定义存放路径,避免资源扫描失败。 - 第二步:向OSGi容器注册B模块的语言资源服务
无需添加Portlet配置,两种注册方式二选一即可,适配所有Liferay 7.x版本:- 注解式注册(推荐,适配Liferay 7.2及以上版本)
在B模块中新增资源绑定注册类,代码如下:
import com.liferay.portal.kernel.language.UTF8Control; import org.osgi.service.component.annotations.Component; import java.util.Enumeration; import java.util.ResourceBundle; @Component( property = { "language.id=en_US", "language.id=zh_CN" }, // 枚举模块支持的所有语种ID service = ResourceBundle.class ) public class ModuleBResourceBundle extends ResourceBundle { @Override protected Object handleGetObject(String key) { return _resourceBundle.getObject(key); } @Override public Enumeration<String> getKeys() { return _resourceBundle.getKeys(); } private final ResourceBundle _resourceBundle = ResourceBundle.getBundle( "content.Language", UTF8Control.INSTANCE); }- bnd配置注册(兼容所有Liferay 7.x版本,无需编写Java类)
直接在B模块的bnd.bnd文件中添加以下配置:
-liferay-aggregate-resource-bundles: true Provide-Capability:\ liferay.resource.bundle;\ resource.bundle.base.name="content.Language" - 注解式注册(推荐,适配Liferay 7.2及以上版本)
- 第三步:调整调用代码,传入模块类加载上下文
无上下文的LanguageUtil.get调用默认走全局资源扫描路径,需要在B模块内部调用语言工具时,传入B模块自身的类加载器,确保优先匹配本模块的语言键:// 传入B模块中任意一个类的Class对象作为类加载上下文即可 String langValue = LanguageUtil.get(ModuleBUtils.class.getClassLoader(), targetLocale, configKey);
验证注意事项
- 配置完成后需要重启B模块或对应Liferay服务器,等待OSGi服务注册完成后再验证,热部署可能出现资源加载不及时的问题
- 语言键优先级规则:调用时指定类加载器的模块自身语言包 > Portlet模块语言包 > 公共全局语言包,非必要不要和公共language模块使用重复的键名,避免出现非预期的覆盖
- 如果出现乱码问题,确认资源文件读取时使用了
UTF8Control作为加载控制,不要使用JDK默认的ISO-8859-1编码加载
内容的提问来源于stack exchange,提问作者KRISTIJAN TOMASINI
相关产品推荐
相关产品推荐

