JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
15.96k stars 1.16k forks source link

String resources for internationalization (i18n) #425

Closed keturn closed 6 months ago

keturn commented 3 years ago

I'd like to see an example of how to do internationalization for Compose Desktop.

I looked at the Code Viewer example, as it's written to run under both Android and desktop. It doesn't yet address that feature; its Text widgets and contentDescription values are hard-coded, e.g. https://github.com/JetBrains/compose-jb/blob/4de10a649910053ed634429b88c82541989bf332/examples/codeviewer/common/src/commonMain/kotlin/org/jetbrains/codeviewer/ui/editor/EditorEmptyView.kt#L28-L29

Can we use stringResource (from androidx.compose.ui.res) on desktop? How do we get the resource ID if we're developing for desktop and not using Android Studio?

olonho commented 3 years ago

Image viewer example has some code for localization.

keturn commented 3 years ago

Where does R.kt come from?

How does it handle plurals?

Image viewer has a common subproject but then it splits much of its code out in to separate implementations for Android https://github.com/JetBrains/compose-jb/blob/da611b319dfa9cb0141d60ad5687b1771854ec72/examples/imageviewer/common/src/androidMain/kotlin/example/imageviewer/view/MainScreen.kt#L202-L210

and desktop https://github.com/JetBrains/compose-jb/blob/da611b319dfa9cb0141d60ad5687b1771854ec72/examples/imageviewer/common/src/desktopMain/kotlin/example/imageviewer/view/MainScreen.kt#L244-L251

Those look like they're supposed to be doing the same job, but the way they use string resources is entirely different. Can we write a view that will work in either environment?

olonho commented 3 years ago

Generally, while meaningful, not sure if it fully belongs to the UI framework scope.

olonho commented 3 years ago

@igordmn do you have an idea how we could support in MPP manner?

igordmn commented 3 years ago

One of the complex things is pluraziation support.

Java only provides ChoiceFormat, which properly works only with some languages.

Proper pluraziation support implemented in ICU.

We can provide a function for pluralization in skiko (because skia already uses icu library).

Or write a pluralization function in pure Kotlin/Java using patterns (example)

Another thing we need to think about - how string resources should be defined:

  1. We can write strings in pure Kotlin:
val strings = when(Locale.getDefault().language) {
    "en" -> EnStrings
    "ru" -> RuStrings
    else -> EnStrings
}

interface Strings {
    val appName: String get() = "Image viewer"
    val open: String
    fun folderFileCount(count: Int): String
}

object EnStrings : Strings {
    override val open = "Open"
    override fun folderFileCount(count: Int) = "Folder file count: ${fileCount(count)}"

    private fun fileCount(count: Int) = plural(
        count,
        zero = "$count files",
        one = "$count file",
        many = "$count files"
    )
}

object RuStrings : Strings {
    override val open = "Открыть"
    override fun folderFileCount(count: Int) = "Количество файлов в папке: ${fileCount(count)}"

    private fun fileCount(count: Int) = plural(
        count,
        zero = "$count файлов",
        one = "$count файл",
        many = "$count файлов"
    )
}

Don't know if it is a good idea. It maybe convinient for string formatting, but not convinient for translators.

  1. Provide android-like strings.xml. There is MPP implementation Moko resources. But support for JVM target isn't implemented yet. There is PR, but for plurals it uses ChoiceFormat.
keturn commented 3 years ago

It maybe convinient for string formatting, but not convinient for translators.

Yeah. Assume translators and their tools don't know Kotlin at all. Best to have a format that makes it super clear which things are strings to be translated and which aren't.

Using one of the web translation portals or other Computer Assisted Translation tools is going to want to parse it in to something like

A good translation house is used to taking all sorts of inputs and munging them in to something that will work but you'll have more options (and cheaper ones) if you can use an existing format. Especially when you take escaping rules in to account: java .properties and Android's strings.xml have their own peculiar rules about which characters need to be escaped and how, how replacement strings like ${count} are marked, etc.

Generally, while meaningful, not sure if it fully belongs to the UI framework scope.

One question that might help clarify this: Is it a goal to be able to share views like that MainScreen.kt between android and Compose for Desktop?

Or are Compose for Desktop apps really their own thing? Sometimes you might get lucky and be able to use some android-compatible component (because that's one of the benefits of composability), but you expect a desktop app to be written as a desktop app.

I've been more of a desktop dev than a mobile one, but my hunch is that if you want to pitch this as a way to take a design you've written for an Android tablet and use it on a Windows or Wayland touchscreen (or vice-versa), then views will need to be compatible with android's string resources.

(As a desktop dev, android support is of secondary importance to me. But android's i18n tools look far more capable than what we've seen from the JDK, as igordmn pointed out with ChoiceFormat. So when I saw this project talking about bringing androidx.compose APIs to the desktop, I was very keen to know if that included things like androidx.compose.ui.res too.)

nrobi144 commented 3 years ago

@igordmn would migrating to PluralRules or PluralFormat from ChoiceFormat on the Moko-Resources side fix your issue?

igordmn commented 3 years ago

@igordmn would migrating to PluralRules or PluralFormat from ChoiceFormat on the Moko-Resources side fix your issue?

Yes, I think that will fix the issue. Thanks 👍!

nrobi144 commented 3 years ago

@igordmn, @keturn just migrated Moko-Resources from ChoiceFormat to PluralRules -> https://github.com/icerockdev/moko-resources/commit/97489b6e92bc57ae99770fcb2cf0a39033b195b9

kazemcodes commented 1 year ago

moko-resource is good but there is some issue with cache configuration issue , if it was created using ksp then it would be amazing

MarcusWolschon commented 1 year ago

One question that might help clarify this: Is it a goal to be able to share views like that MainScreen.kt between android and Compose for Desktop?

Most certainly YES. That's what I already do and without localization it already works well. So many more possibilities when you get a desktop application nearly for free while developing the Android app.

francismariano commented 11 months ago

This feature is very important for KMP ecosystem. There are others libraries with that goal but they generally have issues with kotlin and/or compose-multiplatform updates.

tsuyosh commented 7 months ago

Is there any plan to support plural in the new resource library?

moten-07 commented 7 months ago

use this ? https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-images-resources.html#resource-usage

okushnikov commented 2 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.