系列文章
本系列文章已收录到专栏。
前言
尽管大多数情况下我们开发的插件可能都是自己或者团队内部使用,但是如果想要将开发的插件发布到 Jetbrains 的插件市场,吸引更多的用户使用和支持,那么 i18n 就必不可少了。而 IntelliJ 也给我提供了内部支持,只需要简单几行代码即可实现 i18n,下面开始分步骤进行讲解,另外本文涉及到的完整代码也已上传到GitHub。
语言文件
首先我们需要在 resources 文件夹下创建我们的语言文件,这里选择先创建一个 messages 文件夹(名称无要求),然后在下面创建一个ActionBundles.properties
文件(后缀为properties
,名称无要求,一般会分模块创建多个语言文件便于管理,该文件用于配置默认语言即英文),之后再创建一个ActionBundles_zh.properties
文件用于配置中文内容,这里的_zh
则代表用于配置中文,其中_
固定,zh
为语言代码,例如想要配置日语则是ja
,不同国家的语言代码可以在网上自行搜索,这里提供一个网址,效果如下:

可以看到在语言配置文件创建完毕后,我们分别在内部添加了demo.greet-msg=Hello, {0}
和demo.greet-msg=\u4f60\u597d\uff0c{0}
两个配置。其中\u4f60\u597d\uff0c
是你好,
中文字符对应的 Unicode 编码,这里之所以使用 Unicode 编码,是因为官网推荐我们将 ASCII 码范围外的字符都使用 Unicode 编码进行表示,相关的转换网站也很多,这里提供一个。除此之外,还可以看到我们的内容中还包含{0}
,这个则是参数占位标记,多个参数按照0, 1, 2...
的顺序依次累加即可。
工具类文件
有了以上语言文件,我们就可以创建一个工具类专用于语言解析了,这里先展示内容:
kotlin
# ①
private const val BUNDLE = "messages.ActionBundles"
# ②
object MessageUtils: DynamicBundle(BUNDLE) {
# ③
fun message(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any) = getMessage(key, *params)
}
调用方式也很简单:
kotlin
# ④
MessageUtils.message("demo.greet-msg", "butterfly")
下面分开始介绍上述代码的含义:
首先是①,这里用于声明语言文件的位置,其中messages
和ActionBundles
分别是上文我们创建的用于存储语言文件的文件夹名和文件名。
然后是②,可以看到这里我们创建的工具类继承了DynamicBundle
类,并传递了我们声明的BUNDLE
,有了这部分代码我们就可以得到 IntelliJ 内部的语言文件解析功能:只需要专注于语言文件的编写,而无需考虑不同语言的判断和文件选取。
之后是③,这里声明了一个message
方法,而内容则是直接调用了getMessage(key, *params)
这个DynamicBundle
类内部提供的方法,这里之所以自己重新声明了一遍方法,则是为了使用 key 参数前@PropertyKey(resourceBundle = BUNDLE)
注解的功能,通过使用PropertyKey
注解,当我们调用该方法的时候获取到提示(参数 resourceBundle 的值就是上面声明的 BUNDLE),效果如下:

同时键不存在时还会有报错提示:

最后是④,有了以上工具类,调用方式也很简单,第一个参数为信息的键值,如果想要传递参数,则按顺序进行传递即可(第二个参数为可变参数,PropertyKey 注解会解析配置的语言信息,如果调用参数个数不一致也会有信息提示,如下图)。

然后创建一个 Action 用于测试:
kotlin
class TestAction: AnAction() {
override fun actionPerformed(event: AnActionEvent) {
NotificationUtils.info(MessageUtils.message("demo.greet-msg", "butterfly"))
}
}
效果如下:

可以看到这里虽然我们没有进行语言选择的操作,但是显示的内容为中文版本。
NotificationUtils
类是自己定义的工具类,内容如下:
kotlinobject NotificationUtils { fun info(msg: String) { Notifications.Bus.notify(Notification("i18n", msg, NotificationType.INFORMATION)) } }
手动切换语言
在部分情况下我们可能还想手动的去控制语言的选择,只需要使用Locale.setDefault(Locale.ENGLISH)
即可,这里的参数为Locale.ENGLISH
即英语,其它语言按需去改变即可,配置完后,我们再看效果:


可以发现配置生效,展示的信息为英语版本了。
如果调用
Locale.setDefault()
方法传递的语言在我们语言文件中不存在,则会使用默认的语言文件,即没有后缀的语言文件,即ActionBundles.properties
。
总结
在上篇文章的结尾说到这篇文章会介绍 PSI 的进阶内容,不过考虑到使用场景较少,所以这篇文章先介绍了关于 i18n 的相关内容,PSI 的进阶内容则留到后续篇章中再进行介绍。