compose-multiplatform icon indicating copy to clipboard operation
compose-multiplatform copied to clipboard

String resources for internationalization (i18n)

Open keturn opened this issue 3 years ago • 14 comments

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?

keturn avatar Feb 25 '21 04:02 keturn

Image viewer example has some code for localization.

olonho avatar Feb 26 '21 05:02 olonho

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?

keturn avatar Feb 27 '21 01:02 keturn

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

olonho avatar Mar 05 '21 07:03 olonho

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

olonho avatar Mar 05 '21 07:03 olonho

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.

igordmn avatar Mar 05 '21 09:03 igordmn

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

  • string in the source language
  • a comment from the author about the string (if they need to provide extra context or explanation)
  • a previous translation of the string (when updating a previously-translated application)
  • the new translation of the string, i.e. the translator's input

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.)

keturn avatar Mar 05 '21 18:03 keturn

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

nrobi144 avatar Mar 11 '21 07:03 nrobi144

@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 👍!

igordmn avatar Mar 11 '21 07:03 igordmn

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

nrobi144 avatar Mar 29 '21 11:03 nrobi144

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

kazemcodes avatar May 15 '23 19:05 kazemcodes

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.

MarcusWolschon avatar May 21 '23 16:05 MarcusWolschon

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.

francismariano avatar Oct 02 '23 20:10 francismariano

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

tsuyosh avatar Feb 14 '24 10:02 tsuyosh

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

moten-07 avatar Feb 15 '24 10:02 moten-07

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

okushnikov avatar Jul 14 '24 15:07 okushnikov