Scala borrows Java String methods like toUpperCase/toLowerCase.
However, the way it does so is not very consistent:
toUpperCase()
is locale-sensitive and sticks to default locale (giving you infamous i → İ problem in Turkish locale)toUpperCase(Locale.ROOT)
toUpperCase()
works in locale-insensitive mannertoUpperCase(Locale locale)
method is effectively not available in ScalaJSHow do I implement locale-insensitive case conversion that will work in Scala on both JVM/JS?
I can think of several ways, all of them as ugly:
Implement my own toUpperCase
for specifically 26 ASCII characters of English alphabet.
Basically the same, but at least reuse Scala toUpper to convert individual chars.
Implement something like
trait CaseChangeOps {
def toUpperCase(s: String): String
}
object Main {
var caseChanger: CaseChanger
}
// whenever I want to use it, do it like that:
Main.caseChanger.toUpperCase("like this") // => "LIKE THIS"
in shared code, and then in JS have:
object CaseChangerJs {
def toUpperCase(s: String): String = s.toUpperCase
}
object MainJs {
Main.caseChanger = CaseChangerJs
}
... and in JVM:
object CaseChangerJvm {
def toUpperCase(s: String): String = s.toUpperCase(Locale.ROOT)
}
object MainJvm {
Main.caseChanger = CaseChangerJvm
}
There is a distinct 3rd party library scala-java-locales, which is listed as ScalaJS-compatible, and can be used to augument ScalaJS.
Looks like a massive overkill, though, as I literally only need locale-insensitive case conversions, not the whole thing for all possible locales.
Any better ideas?
The standard approach is close to your method 2, but much simpler. In shared code you just call
Platform.toUpperLocaleInsensitive(string)
which has different implementations on JVM and JS:
// JVM
object Platform {
def toUpperLocaleInsensitive(s: String) = s.toUpperCase(Locale.ROOT)
// other methods with different implementations
}
// JS
object Platform {
def toUpperLocaleInsensitive(s: String) = s.toUpperCase()
// other methods with different implementations
}
See the description of a similar case in Hands-on Scala.js.
This works because shared code doesn't need to compile by itself, only together with platform-specific code.