Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to modify the text used by certain widgets (like DatePickerButton) to allow translation/localization #5360

Open
thmxv opened this issue Nov 8, 2024 · 2 comments

Comments

@thmxv
Copy link

thmxv commented Nov 8, 2024

Using egui in an application supporting multiple languages is possible, but some widgets (only DatePickerButton in my experience) uses text in English and do not provide a method to override the text used.

I suppose a constructor allowing to pass (a reference/borrow to) a DatePickerLabels structure containing all the String to be used. Would be the best/simplest way to provide that. Or some other API that default to the English labels:

let french_labels = egui_extras::DatePickerLabels {
    week: "Semaine".to_string(),
    ...
};
egui_extras::DatePickerButton::new(date).with_labels(&french_labels);

The solution should not be tight to a specific localization/translation framework but generic enough to work with all translation methods possible.

@YgorSouza
Copy link
Contributor

It might be better to just use the existing Memory facilities. That way, third-party widgets could also use the same strings or define their own keys in the same way.

For example, if you had the strings defined in your code like this:

mod fr {
    use std::sync::Arc;

    pub fn january() -> Arc<str> {
        "Janvier".into()
    }
    pub fn february() -> Arc<str> {
        "Fevrier".into()
    }
}

You would insert them into egui's memory whenever the app's language is changed:

// if selected language "fr"
ui.data_mut(|d| d.insert_temp(Id::new("i18n::month::january"), fr::january()));
ui.data_mut(|d| d.insert_temp(Id::new("i18n::month::february"), fr::february()));

And then the widget would get it like this:

let january = ui.data(|d| d.get_temp::<Arc<str>>(Id::new("i18n::month::january")));
ui.label(january.as_deref().unwrap_or("January"));

So for static strings like the names of the days and months, you would only do heap allocations once (or at most once every time the language is changed), and you could override the strings for all widgets in the same way.

Just have to sort out the details of how the Ids are constructed and how they are exposed to the user, to make sure it is ergonomic and performant and avoids collisions between multiple libraries using this system.

@thmxv
Copy link
Author

thmxv commented Nov 9, 2024

Thanks.

I did not even knew about those Memory facilities. So my "best/simplest way" is definitely not something to be interpreted as best or simplest :-/ I definitely think someone with better experience than me should decide which way is the best.

In my code example, tacking a reference to the DatePickerLabels struct was to avoid allocating on each frame. But I suppose it would need a static of some form, and some kind of (lazy) initialization of this static, for the default (English) labels. The use the Memory facilities are probably better.

Apparently the IdTypeMap of the Memory facilities can take a value of any type. Maybe inserting just one value containing all the labels is better, or at least would require less code and less Ids. I do not know, I am just trying to get information on what would be the recommended way to do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants