I'm trying to import <https://github.com/UUDigital...
# javascript
b
I'm trying to import https://github.com/UUDigitalHumanitieslab/handlebars-i18next but can't figure out how to type the definition. I've tried
Copy code
package com.i18next

import com.handlebarsjs.Handlebars

@JsModule("handlebars-i18next")
@JsNonModule
external fun registerI18nHelper(
    handlebars: Handlebars,
    i18Next: I18Next,
    helperName: String? = definedExternally
)
but that produces handlebars_i18next__WEBPACK_IMPORTED_MODULE_12__ is not a function with or without the @JsNonModule annotation
1
the compiled lib looks like this
Copy code
(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(["exports"], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports);
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports);
    global.handlebarsI18next = mod.exports;
  }
})(this, function (_exports) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports["default"] = _default;
  // These are options to i18n.t that may take array or object values.
  var jsonKeys = ['lngs', 'fallbackLng', 'ns', 'postProcess', 'interpolation']; // Quick polyfill for Object.assign, because IE11 doesn't have that method.

  function extend(target) {
    for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      sources[_key - 1] = arguments[_key];
    }

    sources.forEach(function (source) {
      if (source) for (var key in source) {
        target[key] = source[key];
      }
    });
    return target;
  }

  function _default(Handlebars, i18next) {
    var name = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'i18n';
    Handlebars.registerHelper(name, function (key, _ref) {
      var hash = _ref.hash,
          data = _ref.data,
          fn = _ref.fn;
      var parsed = {};
      jsonKeys.forEach(function (key) {
        if (hash[key]) {
          // Everything in jsonKeys is known not to belong in options.replace.
          // Everything in hash ends up in options.replace, so we limit
          // interpolation replacement polution by transferring these keys
          // to parsed.
          parsed[key] = JSON.parse(hash[key]);
          delete hash[key];
        }
      });
      var options = extend({}, data.root.i18next, hash, parsed, {
        returnObjects: false
      });
      var replace = options.replace = extend({}, this, options.replace, hash);
      delete replace.i18next; // may creep in if this === data.root

      if (fn) options.defaultValue = fn(replace);
      return new Handlebars.SafeString(i18next.t(key, options));
    });
  }

  ;
});

//# sourceMappingURL=handlebars-i18next.js.map
t
Copy code
@file:JsModule("handlebars-i18next")

package handlebarsjs.i18next

import com.handlebarsjs.Handlebars

@JsName("default")
external fun registerI18nHelper(
    handlebars: Handlebars,
    i18Next: I18Next,
    helperName: String? = definedExternally
)
b
@turansky same issue unfortunately
t
Caches?
b
not related to caches
t
Also, please use
target = "es2015"
b
I don't think I can do that
I'm interfacing with es6 classes
same issue btw
t
es2015
- meta property
b
Copy code
kotlin {
    js {
        useEsModules()
        compilerOptions {
            freeCompilerArgs.addAll(
                "-opt-in=kotlin.io.encoding.ExperimentalEncodingApi",
                "-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
                "-opt-in=kotlin.contracts.ExperimentalContracts",
                "-opt-in=kotlin.ExperimentalStdlibApi",
                "-opt-in=kotlin.js.ExperimentalJsExport",
                "-opt-in=kotlin.js.ExperimentalJsStatic",
                "-Xwhen-guards",
            )
            moduleKind = JsModuleKind.MODULE_ES
            useEsClasses = true
        }
        browser {
            @OptIn(ExperimentalDistributionDsl::class)
            distribution {
                outputDirectory = file( "dist")
            }
            webpackTask {
                mainOutputFileName = "main.js"
            }
            testTask {
                useKarma {
                    useFirefoxHeadless()
                }
            }
        }
        binaries.executable() // create a js file
    }
    sourceSets {
        val commonMain by getting {
            resources.srcDirs(
                tasks.named("processTranslations"),
                tasks.named("combineJsonFiles"),
            )
            dependencies {
                implementation(libs.kotlinx.serialization.core)
                implementation(libs.kotlinx.serialization.json)
                implementation(libs.kotlinx.datetime)
                implementation(libs.kotlinx.coroutines)
            }
        }
        val commonTest by getting {
            dependencies {
                implementation(libs.kotlin.test)
            }
        }
        // define a jsMain module
        val jsMain by getting {
            dependencies {
                implementation(project.dependencies.enforcedPlatform(libs.kotlin.wrappers))
                implementation(libs.kotlin.wrappers.js)
                implementation(libs.kotlin.plain.objects)
                implementation(libs.kotlinx.html)
                implementation(libs.kotlinx.coroutines.js)
                implementation(libs.jsonschemavalidator.js)
                implementation(npm("uuid", "11.1.0"))
                implementation(npm("i18next", "24.2.3"))
                implementation(npm("i18next-http-backend", "3.0.2"))
                implementation(npm("i18next-icu", "2.3.0"))
                implementation(npm("intl-messageformat", "10.7.16"))
                implementation(npm("handlebars-i18next", "1.0.3"))
                api(libs.jquery)
            }
        }
        val jsTest by getting {
            dependencies {
                implementation(libs.kotlin.test.js)
            }
        }
    }
}
t
es2015
- meta property = ES classes + ES module + ES generators
b
ah I see
where do I put that?
t
Copy code
kotlin {
    js {
       compilerOptions {
        target = "es2015"
       }
    }
}
b
no success unfortunately
this is what the import gets turned into
Copy code
/* harmony import */ var handlebars_i18next__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! handlebars-i18next */ "../../node_modules/handlebars-i18next/handlebars-i18next.js");
Copy code
handlebars_i18next__WEBPACK_IMPORTED_MODULE_0__(tmp$ret$8, i18next__WEBPACK_IMPORTED_MODULE_10__["default"], 't');
t
Copy code
@file:JsModule("handlebars-i18next")

