From b4422bffc46d21adf85180c6f1033e0a55c2a894 Mon Sep 17 00:00:00 2001 From: Kamil Jarosz Date: Thu, 29 Aug 2024 22:51:29 +0200 Subject: [PATCH] desktop: Add LocalizableText struct This structure allows specifying localizable text when there's no locale available, but it will be available in the future (e.g. when rendering). It has several advantages over specifying bare labels: 1. labels cannot be easily mixed with non-localizable text, 2. it's easy to find labels in use by looking for enum variant usages. It's also better than providing a function of locale which requires complicated type definitions and dynamic dispatch. --- desktop/src/gui.rs | 16 ++++++++++++++++ desktop/src/gui/dialogs/open_dialog.rs | 21 ++++++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/desktop/src/gui.rs b/desktop/src/gui.rs index 09bf6e422..adcd39c28 100644 --- a/desktop/src/gui.rs +++ b/desktop/src/gui.rs @@ -77,6 +77,22 @@ pub fn text_with_args<'a, T: AsRef>( }) } +pub enum LocalizableText { + #[allow(dead_code)] + NonLocalizedText(Cow<'static, str>), + LocalizedText(&'static str), +} + +impl LocalizableText { + pub fn localize(&self, locale: &LanguageIdentifier) -> Cow<'_, str> { + match self { + LocalizableText::NonLocalizedText(Cow::Borrowed(text)) => Cow::Borrowed(text), + LocalizableText::NonLocalizedText(Cow::Owned(text)) => Cow::Borrowed(text), + LocalizableText::LocalizedText(id) => text(locale, id), + } + } +} + /// Size of the top menu bar in pixels. /// This is the offset at which the movie will be shown, /// and added to the window size if trying to match a movie. diff --git a/desktop/src/gui/dialogs/open_dialog.rs b/desktop/src/gui/dialogs/open_dialog.rs index d1b4fb21b..4d39836d5 100644 --- a/desktop/src/gui/dialogs/open_dialog.rs +++ b/desktop/src/gui/dialogs/open_dialog.rs @@ -1,6 +1,6 @@ use crate::custom_event::RuffleEvent; use crate::gui::widgets::PathOrUrlField; -use crate::gui::{text, FilePicker}; +use crate::gui::{text, FilePicker, LocalizableText}; use crate::player::LaunchOptions; use egui::{ emath, Align2, Button, Checkbox, ComboBox, Grid, Layout, Slider, TextEdit, Ui, Widget, Window, @@ -158,7 +158,7 @@ impl OpenDialog { } }), ), - Box::new(|locale| text(locale, "align-force")), + LocalizableText::LocalizedText("align-force"), false, ), ); @@ -189,10 +189,10 @@ impl OpenDialog { StageScaleMode::ExactFit => Some(text(locale, "scale-mode-exactfit-tooltip")), StageScaleMode::NoBorder => Some(text(locale, "scale-mode-noborder-tooltip")), })), - Box::new(|locale| text(locale, "scale-mode-force")), + LocalizableText::LocalizedText("scale-mode-force"), false, ) - .with_checkbox_tooltip(Box::new(|locale| text(locale, "scale-mode-force-tooltip"))), + .with_checkbox_tooltip(LocalizableText::LocalizedText("scale-mode-force-tooltip")), ); let load_behavior = OptionalField::new( defaults.player.load_behavior, @@ -729,7 +729,6 @@ impl InnerField for NumberField { type ValueToTextFn = dyn Fn(T, &LanguageIdentifier) -> Cow<'static, str>; type ValueToOptTextFn = dyn Fn(T, &LanguageIdentifier) -> Option>; -type LabelFn = dyn Fn(&LanguageIdentifier) -> Cow<'static, str>; struct EnumDropdownField { id: egui::Id, @@ -827,13 +826,13 @@ impl InnerField for BooleanDropdownField { struct FieldWithCheckbox { field: T, - checkbox_label: Box, + checkbox_label: LocalizableText, checkbox_default: bool, - tooltip_label: Option>, + tooltip_label: Option, } impl FieldWithCheckbox { - pub fn new(field: T, checkbox_label: Box, checkbox_default: bool) -> Self { + pub fn new(field: T, checkbox_label: LocalizableText, checkbox_default: bool) -> Self { Self { field, checkbox_label, @@ -842,7 +841,7 @@ impl FieldWithCheckbox { } } - pub fn with_checkbox_tooltip(mut self, tooltip_label: Box) -> Self { + pub fn with_checkbox_tooltip(mut self, tooltip_label: LocalizableText) -> Self { self.tooltip_label = Some(tooltip_label); self } @@ -858,9 +857,9 @@ impl InnerField for FieldWithCheckbox { fn ui(&self, ui: &mut Ui, value: &mut Self::Value, error: bool, locale: &LanguageIdentifier) { self.field.ui(ui, &mut value.0, error, locale); - let response = ui.checkbox(&mut value.1, (self.checkbox_label)(locale)); + let response = ui.checkbox(&mut value.1, self.checkbox_label.localize(locale)); if let Some(ref tooltip_label) = self.tooltip_label { - response.on_hover_text_at_pointer(tooltip_label(locale)); + response.on_hover_text_at_pointer(tooltip_label.localize(locale)); } }