Kotlin 中的国际化 (i18n):完整指南及示例
国际化 (i18n) 是设计和开发软件的过程,使其能够适应不同的语言和地区,而无需修改源代码。在 Kotlin 生态系统中,无论是 Android 应用、基于 Ktor 的服务器项目,还是使用 Kotlin Multiplatform 的多平台解决方案,正确实现 i18n 对于产品的全球成功至关重要。在本文中,我们将介绍 Kotlin 应用程序国际化的主要方法、工具和最佳实践。
为什么 i18n 在 Kotlin 中很重要?
Kotlin 作为一种现代语言,与 Java 完全兼容,继承了 Java 用于本地化的所有功能,同时也提供了自己独特的解决方案。正确的国际化可以:
- 显著扩大应用程序的用户群
- 改善不同语言使用者的用户体验
- 遵守不同国家的法律要求(例如,涉及货币或日期格式)
- 简化未来添加新语言的过程
Kotlin 中 i18n 的主要方法
1. 使用 Resource Bundle(Java 兼容方法)
最常见且简单的方法是使用标准的 ResourceBundle 和属性文件 (.properties)。此方法非常适合 Kotlin 中的控制台应用程序和服务器项目。
// messages_en.propertiesgreeting=Hello, {0}!farewell=Goodbye
// messages_ru.propertiesgreeting=Привет, {0}!farewell=До свиданияimport java.util.ResourceBundleimport java.text.MessageFormat
fun main() { val bundle = ResourceBundle.getBundle("messages", Locale("ru")) val greeting = MessageFormat.format(bundle.getString("greeting"), "Мир") println(greeting) // 输出:Привет, Мир! println(bundle.getString("farewell")) // 输出:До свидания}2. 使用扩展函数的 Kotlin 特定方法
Kotlin 允许使用扩展函数和委托属性创建更简洁、更安全的本地化 API。
import java.util.*import kotlin.properties.ReadOnlyPropertyimport kotlin.reflect.KProperty
class I18n(private val baseName: String) { private val bundle: ResourceBundle get() = ResourceBundle.getBundle(baseName) operator fun provideDelegate( thisRef: Any?, prop: KProperty<*> ): ReadOnlyProperty { return ReadOnlyProperty { _, _ -> bundle.getString(prop.name) } }}
object Strings { val i18n = I18n("messages") val greeting by i18n val farewell by i18n}
fun main() { // 自动使用系统区域设置 println(Strings.greeting) // 输出属性文件中的相应值 println(Strings.farewell)} Kotlin 中的本地化工具
1. Kotlin Multiplatform (KMP) 和 expect/actual
对于多平台项目,Kotlin 提供了强大的 expect/actual 机制,允许声明通用的 i18n API,并为每个平台单独实现。
// 在通用代码中 (commonMain)expect class PlatformStringResources { fun getString(key: String, vararg args: Any?): String}
// 在 Android 中 (androidMain)actual class PlatformStringResources { private val context: Context = // 获取上下文 actual fun getString(key: String, vararg args: Any?): String { val resId = context.resources.getIdentifier(key, "string", context.packageName) return context.getString(resId, *args) }}
// 在 iOS 中 (iosMain)actual class PlatformStringResources { actual fun getString(key: String, vararg args: Any?): Str