Jetpack構成によるスイッチングロケール


私はすでに記事を発表しましたhow it's important to allow users to switch languages . そうする理由がたくさんある.
さて、カスタム言語の切り替えを実装するためにJetpack Composeでどのようにシンプルにするかを見てみましょう.

アプリを準備する


すべての文字列をres/values/strings.xml そして、あなたがそれらを必要とするたびに、Androidの標準メカニズムを使用してそれらを得るgetString() .
それは翻訳ツールで最高の作品としてベース言語として英語を使用するのが最善です、そしてそれは通常、協力者とボランティアを見つけるのが簡単です.
そして、それはすべてです.他の言語のXMLファイルを気にする必要はありません.そのためのローカライズプラットフォームを使用します.

翻訳を管理する


一度あなたのstrings.xml ファイル準備完了.sign up for Localazy Androidの統合命令に従ってください.それはあなたのルートのとアプリケーションのに追加されるいくつかの行を意味するように単純ですbuild.gradle — ソースコードやリソースを変更する必要はありません.
行う必要があるすべての変更は以下のようになります.
LocalAzyをルートのビルドに追加します.Gradleファイル:
buildscript {

    repositories {
        // ...
        maven { url "https://maven.localazy.com/repository/release/" }
    }

    dependencies {
        // ...
        classpath "com.localazy:gradle:1.5.2"
    }

}
アプリケーションのビルドにlocalazyを追加します.Gradleファイル:
apply plugin: 'com.localazy.gradle'

localazy {
    readKey "your-read-key"
    writeKey "your-write-key"
}
そして、それ!今、あなたはuploadStrings Gradleを使用したタスクコマンドラインで利用できます.
./gradlew uploadStrings
また、Android StudioのGradleビューでも.

その瞬間から、簡単にlocalazyを使用して翻訳を管理することができますし、また、無料で最大80の言語にあなたのアプリケーションの巨大な部分を翻訳する共有翻訳があります.

ハローワールド


Localeスイッチングの仕組みをテストするには、簡単なHello World Appを作成しましょう.
ここでは、画面の中央にレンダリングされた、構成可能なテキスト用のコードが表示されます.
@Composable
fun WelcomeText(text: String) {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .fillMaxHeight(),
        verticalArrangement = Arrangement.Center
    ) {
        Text(
            text = text,
            modifier = Modifier
                .gravity(Alignment.CenterHorizontally)
        )
    }
}
ユーザーが自分の言語を切り替えることができるように、我々はフローティングアクションボタンを使用することができます.我々は、我々の活動にそれを加えて、それに行動を与えることができますSwitchActivity 我々が後で議論すること.
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Scaffold(
                floatingActionButton = {
                    FloatingActionButton(
                        onClick = {
                            startActivity(
                                Intent(this@MainActivity, SwitchActivity::class.java)
                            )
                        },
                        elevation = 10.dp
                    ) {
                        Icon(Icons.Default.Translate)
                    }
                },
                bodyContent = {
                    WelcomeText(text = getString(R.string.welcome_message))
                }
            )
        }
    }

}
画面が期待される.

さて、実装しましょうSwitchActivity .

スイッチング活動


LocalazyのAndroidライブラリは自動的に我々のアプリは、上記のビルドスクリプトのいくつかの行で統合されているので、それが利用可能です.全体documentation for the Localazy Android library is available on the website .
まず、シンプルなラップViewModel 周りのデータを簡単に我々の新しく作成された活動にアクセスできるように.
class LocaleViewModel : ViewModel() {

    private val localazyListener = LocalazyWrappedListener {
        viewModelScope.launch {
            update()
        }
    }

    var locales by mutableStateOf(listOf<LocalazyLocale>())
        private set

    init {
        Localazy.setListener(localazyListener)
        update()
    }

    private fun update() {
        locales = Localazy.getLocales() ?: emptyList()
    }

}
我々はラップLocalazyListener , それで、我々は一つのイベントを聞くためにすべてのオーバーライドを実装する必要はありません.以下は実装です.
/**
 * A simple class to wrap LocalazyListener, so we don't need to implement
 * all functions, and can use a lambda to monitor changes.
 */
class LocalazyWrappedListener(val body: () -> Unit) : LocalazyListener {

    override fun missingTextFound(p0: LocalazyId?, p1: Locale?, p2: String?) {}

    override fun missingKeyFound(p0: Locale?, p1: String?) {}

    override fun stringsUpdateStarted() {}

    /**
     * This function is called when updated data is downloaded.
     */
    override fun stringsUpdateFinished() {
        body()
    }

    override fun stringsUpdateFailed(p0: Int) {}

    override fun stringsUpdateNotNecessary() {}

    /**
     * This function is called when the strings are loaded.
     */
    override fun stringsLoaded(fromUpdate: Boolean, success: Boolean) {
        if (success) {
            body()
        }
    }

}
すごい!それはかなり簡単だった.さて、Jetpackのコンポジブルを使って言語セレクタをレンダリングしましょう.我々が利用可能な言語を示すだけでなく、与えられた言語がまだ完全に翻訳されていないことを示すことができます(それは翻訳者を助けるためにより多くの貢献者とボランティアを引きつけることができて、非常に便利です)、そして、もちろん、我々はlocalazyの上で我々のプロジェクトにユーザーを指す必要もあります.
@Composable
fun LocaleSwitcher(
    items: List<LocalazyLocale>,
    onChange: (LocalazyLocale) -> Unit,
    onHelp: () -> Unit
) {
    Column {
        LazyColumnFor(items = items, modifier = Modifier.padding(0.dp, 8.dp)) {
            TextButton(
                onClick = {
                    onChange(it)
                },
                modifier = Modifier.padding(16.dp, 4.dp, 4.dp, 4.dp).fillMaxWidth()
            ) {
                val name =
                    "${it.localizedName}${if (!it.isFullyTranslated) " (incomplete)" else ""}"
                Text(name)
            }
        }
        TextButton(
            onClick = {
                onHelp()
            },
            modifier = Modifier.padding(16.dp, 12.dp, 4.dp, 4.dp).fillMaxWidth()
        ) {
            Text("Help us translate the app!")
        }
    }
}
我々はすべての準備ができているSwitchActivity . ドラムロールを作りましょう.
class SwitchActivity : AppCompatActivity() {

    private val localeViewModel by viewModels<LocaleViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            LocaleSwitcher(
                items = localeViewModel.locales,
                onChange = {

                    // Change the locale and persist the new choice.
                    Localazy.forceLocale(it.locale, true)

                    // Reopen MainActivity with clearing top.
                    startActivity(
                        Intent(
                            this@SwitchActivity,
                            MainActivity::class.java
                        ).apply {
                            flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
                        }
                    )

                },
                onHelp = {
                    // Open the project on Localazy to allow contributors to help us with translating.
                    startActivity(
                        Intent(Intent.ACTION_VIEW, Localazy.getProjectUri()).apply {
                            flags = Intent.FLAG_ACTIVITY_NEW_TASK
                        }
                    )
                }
            )
        }
    }

}
結果

これは正確に与えられた時間にlocalazyの私のアプリと一致します:

より多くの言語に私のアプリを翻訳するには、私はXMLファイルやソースコードをタッチする必要はありません.すべてはlocalazyを通して管理できます.
更新された翻訳や新しい言語を再利用する必要がなく、既存のユーザーにオンラインで配信されているApp Storeを再生するために提出します.すごい?

ソースコード


あなたは見つけることができますthe whole source code on Github .
この投稿は当初公表されたLocalazy .