Hey everyone :wave: I’m running into an issue whe...
# multiplatform
a
Hey everyone 👋 I’m running into an issue when trying to display Arabic text on the web using Kotlin Multiplatform. The Arabic text shows up as boxes (missing glyphs or encoding issue) when running on JS/WASM, but it works fine on other platforms (like Android and iOS). Has anyone faced a similar problem or found a way to properly render Arabic characters in Kotlin/JS or Kotlin/WASM? If you know of any helpful blog posts, articles, or documentation that discuss font rendering, Unicode handling, or localization for Arabic in KMP, I’d really appreciate it! 🙏 Thanks in advance!
m
In the generated HTML / CSS / attributes of the Kotlin/JS web entry point, include fallback font families (Arabic fonts). Then, in Compose Web, ensure your text or CSS includes those font families.
a
I try to add throw index.html and styles.css, and not working, so I try to add through code, but still not working. I use a font from composeResources, but nothing is changing
Copy code
fun injectArabicFontSupport() {
    // Preconnect for performance
    val preconnect = document.createElement("link").apply {
        setAttribute("rel", "preconnect")
        setAttribute("href", "<https://fonts.googleapis.com>")
    }

    val preconnectStatic = document.createElement("link").apply {
        setAttribute("rel", "preconnect")
        setAttribute("href", "<https://fonts.gstatic.com>")
        setAttribute("crossorigin", "")
    }

    // Load font stylesheet
    val fontLink = document.createElement("link").apply {
        setAttribute("rel", "stylesheet")
        setAttribute("href",
            "<https://fonts.googleapis.com/css2>?" +
                    "family=Noto+Sans+Arabic:wght@400;500;600;700&" +
                    "family=Roboto:wght@400;500;700&" +
                    "display=swap"
        )
    }

    document.head?.apply {
        appendChild(preconnect)
        appendChild(preconnectStatic)
        appendChild(fontLink)
    }

    // CRITICAL: Force browser text rendering with proper shaping
    val style = document.createElement("style").apply {
        textContent = """
            /* Global font family */
            * {
                font-family: 'Noto Sans Arabic', 'Roboto', -apple-system, 
                             BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
            }
            
            /* CRITICAL: Force proper text rendering and shaping */
            body, div, span, p, h1, h2, h3, h4, h5, h6,
            input, button, textarea, select, label, option {
                /* Enable text shaping */
                text-rendering: optimizeLegibility !important;
                -webkit-font-feature-settings: 'liga', 'kern' !important;
                font-feature-settings: 'liga', 'kern' !important;
                
                /* Force subpixel antialiasing */
                -webkit-font-smoothing: subpixel-antialiased !important;
                -moz-osx-font-smoothing: auto !important;
                
                /* Ensure proper Unicode bidirectional text */
                unicode-bidi: embed !important;
            }
            
            /* Force Skia canvas to use proper text rendering */
            canvas {
                text-rendering: optimizeLegibility !important;
            }
            
            /* RTL support for Arabic */
            [dir="rtl"], [dir="rtl"] * {
                direction: rtl !important;
                text-align: right !important;
                unicode-bidi: embed !important;
            }
            
            /* Specific targeting for Compose canvas elements */
            [style*="position: absolute"] {
                text-rendering: optimizeLegibility !important;
            }
        """.trimIndent()
    }

    document.head?.appendChild(style)

    // Add a script to monitor and fix any dynamically created elements
    val script = document.createElement("script").apply {
        textContent = """
            (function() {
                const observer = new MutationObserver(function(mutations) {
                    mutations.forEach(function(mutation) {
                        mutation.addedNodes.forEach(function(node) {
                            if (node.nodeType === 1) {
                                node.style.textRendering = 'optimizeLegibility';
                            }
                        });
                    });
                });
                
                observer.observe(document.body, {
                    childList: true,
                    subtree: true
                });
            })();
        """.trimIndent()
    }

    document.head?.appendChild(script)

    console.log("✅ Arabic font support injected with text shaping")
}
a
Is the Arabic text rendered by Compose Multiplatform?
a
In web (JS/WASM), not in other platforms, working will.
a
@Oleksandr Karpovich [JB] ^^
🙌 1