Make ResourceEnvironment public
Problem
Currently, StringResources.getString(...) and ResourceEnvironment are only convenient to use inside a composition. For server-side rendering (SSR) with Kotlin/WasmJS, we need to serve html pages that are SEO-friendly and localized. This requires access to string resources outside composition and the ability to configure a ResourceEnvironment manually.
Proposed Changes
-
ResourceEnvironment
- Made public (
language,region,theme,densitynow publicvals). - Added a
copy(...)helper to allow modification without exposing adata class.
- Made public (
-
StringResources
- Added overloads of
getString(...)that accept aResourceReaderparameter (default:DefaultResourceReader). - This enables reading localized strings outside of composition while keeping composition-aware behavior unchanged.
- Added overloads of
Motivation
- SSR requires rendering UI to HTML on the server, not just in the browser.
- Without these changes, we cannot reliably access localized strings during SSR, leading to incomplete or incorrect rendering.
- The ability to override
ResourceEnvironmentis crucial for generating pages in multiple locales programmatically.
Open Questions
- The current PR only adds support for strings. Should we extend a similar pattern to other resource types (images, fonts, etc.) for consistency?
- Binary compatibility: do we need to preserve exact overloads of the old
getStringsignatures to avoid breaking precompiled binaries?This change allows to access resources outside the composition while also allowing configuring ResourceEnvironment.
The reason behind this change is to simplify the generation of SSR pages for Kotlin/WasmJs while also respecting localization.
Could you file an issue for that? I don't understand why it's implemented for strings only? Where are tests? What is a use case and why it matters? I need more information in the issue on YouTrack
I understand a general idea to override resources' environment, but we have a consensus it should be done globally in the app. https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-resource-environment.html
Moreover, the proposed API opens only a small specific sub-set of non-compose API to read custom strings. If you want the feature, it should be implemented to provide a custom environment for all resource reads.
I updated the PR details. What do you think about it?
I have a few concerns about the changes:
- Compose resources were designed for the Compose only apps. We explicitly avoid to support non-compose scenarios because we don't want to cover such cases and be responsible for them.
- "For server-side rendering (SSR) with Kotlin/WasmJS, we need to serve html pages" sounds like a task not for Compose resources.
- I am against semi-designed half-implemented features. Like only string resources, only for SSR case. Compose Multiplatform resources should support all targets and be designed for a wide set scenarios.
- At the moment I am not focused on CMP resources, and I'm not ready to approve the PR with no deep design.
NB: Compose Web apps are single page apps, for now. I didn't research SSR or other scenarios. So, I couldn't value these changes, might be.
In your specific case I'd recommend to use original xml resources on the backend to render your htmls.