Skip to content
一个可以快速实现多语言切换的 Android 第三方库 An android library with kotlin for fast changing multi-language.
Kotlin
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
demo
gradle/wrapper
media
plugin-locale
.gitignore
LICENSE
README.md
build.gradle
gradle.properties
gradlew
gradlew.bat
settings.gradle

README.md

Plugin-Locale-Kotlin

Android Version Language Releases Download license

An android library with kotlin for changing multi-language.

Only support English/Simplified Chinese/Traditional Chinese, but you can submit issues or contact to me if you need other languages.

Now we support any language but need you to define the connection between language's key and value

一个用 Kotlin 写的多语言切换的 Android 第三方库。

目前只支持英文/简中/繁中三种语言,需要添加其他的语言可以提交 issue 或者直接联系我。

现在我们支持任何一种语言,但是需要你自己定义你要支持的语言列表(Key 与 Value 间的关系),详情请看下方👉注意事项

背景

项目历经9个月的演化,终于从一开始为宝可梦的那样记账研究的语言切换而写的Demo进化成第三方库。

这是我的第一个开源第三方库,说起来还挺激动的(嗯...失眠了...)~

使用文档

引入依赖

plugin-locale

(可选)项目的 build.gradle 中加入:

当 JCenter 无法链接的时候可以尝试使用

allprojects {
    repositories {
        // ...
        maven { url "https://dl.bintray.com/rebornq/maven/" }
    }
}

app.gradle 中加入:

implementation 'com.mallotec.reb:plugin-locale:{last-version}'

注意:{last-version}要替换为最新版本号,最新版本链接:https://bintray.com/rebornq/maven/plugin-locale/_latestVersion

混淆规则

添加混淆规则(可选)

# LocalePlugin 混淆规则
-keep class com.mallotec.reb.localeplugin.** { *; }
-dontwarn com.mallotec.reb.localeplugin.**

只需三步即可食用

  1. 在 Application 中初始化

    LocalePlugin.init(this)

    LocalePlugin.init(this, { 刷新界面的方式 })

    其中{ 刷新界面的方式 }有三种:

    1. LocaleConstant.RESTART_TO_LAUNCHER_ACTIVITY: 清空栈中所有Activity并重启到LauncherActivity
    2. LocaleConstant.RECREATE_CURRENT_ACTIVITY: 重新创建当前Activity默认是这种方式,可不填写此方式可能会因为内存低无法注销广播接收器而导致内存泄漏,解决方法请查看下方👉常见问题👉Wiki
    3. LocaleConstant.CUSTOM_WAY_TO_UPDATE_INTERFACE: 自定义刷新界面, 如果选这种方式的朋友请务必查看下方👉更多用法👉Wiki
  2. 定义好支持的语言列表对应关系,详情请看下方👉注意事项,如:

    private fun getLocale(which : String): Locale {
        return when (which) {
            "0" -> Locale.ROOT  // 跟随系统
            "1" -> Locale.ENGLISH
            "2" -> Locale.SIMPLIFIED_CHINESE
            "3" -> Locale.TRADITIONAL_CHINESE
            else -> Locale.SIMPLIFIED_CHINESE
        }
    }
  3. 一句代码调用切换语言:

    // 应用切换的语言
    LocaleHelper.getInstance()
        .language(getLocale(which.toString()))
        .apply(this)

    { 刷新界面的方式 }选择了第一种LocaleConstant.RESTART_TO_LAUNCHER_ACTIVITY,请使用下面的方式:

    // 应用切换的语言
    val intent = Intent(this, TargetActivity::class.java)
    LocaleHelper.getInstance()
        .language(getLocale(which.toString()))
        .apply(this, intent)

    { 刷新界面的方式 }选择了第三种LocaleConstant.CUSTOM_WAY_TO_UPDATE_INTERFACE,请使用下面的方式:

    上面有写,查看下方👉更多用法👉Wiki

    注意:这里的this必须是当前ActivityContextwhich是所选的语言标记,详情请看下方注意事项的对应关系

注意事项

SharePreferenceslanguage字段的value与 App 语言的对应关系

对应关系如下:

V1.0.10 前的版本
"0" -> 跟随系统
"1" -> English
"2" -> 简体中文
"3" -> 繁体中文
V1.0.10+

新版本兼容获取旧版本的值,但是设置的时候会重新set新的值,放心,绝对平稳过渡

新版本对应关系需要自己定义(必须做这一步!!!),这样就可以自己定义支持什么语言了,举例:

private fun getLocale(which : String): Locale {
    return when (which) {
        "0" -> Locale.ROOT  // 跟随系统
        "1" -> Locale.ENGLISH
        "2" -> Locale.SIMPLIFIED_CHINESE
        "3" -> Locale.TRADITIONAL_CHINESE
        else -> Locale.SIMPLIFIED_CHINESE
    }
}

