mondeja / leptos-fluent

Internationalization framework for Leptos using Fluent
https://mondeja.github.io/leptos-fluent/
MIT License
39 stars 10 forks source link

Browser console warning when using the `tr!` macro. #198

Closed SleeplessOne1917 closed 3 months ago

SleeplessOne1917 commented 3 months ago

Whenever I use the tr! macro, I see this warning show up:

At /home/insomnia/.cargo/registry/src/index.crates.io-6f17d22bba15001f/leptos-fluent-0.1.10/src/lib.rs:580:33, you access a signal or memo (defined at src/app.rs:19:5) outside a reactive tracking context. This might mean your app is not responding to changes in signal values in the way you expect.

Here’s how to fix it:

1. If this is inside a `view!` macro, make sure you are passing a function, not a value.
  ❌ NO  <p>{x.get() * 2}</p>
  ✅ YES <p>{move || x.get() * 2}</p>

2. If it’s in the body of a component, try wrapping this access in a closure: 
  ❌ NO  let y = x.get() * 2
  ✅ YES let y = move || x.get() * 2.

3. If you’re *trying* to access the value without tracking, use `.get_untracked()` or `.with_untracked()` instead.

It only seems to happen with the tr! macro. I setup a test project to try this in based off of the leptos-rs/start template. All of the rust code is the same except for app.rs, which is the following:

use fluent_templates::static_loader;
use leptos_fluent::{leptos_fluent, move_tr, tr};
use leptos::*;
use leptos_meta::*;
use leptos_router::*;

static_loader! {
    static TRANSLATIONS = {
        locales: "./locales",
        fallback_language: "en",
    };
}

#[component]
pub fn App() -> impl IntoView {
    // Provides context that manages stylesheets, titles, meta tags, etc.
    provide_meta_context();

    leptos_fluent! {{
        translations: [TRANSLATIONS],
        locales: "./locales",
        check_translations: "./src/**/*.rs",
        sync_html_tag_lang: true,
        initial_language_from_accept_language_header: true,
        cookie_attrs: "SameSite=Strict; Secure;",
        initial_language_from_cookie: true,
        set_language_to_cookie: true,
        initial_language_from_navigator: true
      }};

    view! {
        // injects a stylesheet into the document <head>
        // id=leptos means cargo-leptos will hot-reload this stylesheet
        <Stylesheet id="leptos" href="/pkg/fluent-foo.css"/>

        // sets the document title
        <Title text=tr!("welcome")/>

        // content for this welcome page
        <Router>
            <main>
                <Routes>
                    <Route path="" view=HomePage/>
                    <Route path="/*any" view=NotFound/>
                </Routes>
            </main>
        </Router>
    }
}

/// Renders the home page of your application.
#[component]
fn HomePage() -> impl IntoView {
    // Creates a reactive value to update the button
    let (count, set_count) = create_signal(0);
    let on_click = move |_| set_count.update(|count| *count += 1);

    view! {
        <h1>{tr!("welcome")}</h1>
        <button on:click=on_click>{move_tr!("click-me", { "count" => count.get()})}</button>
    }
}

/// 404 - Not Found
#[component]
fn NotFound() -> impl IntoView {
    // set an HTTP status code 404
    // this is feature gated because it can only be done during
    // initial server-side rendering
    // if you navigate to the 404 page subsequently, the status
    // code will not be set because there is not a new HTTP request
    // to the server
    #[cfg(feature = "ssr")]
    {
        // this can be done inline because it's synchronous
        // if it were async, we'd use a server function
        let resp = expect_context::<leptos_actix::ResponseOptions>();
        resp.set_status(actix_web::http::StatusCode::NOT_FOUND);
    }

    view! {
        <h1>"Not Found"</h1>
    }
}

My main.ftl for English is the following:

welcome = Welcome to Leptos!
click-me = Click Me: { $count }

Let me know if there is any more information I can provide that would be helpful.

mondeja commented 3 months ago

Is the expected behaviour. The message says that you're not in a reactive tracking context, which is exactly happening. If you change the language the translation will not be updated on the fly. Use move_tr!, || tr!, move || tr! or use tr! inside a reactive tracking context by another way.