comahe-de / i18n4k

Internationalization for Kotlin
Apache License 2.0
78 stars 9 forks source link

Question regarding the global i18n4k object #48

Closed trentkan closed 11 months ago

trentkan commented 11 months ago

Hello,

I'm trying to test my common function in the nodeJs environment to use server-side in a JS app. I noticed the I18n4kDefault implementation made reference to the window object here when I relied on the default, so I created a CustomConfig that overrode the locale.

class LinkBuilder {
    fun hello(locale: String): String {
        setLocale(locale)
        return Messages.hello
    }

    private fun setLocale(locale: String) {
        val localeSplit = locale.split('_').toTypedArray();
        val newLocale = Locale(localeSplit[0], localeSplit[1])
        val i18n4kConfig = I18n4kConfigDelegateObject(CustomI18nConfig(newLocale));
        i18n4k = i18n4kConfig
    }
}

class CustomI18nConfig(override val locale: Locale): I18n4kConfig {
    override val defaultLocale = Locale("en", "US")
    override val messageFormatter = MessageFormatterDefault
    override val treadBlankStringAsNull = false
}

I don't get an error for trying to access window when building the i18n4kConfig now as I'm not relying on the default. However, it seems to still get hung up on the window object reference when I set i18n4k to my custom config.

I'm not quite sure why it's falling back to the default object, but it is. Do I need to set the global object? From the README, I'm a bit confused why we need this line.

trentkan commented 11 months ago

Stack trace if helpful:

ReferenceError: window is not defined
ReferenceError: window is not defined
    at <global>._init_properties_Locale_kt__dhcc6y(~/i18n4k/i18n4k-core/src/jsMain/kotlin/de/comahe/i18n4k/Locale.kt:27)
    at <global>.get_systemLocale(kotlin/i18n4k-i18n4k-core.js:1831)
    at <global>.new I18n4kConfigDefault(~/i18n4k/i18n4k-core/src/commonMain/kotlin/de/comahe/i18n4k/config/I18n4kConfigDefault.kt:24)
    at <global>._init_properties_I18n4k_kt__k748j9(~/i18n4k/i18n4k-core/src/commonMain/kotlin/de/comahe/i18n4k/I18n4k.kt:7)
    at <global>.set_i18n4k(~/kotlin/i18n4k-i18n4k-core.js:208)
    at <global>.setLocale(src/commonMain/kotlin/Test.kt:22)

It seems like it has something to do with how the global object is set.

comahe-de commented 11 months ago

Hi @trentkan, From you stack-trace I see that in this line from the Locale module, where systemLocale is defined, window is referenced: https://github.com/comahe-de/i18n4k/blob/master/i18n4k-core/src/jsMain/kotlin/de/comahe/i18n4k/Locale.kt#L27

And I18n4kConfigDefault references to systemLocale.

As the Locale class is essential, you cannot replace it.

I was not aware that window is not always available. I will make a try-catch around.

Meanwhile, you may try this workaround: https://stackoverflow.com/a/46908295/2611134 Using the "global"-lib: https://www.npmjs.com/package/global

trentkan commented 11 months ago

Ah, I trace that now. So anytime I create a Locale in JS, it will reference window when it sets systemLocale...

That being said, can we follow a similar implementation as in Java - that is, to check for presence of window.navigator.language, otherwise fall back to default.

or perhaps just remove the concept of systemLocale and use english for localeRef consistency?

comahe-de commented 11 months ago

Added the fix and a nodeJS test without browser which triggered the fix.

You may check the PR #50

trentkan commented 11 months ago

Thank you @comahe-de. I will check this out