然后再一句代码调用切换语言:

// 应用切换的语言
LocaleHelper.getInstance()
    .language(getLocale(which.toString()))
    .apply(this)

说明:通常,which为语言列表的第几项。当然,你也可以不定义0/1/2/3,你可以定义auto/en/zh_cn/zh_tw注意:若要做跟随系统,此项对应关系的value必须为Locale.ROOT

Demo

效果图(默认第二种刷新界面方式)

MultiLanguageDemo-NoRestartToLaunche

更多请查看本项目的 Demo

更多用法

更多用法请转战 Wiki🚪传送门

~~第三方 Activity 库适配指南(V1.0.9后已不再需要适配)~~

以下内容并非不再需要适配的原因,仅保留用作笔记

对于切换语言后一定不在返回栈中的Activity,不必做适配。 这是因为App内所有界面共享同一个Locale,切换后Locale变了,新启动的Activity用上新的Context已经是切换后的Locale。所以其实返回栈中的Locale也变了,只是界面资源没有刷新。

自定义切换语言后刷新界面的方式

自定义切换语言后刷新界面的方式

首先,下面是几个初始化刷新界面方式的常量:

LocaleConstant.RESTART_TO_LAUNCHER_ACTIVITY -> 重启到主页(非重启 AppLocaleConstant.RECREATE_CURRENT_ACTIVITY -> 重启已经打开的 Activity
LocaleConstant.CUSTOM_WAY_TO_UPDATE_INTERFACE -> 自己实现刷新界面的方式

插件默认初始化为LocaleConstant.RECREATE_CURRENT_ACTIVITY,若要自己实现,需要使用前先在Application初始化插件:

LocalePlugin.init(this, LocaleConstant.CUSTOM_WAY_TO_UPDATE_INTERFACE)

初始化过后,在切换语言的界面实现ActivityHelper.OnUpdateInterfaceListener接口、设置监听器,然后在接口方法体内写自己想要实现的刷新界面逻辑,如:

class SettingActivity : AppCompatActivity(), ActivityHelper.OnUpdateInterfaceListener {

    @SuppressLint("StringFormatInvalid")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_settings)
        ...
        // 设置监听器
        ActivityHelper.getInstance().setOnUpdateInterfaceListener(this)
    }

    override fun updateInterface(context: Context, intent: Intent?) {
        // TODO: To write your way to update interface
        Toast.makeText(context, intent?.getStringExtra("Test"), Toast.LENGTH_LONG).show()
    }
}

然后在切换语言的时候调用:

// 应用切换的语言
LocaleHelper.getInstance()
    .language(which.toString())
    .apply(this@SettingActivity, intent, ActivityUtil)

举例:

val intent = Intent(this, MainActivity::class.java)
intent.putExtra("Test", getString(R.string.activity_custom_refresh_way_test))
LocaleHelper.getInstance()
    .language(which.toString())
    .apply(this@SettingActivity, intent, ActivityUtil)

常见问题

切换语言失效原因及解决方法

AndroidX AppCompat 库 1.1.0-alpha03 以上版本导致的 Locale 被一个新的 Configuration 对象覆盖掉

AndroidX AppCompat 库 1.1.0-alpha03 以上版本导致的 Locale 被一个新的 Configuration 对象覆盖掉

仅写出解决方法,本demo经测试无法复现问题

Activity中加入以下代码即可:

// 防止 Locale 被一个新的 Configuration 对象覆盖掉(AndroidX AppCompat 库 1.1.0-alpha03 以上版本)
override fun applyOverrideConfiguration(overrideConfiguration: Configuration?) {
    overrideConfiguration?.setLocale(LocaleHelper.getInstance().getSetLocale())
    super.applyOverrideConfiguration(overrideConfiguration)
}

内存泄漏原因及解决方法

Activity 对象被回收时还没来得及执行 onDestroy() 方法导致没注销对应的广播接收器引发的内存泄漏

Activity 对象被回收时还没来得及执行 onDestroy() 方法导致没注销对应的广播接收器引发的内存泄漏

这种情况常见于内存低的时候Activity被强制回收,不走onDestroy()方法导致的。

遇到这种情况的朋友请自行判断内存低即将回收Activity的地方(onTrimMemory()?),

然后手动调用以下代码注销广播接收器:

BroadcastReceiverManager.unregisterBroadcastReceiver(activity)

写在最后

欢迎大家 Star、Fork 和提 Issue 提 PR 呀~

Thanks

以下不分排名先后

You can’t perform that action at this time.