dioxus-community / dioxus-i18n

i18n (localization) support for all Dioxus apps and renderers
MIT License
17 stars 3 forks source link

Is dioxus-i18n compatible with fullstack? #20

Closed webhype closed 4 weeks ago

webhype commented 4 weeks ago

I added some internationalization to my fullstack web app, and it compiles fine, but panics at runtime with:

calledResult::unwrap()on anErrvalue: RuntimeError

Here's my compiler output: $ dx serve --verbose --trace --platform web

... lots of compilation logging
16:01:27 [cargo]        Fresh axum_session_auth v0.12.1
16:01:27 [cargo]        Fresh dx v0.1.0 (/Users/macuser/mm/dx)
16:01:27 [cargo]     Finished `server-dev` profile [unoptimized + debuginfo] target(s) in 0.52s
16:01:27 [dev] Build completed successfully - output location: "/Users/macuser/mm/dx/target/server-dev/dx"
16:01:27 [dev] Collecting assets ...
16:01:27 [dev] Assembling app bundle
16:01:27 [dev] Running wasm-bindgen
16:01:30 [dev] wasm-bindgen complete in 3.18727075s
16:01:30 [dev] Copying server executable to: "/Users/macuser/mm/dx/target/dx/dx/debug/web/server" BuildArtifacts {
    exe: "/Users/macuser/mm/dx/target/server-dev/dx",
    assets: AssetManifest {
        assets: {
            "/Users/macuser/mm/dx/public/pexels-peng-louis-587527-1643457.jpg": BundledAsset {
                absolute_source_path: "/Users/macuser/mm/dx/public/pexels-peng-louis-587527-1643457.jpg",
                bundled_path: "pexels-peng-louis-587527-1643457-ad0d3993c9c9204b.avif",
                options: Image(
                    ImageAssetOptions {
                        ty: Avif,
                        low_quality_preview: false,
                        size: Manual {
                            width: 200,
                            height: 200,
                        },
                        preload: false,
                    },
                ),
            },
            "/Users/macuser/mm/dx/public/loading.css": BundledAsset {
                absolute_source_path: "/Users/macuser/mm/dx/public/loading.css",
                bundled_path: "loading-0b2cb454eeff38a5.css",
                options: Unknown,
            },
            "/Users/macuser/mm/dx/public/favicon.ico": BundledAsset {
                absolute_source_path: "/Users/macuser/mm/dx/public/favicon.ico",
                bundled_path: "favicon-78763c6c4cb3a95e.ico",
                options: Unknown,
            },
            "/Users/macuser/mm/dx/public/heroicons-24-outline/globe-alt.svg": BundledAsset {
                absolute_source_path: "/Users/macuser/mm/dx/public/heroicons-24-outline/globe-alt.svg",
                bundled_path: "globe-alt-612787905510bdf0.svg",
                options: Unknown,
            },
            "/Users/macuser/mm/dx/public/tailwind.css": BundledAsset {
                absolute_source_path: "/Users/macuser/mm/dx/public/tailwind.css",
                bundled_path: "tailwind-a22448bfff6b22a5.css",
                options: Unknown,
            },
        },
    },
    time_taken: 1.274279792s,
}
16:01:30 [dev] Removing old assets
16:01:31 [dev] Copying asset "/Users/macuser/mm/dx/public/favicon.ico" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/favicon-78763c6c4cb3a95e.ico"
16:01:31 [dev] Copying asset "/Users/macuser/mm/dx/public/loading.css" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/loading-0b2cb454eeff38a5.css"
16:01:31 [dev] Copying asset "/Users/macuser/mm/dx/public/tailwind.css" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/tailwind-a22448bfff6b22a5.css"
16:01:31 [dev] Copying asset "/Users/macuser/mm/dx/public/heroicons-24-outline/globe-alt.svg" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/globe-alt-612787905510bdf0.svg"
16:01:31 [dev] Copying asset "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/wasm-bindgen/dx.js" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/dx-15060f7b14c535dd.js"
16:01:31 [dev] Copying asset "/Users/macuser/mm/dx/public/pexels-peng-louis-587527-1643457.jpg" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/pexels-peng-louis-587527-1643457-ad0d3993c9c9204b.avif"
16:01:31 [dev] Copying asset "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/wasm-bindgen/dx_bg.wasm" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/dx_bg-d64528b118ee8fb3.wasm"
16:01:31 [dev] Copying legacy asset "/Users/macuser/mm/dx/public/favicon.ico" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/favicon.ico"
16:01:31 [dev] Copying legacy asset "/Users/macuser/mm/dx/public/.DS_Store" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/.DS_Store"
16:01:31 [dev] Copying legacy asset "/Users/macuser/mm/dx/public/tailwind.css" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/tailwind.css"
16:01:31 [dev] Copying legacy asset "/Users/macuser/mm/dx/public/heroicons-24-outline" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/heroicons-24-outline"
16:01:31 [dev] Copying legacy asset "/Users/macuser/mm/dx/public/loading.css" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/loading.css"
16:01:31 [dev] Copying legacy asset "/Users/macuser/mm/dx/public/pexels-peng-louis-587527-1643457.jpg" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/pexels-peng-louis-587527-1643457.jpg"
16:01:31 [dev] Copying legacy asset "/Users/macuser/mm/dx/public/i18n" to "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/assets/i18n"
16:01:31 [dev] Starting asset copy 11/14 from "/Users/macuser/mm/dx/public/loading.css"
16:01:31 [dev] Starting asset copy 3/14 from "/Users/macuser/mm/dx/public/heroicons-24-outline"
16:01:31 [dev] Starting asset copy 0/14 from "/Users/macuser/mm/dx/public/favicon.ico"
16:01:31 [dev] Starting asset copy 2/14 from "/Users/macuser/mm/dx/public/heroicons-24-outline/globe-alt.svg"
16:01:31 [dev] Starting asset copy 8/14 from "/Users/macuser/mm/dx/public/pexels-peng-louis-587527-1643457.jpg"
16:01:31 [dev] Starting asset copy 5/14 from "/Users/macuser/mm/dx/public/pexels-peng-louis-587527-1643457.jpg"
16:01:31 [dev] Starting asset copy 10/14 from "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/wasm-bindgen/dx_bg.wasm"
16:01:31 [dev] Starting asset copy 9/14 from "/Users/macuser/mm/dx/public/i18n"
16:01:31 [dev] Starting asset copy 4/14 from "/Users/macuser/mm/dx/public/.DS_Store"
16:01:31 [dev] Starting asset copy 7/14 from "/Users/macuser/mm/dx/public/loading.css"
16:01:31 [dev] Starting asset copy 1/14 from "/Users/macuser/mm/dx/public/favicon.ico"
16:01:31 [dev] Starting asset copy 6/14 from "/Users/macuser/mm/dx/public/tailwind.css"
16:01:31 [dev] Starting asset copy 12/14 from "/Users/macuser/mm/dx/public/tailwind.css"
16:01:31 [dev] Starting asset copy 13/14 from "/Users/macuser/mm/dx/target/dx/dx/debug/web/public/wasm-bindgen/dx.js"
16:01:31 [dev] Bundle created at /Users/macuser/mm/dx/target/dx/dx/debug/web/public
16:01:31 [dev] Build completed successfully in 1153ms, launching app! 💫
16:01:31 [dev] Proxying fullstack server from port 192.168.0.190:58928
16:01:31 [dev] Launching server from path: "/Users/macuser/mm/dx/target/dx/dx/debug/web/server"
16:01:31 [dev] Sending reload to toast
16:01:31 [server] thread 'main' panicked at /Users/macuser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/dioxus-hooks-0.6.2/src/use_context.rs:66:5:
16:01:31 [server] called `Result::unwrap()` on an `Err` value: RuntimeError
16:01:31 [server] stack backtrace:
16:01:31 [server]    0: rust_begin_unwind
16:01:31 [server]              at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/std/src/panicking.rs:665:5
16:01:31 [server]    1: core::panicking::panic_fmt
16:01:31 [server]              at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/panicking.rs:74:14
16:01:31 [server]    2: core::result::unwrap_failed
16:01:31 [server]              at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/result.rs:1700:5
16:01:31 [server]    3: core::result::Result<T,E>::unwrap
16:01:31 [server]              at /Users/macuser/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/result.rs:1104:23
16:01:31 [server]    4: dioxus_core::global_context::use_hook
16:01:31 [server]              at /Users/macuser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/dioxus-core-0.6.3/src/global_context.rs:302:5
16:01:31 [server]    5: dioxus_hooks::use_context::use_context_provider
16:01:31 [server]              at /Users/macuser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/dioxus-hooks-0.6.2/src/use_context.rs:66:5
16:01:31 [server]    6: dioxus_i18n::use_i18n::use_init_i18n
16:01:31 [server]              at /Users/macuser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/dioxus-i18n-0.4.2/src/use_i18n.rs:243:5
16:01:31 [server]    7: dx::main
16:01:31 [server]              at ./src/main.rs:68:3
16:01:31 [server]    8: core::ops::function::FnOnce::call_once
16:01:31 [server]              at /Users/macuser/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
16:01:31 [server] note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
16:01:31 [dev] Application [web] exited with error: exit status: 101