package handlebarsjs.i18next

import com.handlebarsjs.Handlebars

@JsName("default")
external val registerI18nHelper: Any
+
Copy code
fun main() {
   console.log(registerI18nHelper)
}
Please check following. What you have in console?
b
_{_esModule: true, default: ƒ}
image.png
hm, the function signature might be the issue?
t
Do you copy my declarations?
b
yes
t
Looks like you don't check my examples
b
yep, copied your example again, same issue
t
Copy code
package handlebarsjs.i18next

import com.handlebarsjs.Handlebars

@JsModule("handlebars-i18next")
external val registerI18nHelper: Any
+
Copy code
fun main() {
   console.log(registerI18nHelper)
}
b
image.png
not even typing it as dynamic and calling it works
Copy code
package handlebarsjs.i18next

@JsModule("handlebars-i18next")
external val registerI18nHelper: dynamic
Copy code
registerI18nHelper(window.Handlebars, i18next)
image.png
log in between is window.Handlebars btw
I'm gonna copy paste the JS in and see where that leads
that works
t
Checked on my project
Copy code
@file:JsModule("handlebars-i18next")

package handlebarsjs.i18next

import com.handlebarsjs.Handlebars

@JsName("default")
external fun registerI18nHelper(
    handlebars: Handlebars,
    i18Next: I18Next,
    helperName: String? = definedExternally
)
is what you need
Screenshot 2025-04-11 at 22.23.41.png
It's required function
b
can you paste me your build script?
I've ported the lib in 10 locs to Kotlin, thank you regardless; I suppose it's either my build script or a compiler bug (maybe the distribution setting?)
t
Secret of success - I use Vite 😉
Copy code
package handlebarsjs.i18next

import com.handlebarsjs.Handlebars

@JsModule("handlebars-i18next")
external object registerI18nHelper {
    @JsName("default") 
    operator fun invoke(
       handlebars: Handlebars,
       i18Next: I18Next,
       helperName: String? = definedExternally,
    )
)
Should work for Webpack too 😉
@Bernhard could you please report bug about this problem?
b
@turansky thank you!
will file tomorrow
I'm trying to add an interface to a companion object which uses @JsStatic but it won't let me; what's the correct way to do that?
t
Looks like issue
I also want overrides
b
slack threads break me xD
I keep posting new questions in old threads
🧌 1
sorry 🙂
will move that up
or do you know an existing issue on the issue tracker?
t
No, looks like new issue
b
thank you
t
I hope you extend external interface
b
yep
the idea is to pull out an interface to add extension methods onto
had to resort to a wrapper class