One way that I found to avoid this (by trial and error) was to conditionally compile all mentions of dioxus-i18n, like so:

pub fn NavBar() -> Element {
    #[cfg(feature = "web")]
    let mut i18n: I18n = i18n();
    rsx! {
        ul {
            li { class: "mb-8",
                Link {
                    onclick: move |_| {
                        #[cfg(feature = "web")]
                        i18n.set_language(langid!("en-US"));
                    },
                    to: Route::Home {},
                    "Switch to English"
                }
            }
            li { class: "mb-8",
                // ... other languages
            }
        }
    } 
}

However, when I do so, there's no "reactivity" going on any more (i.e. the Link shown isn't clickable and doesn't switch the language as expected.

It seems that the panic happens in main() when calling use_init_i18n(), here's how I initialize dioxus-i18n:

fn main() {
    // Set the logger ahead of time since we don't use `dioxus::launch` on the server
    dioxus::logger::initialize_default();

    use_init_i18n(|| {
        I18nConfig::new(langid!("en-US"))
            .with_locale((langid!("en-US"), include_str!("../public/i18n/en-US.ftl")))
            .with_locale((langid!("es-ES"), include_str!("../public/i18n/es-ES.ftl")))
            .with_locale((langid!("pt-BR"), include_str!("../public/i18n/pt-BR.ftl")))
            .with_locale((langid!("de-DE"), include_str!("../public/i18n/de-DE.ftl")))
    });

    #[cfg(feature = "web")]
    // Hydrate the application on the client
    dioxus_web::launch::launch_cfg(app, dioxus_web::Config::new().hydrate(true));

    #[cfg(feature = "server")]
    {
        use crate::auth::*;
        use axum::routing::*;
        // ... server stuff ...
    }
}

What am I missing?

marc2332 commented 4 weeks ago

use_init_i18n is a hook, and therefore you can only call it in Dioxus components. Instead of calling it in your main function, do it in your root compoennt (app)

webhype commented 4 weeks ago

Brilliant, worked like a charm, and makes so much sense lol. The use_ prefix should have given me the hint lol. Thank you for the lighning-fast response!

Can dioxus-i18n be used on server side as well for example to translate text for SSG or SSR pages?

I'm a beginner in Dioxus; the boundaries between what is "web" (client) and what is "server" aren't always clear to me yet.

marc2332 commented 4 weeks ago

Can dioxus-i18n be used on server side as well for example to translate text for SSG or SSR pages?

I think so, but I must admit I haven't tried it myself, so maybe there is some edge case that I am not aware of. But in theory it should work just fine, its just components at the end of the day

😄