Skip to main content

ravenrs_widgets/
labels.rs

1//! The words the built-in components show or read aloud, in one place.
2
3use std::fmt::Write as _;
4
5use ravenrs_app_i18n::{Language, Texts, format_with};
6
7use crate::context::{BuildCx, NodeId};
8use crate::date::Date;
9use crate::grid::Summary;
10use crate::recurrence::{Frequency, RecurrenceEnd, RecurrenceRule};
11use crate::view::View;
12
13/// The words the built-in components use. Start from [`Labels::default`]
14/// (English) or [`Labels::pt_br`], change what you need, and give it to
15/// [`Localized`].
16#[derive(Clone, Debug)]
17#[non_exhaustive]
18#[cfg_attr(feature = "live", ravenrs_live::expose(part = "fields"))]
19pub struct Labels {
20    /// Closes a dialog or a sheet.
21    pub close: String,
22    /// The name of a [`HelpTip`](crate::HelpTip), before what it explains.
23    pub help: String,
24    /// A sidebar's name.
25    pub navigation: String,
26    /// A sidebar trigger's name.
27    pub toggle_sidebar: String,
28    /// Dismisses a toast.
29    pub dismiss: String,
30    /// A [`Chat`](crate::Chat)'s send button.
31    pub send: String,
32    /// A [`Chat`](crate::Chat)'s button to hear an answer.
33    pub listen: String,
34    /// A [`TreeView`](crate::TreeView)'s name.
35    pub tree_name: String,
36    /// Before the tag a [`TagBox`](crate::TagBox) button takes off.
37    pub tag_remove: String,
38    /// A [`ColorPicker`](crate::ColorPicker)'s panel.
39    pub pick_color: String,
40    /// A [`ColorPicker`](crate::ColorPicker) with no color.
41    pub no_color: String,
42    /// The shade square of a [`ColorPicker`](crate::ColorPicker).
43    pub color_shade: String,
44    /// The hue bar of a [`ColorPicker`](crate::ColorPicker).
45    pub color_hue: String,
46    /// The opacity bar of a [`ColorPicker`](crate::ColorPicker).
47    pub color_alpha: String,
48    /// The typed color of a [`ColorPicker`](crate::ColorPicker).
49    pub color_hex: String,
50    /// A [`DateRangePicker`](crate::DateRangePicker) with no period.
51    pub pick_date_range: String,
52    /// Where a candle of a [`Chart`](crate::Chart) opened.
53    pub candle_open: String,
54    /// The highest a candle of a [`Chart`](crate::Chart) went.
55    pub candle_high: String,
56    /// The lowest a candle of a [`Chart`](crate::Chart) went.
57    pub candle_low: String,
58    /// Where a candle of a [`Chart`](crate::Chart) closed.
59    pub candle_close: String,
60    /// What a [`SankeyChart`](crate::SankeyChart) says when its flows go in a circle,
61    /// before the names of the nodes.
62    pub sankey_cycle: String,
63    /// A [`VirtualList`](crate::VirtualList)'s name.
64    pub list_name: String,
65    /// A [`Filmstrip`](crate::Filmstrip)'s name.
66    pub filmstrip_name: String,
67    /// A [`PagedDocumentView`](crate::PagedDocumentView)'s name.
68    pub document_name: String,
69    /// A page of a [`PagedDocumentView`](crate::PagedDocumentView), before its number.
70    pub page_word: String,
71    /// Between a page's number and the total, such as `" of "`.
72    pub page_of: String,
73    /// Goes to the previous page of a [`PagedDocumentView`](crate::PagedDocumentView).
74    pub previous_page: String,
75    /// Goes to the next page of a [`PagedDocumentView`](crate::PagedDocumentView).
76    pub next_page: String,
77    /// A [`FileBrowser`](crate::FileBrowser)'s name.
78    pub file_browser_name: String,
79    /// The column of names of a [`FileBrowser`](crate::FileBrowser).
80    pub file_name: String,
81    /// The column of sizes of a [`FileBrowser`](crate::FileBrowser).
82    pub file_size: String,
83    /// An [`AttachmentStrip`](crate::AttachmentStrip)'s name.
84    pub attachments: String,
85    /// Takes a file out of an [`AttachmentStrip`](crate::AttachmentStrip), before its name.
86    pub attachment_remove: String,
87    /// How a file will be sent, with `{what}` for the way chosen.
88    pub attachment_send_as: String,
89    /// A [`SelectionBar`](crate::SelectionBar)'s name.
90    pub selection_bar: String,
91    /// Leaves a selection.
92    pub selection_exit: String,
93    /// What a [`SelectionBar`](crate::SelectionBar) says with nothing chosen.
94    pub selection_none: String,
95    /// What a [`SelectionBar`](crate::SelectionBar) says with one thing chosen.
96    pub selection_one: String,
97    /// What a [`SelectionBar`](crate::SelectionBar) says with more, with `{count}`.
98    pub selection_many: String,
99    /// The name of an [`AudioPlayerButton`](crate::AudioPlayerButton)'s progress.
100    pub audio_player: String,
101    /// Plays a recording.
102    pub audio_play: String,
103    /// Stops a recording.
104    pub audio_stop: String,
105    /// A recording is on its way.
106    pub audio_loading: String,
107    /// Shows or hides what was said in a recording.
108    pub audio_transcript: String,
109    /// Asks for what was said in a recording.
110    pub audio_transcribe: String,
111    /// What was said in a recording is on its way.
112    pub audio_transcribing: String,
113    /// A recording with no one speaking.
114    pub audio_no_speech: String,
115    /// A photo in a [`Chat`](crate::Chat) with no description.
116    pub chat_photo: String,
117    /// A photo in a [`Chat`](crate::Chat) is on its way.
118    pub chat_photo_loading: String,
119    /// Opens a file in a [`Chat`](crate::Chat), with `{what}` for what it is.
120    pub chat_open: String,
121    /// The column of dates of a [`FileBrowser`](crate::FileBrowser).
122    pub file_modified: String,
123    /// What a [`FileBrowser`](crate::FileBrowser) says of a folder.
124    pub folder_word: String,
125    /// What a [`FileBrowser`](crate::FileBrowser) shows in a folder with nothing in it.
126    pub folder_empty: String,
127    /// A [`YearView`](crate::YearView)'s button to the year before.
128    pub previous_year: String,
129    /// A [`YearView`](crate::YearView)'s button to the year after.
130    pub next_year: String,
131    /// What a [`YearView`](crate::YearView) says of a marked day without words of its own.
132    pub day_marked: String,
133    /// A [`SortableList`](crate::SortableList)'s name.
134    pub sortable_name: String,
135    /// How to move a row of a [`SortableList`](crate::SortableList) from the keyboard.
136    pub sortable_hint: String,
137    /// What is announced after a reorder. `{position}` and `{total}` are filled in.
138    pub moved_to: String,
139    /// A [`DocumentTabs`](crate::DocumentTabs)' name.
140    pub document_tabs_name: String,
141    /// A [`DockArea`](crate::DockArea)'s name.
142    pub dock_area_name: String,
143    /// The name of the tabs of a group of a [`DockArea`](crate::DockArea).
144    pub dock_tabs_name: String,
145    /// What a [`DockArea`](crate::DockArea) says with nothing in its center.
146    pub dock_empty: String,
147    /// The left dock of a [`DockArea`](crate::DockArea), in a menu.
148    pub dock_left: String,
149    /// The right dock of a [`DockArea`](crate::DockArea), in a menu.
150    pub dock_right: String,
151    /// The bottom dock of a [`DockArea`](crate::DockArea), in a menu.
152    pub dock_bottom: String,
153    /// The center of a [`DockArea`](crate::DockArea), in a menu.
154    pub dock_center: String,
155    /// The item of a [`DockArea`](crate::DockArea)'s menu that opens where a panel can go.
156    pub dock_move_to: String,
157    /// Joins a group of a [`DockArea`](crate::DockArea), with `{title}` for what shows in it.
158    pub dock_with: String,
159    /// Opens a group to the right of a panel's own in a [`DockArea`](crate::DockArea).
160    pub dock_split_right: String,
161    /// Opens a group below a panel's own in a [`DockArea`](crate::DockArea).
162    pub dock_split_below: String,
163    /// Closes a panel of a [`DockArea`](crate::DockArea), in a menu.
164    pub dock_close: String,
165    /// The item of a [`DockArea`](crate::DockArea)'s menu that lists closed panels.
166    pub dock_reopen: String,
167    /// The button that closes a panel, with `{title}`.
168    pub dock_close_panel: String,
169    /// The button with a panel's menu, with `{title}`.
170    pub dock_options: String,
171    /// Collapses a dock, with `{place}`.
172    pub dock_hide: String,
173    /// Brings a dock back, with `{place}`.
174    pub dock_show: String,
175    /// The bar that resizes a dock, with `{place}`.
176    pub dock_resize: String,
177    /// The bar between two parts of a split, with `{first}` and `{second}`.
178    pub dock_resize_pair: String,
179    /// What is announced after a panel moved, with `{place}`.
180    pub dock_moved: String,
181    /// What is announced after a panel closed, with `{title}`.
182    pub dock_closed: String,
183    /// Closes a tab of a [`DocumentTabs`](crate::DocumentTabs).
184    pub close_tab: String,
185    /// Opens a new tab of a [`DocumentTabs`](crate::DocumentTabs).
186    pub new_tab: String,
187    /// Closes the other tabs of a [`DocumentTabs`](crate::DocumentTabs).
188    pub close_other_tabs: String,
189    /// Closes the tabs to the right in a [`DocumentTabs`](crate::DocumentTabs).
190    pub close_tabs_to_right: String,
191    /// What a [`DocumentTabs`](crate::DocumentTabs) says of a document with unsaved changes.
192    pub unsaved: String,
193    /// Goes to the previous step of a [`Wizard`](crate::Wizard).
194    pub wizard_back: String,
195    /// Goes to the next step of a [`Wizard`](crate::Wizard).
196    pub wizard_next: String,
197    /// Ends a [`Wizard`](crate::Wizard).
198    pub wizard_finish: String,
199    /// Leaves a [`Wizard`](crate::Wizard).
200    pub wizard_cancel: String,
201    /// A step of a [`Wizard`](crate::Wizard) already done.
202    pub wizard_done: String,
203    /// A step of a [`Wizard`](crate::Wizard) or a [`StepIndicator`](crate::StepIndicator) with a problem.
204    pub wizard_error: String,
205    /// The bar between two panes, for screen readers.
206    pub split_resize: String,
207    /// What dragging a [`FloatingPanel`](crate::FloatingPanel) by its header does.
208    pub panel_move: String,
209    /// Reduces a [`FloatingPanel`](crate::FloatingPanel) to its header.
210    pub panel_minimize: String,
211    /// Brings back a reduced [`FloatingPanel`](crate::FloatingPanel).
212    pub panel_restore: String,
213    /// The arrow of a [`ScrollEdgeArrow`](crate::ScrollEdgeArrow) toward the start.
214    pub scroll_back: String,
215    /// The arrow of a [`ScrollEdgeArrow`](crate::ScrollEdgeArrow) toward the end.
216    pub scroll_forward: String,
217    /// The minimize button of a [`TitleBar`](crate::TitleBar).
218    pub window_minimize: String,
219    /// The maximize button of a [`TitleBar`](crate::TitleBar).
220    pub window_maximize: String,
221    /// The same button of a [`TitleBar`](crate::TitleBar) when the window is maximized.
222    pub window_restore: String,
223    /// Names a [`ValueSlider`](crate::ValueSlider) that was not given a label.
224    pub value_adjust: String,
225    /// Names the field of an [`InlineRename`](crate::InlineRename) that was not given a label.
226    pub rename: String,
227    /// How to start an [`InlineRename`](crate::InlineRename), for screen readers.
228    pub rename_hint: String,
229    /// What a [`FileUpload`](crate::FileUpload) asks for.
230    pub file_drop: String,
231    /// Opens the chooser of a [`FileUpload`](crate::FileUpload).
232    pub file_choose: String,
233    /// Takes a file off.
234    pub file_remove: String,
235    /// Why a file was refused.
236    pub file_wrong_kind: String,
237    /// Why a file was refused.
238    pub file_too_large: String,
239    /// Why a file was refused.
240    pub file_too_many: String,
241    /// Opens the chooser of an [`ImageField`](crate::ImageField).
242    pub image_choose: String,
243    /// Opens the chooser of an [`ImageField`](crate::ImageField) that has a picture.
244    pub image_replace: String,
245    /// An [`ImageField`](crate::ImageField) with no picture.
246    pub image_none: String,
247    /// A file an [`ImageField`](crate::ImageField) cannot show.
248    pub image_invalid: String,
249    /// The handle that moves a tile of a [`TileLayout`](crate::TileLayout).
250    pub tile_move: String,
251    /// The handle that resizes a tile of a [`TileLayout`](crate::TileLayout).
252    pub tile_resize: String,
253    /// A [`CardView`](crate::CardView)'s name.
254    pub cards_name: String,
255    /// Opens the details of a row of a [`DataGrid`](crate::DataGrid).
256    pub grid_expand_row: String,
257    /// Closes the details of a row of a [`DataGrid`](crate::DataGrid).
258    pub grid_collapse_row: String,
259    /// What an option of a [`TagBox`](crate::TagBox) says when it adds what was typed, where `{0}`
260    /// is what was typed. [`Labels::tag_add`] fills it in.
261    pub tag_add: String,
262    /// Where a [`Wizard`](crate::Wizard) stands, where `{0}` is its step and `{1}` its count.
263    /// [`Labels::wizard_progress`] fills it in.
264    pub wizard_progress: String,
265    /// The language and region of numbers and dates in files, such as `pt-BR`.
266    pub culture: String,
267    /// A spinner's name.
268    pub loading: String,
269    /// A stepper's minus button.
270    pub decrease: String,
271    /// A stepper's plus button.
272    pub increase: String,
273    /// The error of an empty [`FormField`](crate::FormField) marked as required.
274    pub required: String,
275    /// A date picker with no date.
276    pub pick_date: String,
277    /// A combobox with no choice.
278    pub select: String,
279    /// A combobox's search field.
280    pub search: String,
281    /// A combobox's search that found nothing.
282    pub no_results: String,
283    /// A command palette's field.
284    pub search_commands: String,
285    /// A command palette's search that found nothing.
286    pub no_commands: String,
287    /// A command palette's name.
288    pub command_palette: String,
289    /// A theme switcher's name.
290    pub theme: String,
291    /// The dark theme.
292    pub theme_dark: String,
293    /// The light theme.
294    pub theme_light: String,
295    /// The glass theme.
296    pub theme_glass: String,
297    /// A theme editor's group: backgrounds and borders.
298    pub theme_surfaces: String,
299    /// A theme editor's group: the colors of text.
300    pub theme_text: String,
301    /// A theme editor's group: the accent.
302    pub theme_accent: String,
303    /// A theme editor's group: colors that say how something went.
304    pub theme_status: String,
305    /// A theme editor's group: corners.
306    pub theme_shape: String,
307    /// A theme editor's group: the sizes of text.
308    pub theme_sizes: String,
309    /// Goes back to the theme as it came.
310    pub theme_restore: String,
311    /// Copies what changed in a theme.
312    pub theme_copy: String,
313    /// Takes tokens that were copied.
314    pub theme_paste: String,
315    /// What was pasted is not tokens of a theme.
316    pub theme_invalid: String,
317    /// How many tokens changed: none, one, and more, where `{0}` is how many.
318    /// [`Labels::theme_changed`] picks and fills it in.
319    pub theme_changed: [String; 3],
320    /// A contrast, where `{0}` is the ratio and `{1}` the token it is measured over.
321    /// [`Labels::theme_contrast`] fills it in.
322    pub theme_contrast: String,
323    /// A code block's copy button.
324    pub copy: String,
325    /// A code block's copy button, right after copying.
326    pub copied: String,
327    /// The list of versions in a [`ReleaseNotes`](crate::ReleaseNotes).
328    pub release_versions: String,
329    /// Goes to the next newer version in a [`ReleaseNotes`](crate::ReleaseNotes).
330    pub release_newer: String,
331    /// Goes to the next older version in a [`ReleaseNotes`](crate::ReleaseNotes).
332    pub release_older: String,
333    /// Between the position and the total, as in "2 of 5".
334    pub release_of: String,
335    /// The diagnostics panel's title.
336    pub diagnostics: String,
337    /// The button that starts a performance test.
338    pub diagnostics_test: String,
339    /// A performance test is running.
340    pub diagnostics_testing: String,
341    /// What to do while a performance test runs.
342    pub diagnostics_testing_detail: String,
343    /// A performance test found the app fluid.
344    pub diagnostics_test_good: String,
345    /// A performance test found visible stutter.
346    pub diagnostics_test_fair: String,
347    /// A performance test found the app slow.
348    pub diagnostics_test_poor: String,
349    /// After the rate a performance test measured.
350    pub diagnostics_test_fps: String,
351    /// A performance test found nothing to blame.
352    pub diagnostics_test_cause_none: String,
353    /// Diagnostics panel: title of the picture of the latest frames.
354    pub diagnostics_timeline: String,
355    /// Diagnostics panel: under it, what the colors and the line mean.
356    pub diagnostics_timeline_detail: String,
357    /// Diagnostics panel: why the views ran again.
358    pub diagnostics_why: String,
359    /// Diagnostics panel: nothing ran again.
360    pub diagnostics_why_none: String,
361    /// Diagnostics panel: the names of the causes, in the order of `BuildCause::ALL`.
362    pub diagnostics_causes: [String; 10],
363    /// Diagnostics panel: the views that cost the most.
364    pub diagnostics_views: String,
365    /// Diagnostics panel: what splits the draw calls.
366    pub diagnostics_batches: String,
367    /// Diagnostics panel: the GPU's resources and memory.
368    pub diagnostics_memory: String,
369    /// Diagnostics panel: the button that copies a capture of the frames.
370    pub diagnostics_copy_trace: String,
371    /// A performance test blames drawing.
372    pub diagnostics_test_cause_gpu: String,
373    /// A performance test blames building the screen.
374    pub diagnostics_test_cause_interface: String,
375    /// Diagnostics: frames are drawn on the CPU.
376    pub diagnostics_software: String,
377    /// What drawing on the CPU means, and what to do about it.
378    pub diagnostics_software_detail: String,
379    /// Diagnostics: the app was built without optimizations.
380    pub diagnostics_unoptimized: String,
381    /// What a build without optimizations means, and what to do about it.
382    pub diagnostics_unoptimized_detail: String,
383    /// Diagnostics: GPUs left out because their drivers are not conformant.
384    pub diagnostics_hidden: String,
385    /// Diagnostics: no GPU could be used.
386    pub diagnostics_no_gpu: String,
387    /// Diagnostics: the time of a whole frame.
388    pub diagnostics_frame: String,
389    /// Diagnostics: the time spent rebuilding and laying out the UI.
390    pub diagnostics_update: String,
391    /// Diagnostics: the time spent waiting for a texture to draw on.
392    pub diagnostics_acquire: String,
393    /// Diagnostics: the time spent recording and submitting GPU work.
394    pub diagnostics_render: String,
395    /// Diagnostics: the button that opens a new bug report in the browser.
396    pub diagnostics_report_bug: String,
397    /// Diagnostics: the title of what a bug report would share.
398    pub diagnostics_report_shares: String,
399    /// Diagnostics: what a bug report would share and that nothing is sent yet.
400    pub diagnostics_report_shares_detail: String,
401    /// Diagnostics: the browser could not be opened for a bug report.
402    pub diagnostics_report_failed: String,
403    /// What to do about the browser not opening.
404    pub diagnostics_report_failed_detail: String,
405    /// The start of a new bug report: the questions for the person to answer.
406    pub diagnostics_report_questions: String,
407    /// After a report cut short to fit in a URL.
408    pub diagnostics_report_truncated: String,
409    /// A calendar's back button.
410    pub previous_month: String,
411    /// A calendar's forward button.
412    pub next_month: String,
413    /// Marks today in a calendar.
414    pub today: String,
415    /// Sunday to Saturday, short, as a calendar's columns.
416    pub weekdays: [String; 7],
417    /// January to December.
418    pub months: [String; 12],
419    /// Between a month and its year, such as `" "` or `" de "`.
420    pub month_year: String,
421    /// How people here write a date, for a date picker, where `{0}` is the day and `{1}` the month
422    /// with two digits, `{2}` the year, `{3}` the day as it is and `{4}` the month in three letters.
423    /// [`Labels::short_date`] fills it in.
424    pub short_date: String,
425    /// Above the errors that keep a form from being saved.
426    pub form_errors: String,
427    /// A [`LookupField`](crate::LookupField)'s button that empties it.
428    pub clear: String,
429    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: all of these.
430    pub filter_all: String,
431    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: any of these.
432    pub filter_any: String,
433    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: how lines combine.
434    pub filter_match: String,
435    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: condition.
436    pub filter_add_condition: String,
437    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: group.
438    pub filter_add_group: String,
439    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: remove.
440    pub filter_remove: String,
441    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: field.
442    pub filter_field: String,
443    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: comparison.
444    pub filter_comparison: String,
445    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: value.
446    pub filter_value: String,
447    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: expression.
448    pub filter_expression: String,
449    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: yes.
450    pub filter_yes: String,
451    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: no.
452    pub filter_no: String,
453    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: is.
454    pub filter_equal: String,
455    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: is not.
456    pub filter_not_equal: String,
457    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: greater than.
458    pub filter_greater: String,
459    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: at least.
460    pub filter_greater_or_equal: String,
461    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: less than.
462    pub filter_less: String,
463    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: at most.
464    pub filter_less_or_equal: String,
465    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: contains.
466    pub filter_contains: String,
467    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: starts with.
468    pub filter_starts_with: String,
469    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: is empty.
470    pub filter_is_empty: String,
471    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: is not empty.
472    pub filter_is_not_empty: String,
473    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: is any of.
474    pub filter_any_of: String,
475    /// A [`FilterBuilder`](crate::FilterBuilder)'s word: is none of.
476    pub filter_none_of: String,
477    /// A [`Ribbon`](crate::Ribbon)'s name.
478    pub ribbon: String,
479    /// A [`Ribbon`](crate::Ribbon)'s search box.
480    pub ribbon_search: String,
481    /// Keeps a [`Ribbon`](crate::Ribbon) open.
482    pub ribbon_pin: String,
483    /// Folds a [`Ribbon`](crate::Ribbon).
484    pub ribbon_collapse: String,
485    /// A [`Carousel`](crate::Carousel)'s button back.
486    pub carousel_previous: String,
487    /// A [`Carousel`](crate::Carousel)'s button forward.
488    pub carousel_next: String,
489    /// A [`Carousel`](crate::Carousel)'s dot, before its number.
490    pub carousel_slide: String,
491    /// An [`InputOtp`](crate::InputOtp)'s name.
492    pub verification_code: String,
493    /// A question's button that gives up on it.
494    pub cancel: String,
495    /// Before the word a [`ConfirmDialog`](crate::ConfirmDialog) asks to be typed.
496    pub confirm_by_typing: String,
497    /// The menu of commands that did not fit.
498    pub more_commands: String,
499    /// A number's decimal separator.
500    pub decimal_separator: char,
501    /// A number's thousands separator.
502    pub group_separator: char,
503    /// A [`TimePicker`](crate::TimePicker)'s hint and button.
504    pub pick_time: String,
505    /// A number field's button that adds a step.
506    pub step_up: String,
507    /// A number field's button that takes a step away.
508    pub step_down: String,
509    /// After the count of events an [`EventCalendar`](crate::EventCalendar) day has no room for.
510    pub calendar_more: String,
511    /// The header over a [`Scheduler`](crate::Scheduler)'s resources.
512    pub scheduler_resources: String,
513    /// Zooms a scheduler's time axis in.
514    pub zoom_in: String,
515    /// Zooms a scheduler's time axis out.
516    pub zoom_out: String,
517    /// A [`Histogram`](crate::Histogram)'s name.
518    pub histogram: String,
519    /// What a [`Histogram`](crate::Histogram) says when a channel piles up at its low end.
520    pub histogram_clipped_low: String,
521    /// What a [`Histogram`](crate::Histogram) says when a channel piles up at its high end.
522    pub histogram_clipped_high: String,
523    /// A [`Ruler`](crate::Ruler)'s name.
524    pub ruler: String,
525    /// A [`ColorWheel`](crate::ColorWheel)'s name.
526    pub color_wheel: String,
527    /// The distance from gray on a [`ColorWheel`](crate::ColorWheel).
528    pub color_saturation: String,
529    /// A [`CurveEditor`](crate::CurveEditor)'s name.
530    pub curve_editor: String,
531    /// One point of a [`CurveEditor`](crate::CurveEditor), before its position in the list.
532    pub curve_point: String,
533    /// After the number of points of a [`CurveEditor`](crate::CurveEditor).
534    pub curve_points: String,
535    /// The horizontal value of a point of a [`CurveEditor`](crate::CurveEditor).
536    pub curve_input: String,
537    /// The vertical value of a point of a [`CurveEditor`](crate::CurveEditor).
538    pub curve_output: String,
539    /// A [`ZoomControl`](crate::ZoomControl)'s name.
540    pub zoom: String,
541    /// Shows the whole content, in a [`ZoomControl`](crate::ZoomControl).
542    pub zoom_fit: String,
543    /// What the 1:1 button of a [`ZoomControl`](crate::ZoomControl) is called by screen readers.
544    pub zoom_actual: String,
545    /// A [`ZoomPanView`](crate::ZoomPanView)'s name.
546    pub zoom_view: String,
547    /// A [`Minimap`](crate::Minimap)'s name.
548    pub minimap: String,
549    /// A [`RubberBand`](crate::RubberBand)'s name.
550    pub rubber_band: String,
551    /// A [`Marquee`](crate::Marquee)'s name.
552    pub marquee: String,
553    /// A [`TransformHandles`](crate::TransformHandles)'s name.
554    pub transform: String,
555    /// A [`CropOverlay`](crate::CropOverlay)'s name.
556    pub crop: String,
557    /// A [`Protractor`](crate::Protractor)'s name.
558    pub protractor: String,
559    /// An [`Eyedropper`](crate::Eyedropper)'s name.
560    pub eyedropper: String,
561    /// What an [`Eyedropper`](crate::Eyedropper)'s tooltip says.
562    pub eyedropper_hint: String,
563    /// An armed [`EyedropperArea`](crate::EyedropperArea)'s name.
564    pub eyedropper_area: String,
565    /// A [`CompareView`](crate::CompareView)'s name.
566    pub compare: String,
567    /// The caption over the first picture of a [`CompareView`](crate::CompareView).
568    pub compare_first: String,
569    /// The caption over the second picture of a [`CompareView`](crate::CompareView).
570    pub compare_second: String,
571    /// An [`ImageLightbox`](crate::ImageLightbox)'s name, for a picture with no caption.
572    pub lightbox: String,
573    /// Goes to the previous picture of an [`ImageLightbox`](crate::ImageLightbox).
574    pub lightbox_previous: String,
575    /// Goes to the next picture of an [`ImageLightbox`](crate::ImageLightbox).
576    pub lightbox_next: String,
577    /// Which picture an [`ImageLightbox`](crate::ImageLightbox) is showing, where `{0}` is which
578    /// and `{1}` how many. [`Labels::lightbox_counter`] fills it in.
579    pub lightbox_counter: String,
580    /// A recurrence editor's name.
581    pub recurrence_name: String,
582    /// Once, daily, weekly, monthly and yearly, as an editor offers them.
583    pub recurrence_frequencies: [String; 5],
584    /// Before the interval, such as "Every".
585    pub recurrence_every: String,
586    /// The singular and plural of day, week, month and year.
587    pub recurrence_units: [(String, String); 4],
588    /// A rule repeating every day, week, month and year, in words.
589    pub recurrence_each: [String; 4],
590    /// What says when a rule stops.
591    pub recurrence_ends_name: String,
592    /// Never, on a date and after a number of times, as an editor offers them.
593    pub recurrence_ends: [String; 3],
594    /// After the number of times.
595    pub recurrence_times: String,
596    /// Before the last day, in words.
597    pub recurrence_until: String,
598    /// Before the next days, in words.
599    pub recurrence_next: String,
600    /// What a grid's group panel says while nothing is grouped.
601    pub grid_drag_hint: String,
602    /// Before a column a grid is grouped by.
603    pub grid_grouped_by: String,
604    /// Stops grouping a grid by a column.
605    pub grid_remove_group: String,
606    /// Opens every group of a grid.
607    pub grid_expand_all: String,
608    /// Closes every group of a grid.
609    pub grid_collapse_all: String,
610    /// Sorts a grid's column from smallest to largest.
611    pub grid_sort_ascending: String,
612    /// Sorts a grid's column from largest to smallest.
613    pub grid_sort_descending: String,
614    /// Stops sorting by a grid's column.
615    pub grid_clear_sort: String,
616    /// Groups a grid by a column.
617    pub grid_group_by_column: String,
618    /// Stops grouping a grid by a column, in its menu.
619    pub grid_ungroup_column: String,
620    /// Keeps a grid's column in place.
621    pub grid_pin_column: String,
622    /// Lets a grid's column scroll again.
623    pub grid_unpin_column: String,
624    /// Hides a grid's column.
625    pub grid_hide_column: String,
626    /// Fits a grid's column to its content.
627    pub grid_fit_column: String,
628    /// Shows a grid's group panel.
629    pub grid_show_panel: String,
630    /// Hides a grid's group panel.
631    pub grid_hide_panel: String,
632    /// Opens a grid's column menu.
633    pub grid_column_menu: String,
634    /// Filters a grid's column by its values.
635    pub grid_filter_values: String,
636    /// Removes a grid's filters.
637    pub grid_clear_filter: String,
638    /// The text of an [`ExpressionEditor`](crate::ExpressionEditor).
639    pub expression_text: String,
640    /// The search field of an [`ExpressionEditor`](crate::ExpressionEditor).
641    pub expression_search: String,
642    /// Puts the chosen item into an [`ExpressionEditor`](crate::ExpressionEditor) at the caret.
643    pub expression_insert: String,
644    /// An [`ExpressionEditor`](crate::ExpressionEditor) whose text has no problem.
645    pub expression_valid: String,
646    /// Where a syntax error is, with `{line}` and `{column}` in it.
647    pub expression_error_at: String,
648    /// Before the names an [`ExpressionEditor`](crate::ExpressionEditor) does not know.
649    pub expression_unknown: String,
650    /// What an [`ExpressionEditor`](crate::ExpressionEditor) says when nothing matches the search.
651    pub expression_no_match: String,
652    /// The groups of an [`ExpressionEditor`](crate::ExpressionEditor), in order: fields,
653    /// parameters, logical, text, math, date and time, reporting and aggregate functions,
654    /// operators and constants.
655    pub expression_groups: [String; 10],
656    /// The operators an [`ExpressionEditor`](crate::ExpressionEditor) lists: what it inserts
657    /// and what it does.
658    pub expression_operators: Vec<(String, String)>,
659    /// The constants an [`ExpressionEditor`](crate::ExpressionEditor) lists: what it inserts
660    /// and what it is.
661    pub expression_constants: Vec<(String, String)>,
662    /// Before what a grid is filtering by.
663    pub grid_filter_label: String,
664    /// Opens the editor of a grid's whole filter.
665    pub grid_edit_filter: String,
666    /// Every value of a grid's column, in its filter.
667    pub grid_all_values: String,
668    /// A grid's menu of saved arrangements.
669    pub grid_scenario: String,
670    /// Saves how a grid is arranged, under a new name.
671    pub grid_scenario_save: String,
672    /// Saves over the scenario in use.
673    pub grid_scenario_update: String,
674    /// Deletes the scenario in use.
675    pub grid_scenario_delete: String,
676    /// Puts a grid back as it first was.
677    pub grid_scenario_original: String,
678    /// What to call a scenario.
679    pub grid_scenario_name: String,
680    /// Confirms a new scenario.
681    pub grid_save: String,
682    /// Before how many rows a grid has per page.
683    pub grid_rows_per_page: String,
684    /// Asks a server for a grid's rows again.
685    pub grid_try_again: String,
686    /// Before a page's number in a grid's pager.
687    pub grid_page: String,
688    /// A grid's pager goes back.
689    pub grid_previous: String,
690    /// A grid's pager goes on.
691    pub grid_next: String,
692    /// Opens the editor of a column's summary.
693    pub grid_edit_summary: String,
694    /// Before the column whose summary is being edited.
695    pub grid_summary_of: String,
696    /// No summary for a column.
697    pub grid_summary_none: String,
698    /// A column's summary from a formula.
699    pub grid_summary_formula: String,
700    /// What a formula looks like.
701    pub grid_formula_hint: String,
702    /// Before what a formula comes to.
703    pub grid_formula_result: String,
704    /// Where a formula could not be worked out.
705    pub grid_formula_error: String,
706    /// Before the columns a formula can use.
707    pub grid_formula_columns: String,
708    /// Before the functions a formula can use.
709    pub grid_formula_functions: String,
710    /// Puts a formula to use.
711    pub grid_apply: String,
712    /// A grid's search field.
713    pub grid_search: String,
714    /// A grid's grouping menu.
715    pub grid_group: String,
716    /// Removes a grid's grouping.
717    pub grid_clear_grouping: String,
718    /// A grid's column menu.
719    pub grid_columns: String,
720    /// Puts a grid's sorting and filters back.
721    pub grid_reset: String,
722    /// A grid's export button.
723    pub grid_export: String,
724    /// A grid's menu of file formats.
725    pub grid_export_file: String,
726    /// A data grid's button that adds a row.
727    pub grid_add_row: String,
728    /// A data grid's button that removes the selected rows.
729    pub grid_delete_rows: String,
730    /// A grid with nothing to show.
731    pub grid_no_rows: String,
732    /// A grid's name.
733    pub grid_name: String,
734    /// A row's check box.
735    pub grid_select_row: String,
736    /// A column sorted up.
737    pub grid_sorted_ascending: String,
738    /// A column sorted down.
739    pub grid_sorted_descending: String,
740    /// A text column's filter hint.
741    pub grid_filter_hint: String,
742    /// A number column's filter hint.
743    pub grid_number_filter_hint: String,
744    /// Before a column's name, in its filter's name.
745    pub grid_filter_column: String,
746    /// A group with no value.
747    pub grid_empty: String,
748    /// Between shown and total rows.
749    pub grid_of: String,
750    /// After the row count.
751    pub grid_rows: String,
752    /// After the count of selected rows.
753    pub grid_selected: String,
754    /// What a [`Rating`](crate::Rating) is called when nothing says what is rated.
755    pub rating: String,
756    /// Where a [`Rating`](crate::Rating) stands, where `{0}` is its score and `{1}` its maximum.
757    /// [`Labels::rating_value`] fills it in.
758    pub rating_value: String,
759    /// A [`DaySeparator`](crate::DaySeparator) for the day before today.
760    pub yesterday: String,
761    /// The title of a [`ShortcutSheet`](crate::ShortcutSheet).
762    pub shortcut_sheet: String,
763    /// What a [`FavoriteToggle`](crate::FavoriteToggle) is called when nothing says what it marks.
764    pub favorite: String,
765    /// A [`SwatchGrid`](crate::SwatchGrid)'s name.
766    pub swatches: String,
767    /// A [`NinePointAnchor`](crate::NinePointAnchor)'s name.
768    pub anchor_point: String,
769    /// The points of a [`NinePointAnchor`](crate::NinePointAnchor), row by row from the top left.
770    pub anchor_names: [String; 9],
771    /// The upper color of a [`ColorPair`](crate::ColorPair).
772    pub color_foreground: String,
773    /// The lower color of a [`ColorPair`](crate::ColorPair).
774    pub color_background: String,
775    /// Swaps the colors of a [`ColorPair`](crate::ColorPair).
776    pub color_swap: String,
777    /// Puts back the first colors of a [`ColorPair`](crate::ColorPair).
778    pub color_reset: String,
779    /// Count, sum, average, smallest and largest, as a grid's footer calls them.
780    pub grid_summaries: [String; 5],
781    /// Runs the code of a `Playground`.
782    pub playground_run: String,
783    /// Puts the chosen example of a `Playground` back.
784    pub playground_restore: String,
785    /// The examples of a `Playground`.
786    pub playground_example: String,
787    /// The code tab of a `Playground`.
788    pub playground_code: String,
789    /// What the code of a `Playground` makes.
790    pub playground_result: String,
791    /// The result a `Playground` keeps while the code has problems.
792    pub playground_last_good: String,
793    /// Before the line of a problem.
794    pub playground_line: String,
795    /// Before the column of a problem.
796    pub playground_column: String,
797    /// Saves what the code of a `Playground` makes as a file to keep.
798    pub playground_download: String,
799    /// The panel under the result of a `Playground`.
800    pub playground_output: String,
801    /// What the code of a `Playground` printed.
802    pub playground_console: String,
803    /// The problems of the code of a `Playground`.
804    pub playground_problems: String,
805    /// When the code of a `Playground` has none.
806    pub playground_no_problems: String,
807    /// When the code of a `Playground` printed nothing.
808    pub playground_nothing_printed: String,
809    /// Empties the output of a `Playground`.
810    pub playground_clear_output: String,
811    /// Folds the output of a `Playground` away.
812    pub playground_hide_output: String,
813    /// Opens the output of a `Playground` again.
814    pub playground_show_output: String,
815    /// The menu of a narrow `Playground` with what is not Run.
816    pub playground_more: String,
817    /// Puts a `Playground` in full screen.
818    pub playground_full_screen: String,
819    /// Takes a `Playground` out of full screen.
820    pub playground_exit_full_screen: String,
821}
822
823impl Default for Labels {
824    fn default() -> Self {
825        Self::from_texts(&Texts::new(Language::English))
826    }
827}
828
829#[cfg_attr(feature = "live", ravenrs_live::expose)]
830impl Labels {
831    /// The texts of a catalog, in its language. What it does not have comes from English.
832    pub fn from_texts(texts: &Texts) -> Self {
833        Self {
834            close: texts.get("widgets.close"),
835            help: texts.get("widgets.help"),
836            navigation: texts.get("widgets.navigation"),
837            toggle_sidebar: texts.get("widgets.toggle_sidebar"),
838            dismiss: texts.get("widgets.dismiss"),
839            send: texts.get("widgets.send"),
840            listen: texts.get("widgets.listen"),
841            tree_name: texts.get("widgets.tree_name"),
842            tag_remove: texts.get("widgets.tag_remove"),
843            pick_color: texts.get("widgets.pick_color"),
844            no_color: texts.get("widgets.no_color"),
845            color_shade: texts.get("widgets.color_shade"),
846            color_hue: texts.get("widgets.color_hue"),
847            color_alpha: texts.get("widgets.color_alpha"),
848            color_hex: texts.get("widgets.color_hex"),
849            pick_date_range: texts.get("widgets.pick_date_range"),
850            candle_open: texts.get("widgets.candle_open"),
851            candle_high: texts.get("widgets.candle_high"),
852            candle_low: texts.get("widgets.candle_low"),
853            candle_close: texts.get("widgets.candle_close"),
854            sankey_cycle: texts.get("widgets.sankey_cycle"),
855            list_name: texts.get("widgets.list_name"),
856            filmstrip_name: texts.get("widgets.filmstrip_name"),
857            document_name: texts.get("widgets.document_name"),
858            page_word: texts.get("widgets.page_word"),
859            page_of: texts.get("widgets.page_of"),
860            previous_page: texts.get("widgets.previous_page"),
861            next_page: texts.get("widgets.next_page"),
862            file_browser_name: texts.get("widgets.file_browser_name"),
863            file_name: texts.get("widgets.file_name"),
864            file_size: texts.get("widgets.file_size"),
865            attachments: texts.get("widgets.attachments"),
866            attachment_remove: texts.get("widgets.attachment_remove"),
867            attachment_send_as: texts.get("widgets.attachment_send_as"),
868            selection_bar: texts.get("widgets.selection_bar"),
869            selection_exit: texts.get("widgets.selection_exit"),
870            selection_none: texts.get("widgets.selection_none"),
871            selection_one: texts.get("widgets.selection_one"),
872            selection_many: texts.get("widgets.selection_many"),
873            audio_player: texts.get("widgets.audio_player"),
874            audio_play: texts.get("widgets.audio_play"),
875            audio_stop: texts.get("widgets.audio_stop"),
876            audio_loading: texts.get("widgets.audio_loading"),
877            audio_transcript: texts.get("widgets.audio_transcript"),
878            audio_transcribe: texts.get("widgets.audio_transcribe"),
879            audio_transcribing: texts.get("widgets.audio_transcribing"),
880            audio_no_speech: texts.get("widgets.audio_no_speech"),
881            chat_photo: texts.get("widgets.chat_photo"),
882            chat_photo_loading: texts.get("widgets.chat_photo_loading"),
883            chat_open: texts.get("widgets.chat_open"),
884            file_modified: texts.get("widgets.file_modified"),
885            folder_word: texts.get("widgets.folder_word"),
886            folder_empty: texts.get("widgets.folder_empty"),
887            previous_year: texts.get("widgets.previous_year"),
888            next_year: texts.get("widgets.next_year"),
889            day_marked: texts.get("widgets.day_marked"),
890            sortable_name: texts.get("widgets.sortable_name"),
891            sortable_hint: texts.get("widgets.sortable_hint"),
892            moved_to: texts.get("widgets.moved_to"),
893            document_tabs_name: texts.get("widgets.document_tabs_name"),
894            dock_area_name: texts.get("widgets.dock_area_name"),
895            dock_tabs_name: texts.get("widgets.dock_tabs_name"),
896            dock_empty: texts.get("widgets.dock_empty"),
897            dock_left: texts.get("widgets.dock_left"),
898            dock_right: texts.get("widgets.dock_right"),
899            dock_bottom: texts.get("widgets.dock_bottom"),
900            dock_center: texts.get("widgets.dock_center"),
901            dock_move_to: texts.get("widgets.dock_move_to"),
902            dock_with: texts.get("widgets.dock_with"),
903            dock_split_right: texts.get("widgets.dock_split_right"),
904            dock_split_below: texts.get("widgets.dock_split_below"),
905            dock_close: texts.get("widgets.dock_close"),
906            dock_reopen: texts.get("widgets.dock_reopen"),
907            dock_close_panel: texts.get("widgets.dock_close_panel"),
908            dock_options: texts.get("widgets.dock_options"),
909            dock_hide: texts.get("widgets.dock_hide"),
910            dock_show: texts.get("widgets.dock_show"),
911            dock_resize: texts.get("widgets.dock_resize"),
912            dock_resize_pair: texts.get("widgets.dock_resize_pair"),
913            dock_moved: texts.get("widgets.dock_moved"),
914            dock_closed: texts.get("widgets.dock_closed"),
915            close_tab: texts.get("widgets.close_tab"),
916            new_tab: texts.get("widgets.new_tab"),
917            close_other_tabs: texts.get("widgets.close_other_tabs"),
918            close_tabs_to_right: texts.get("widgets.close_tabs_to_right"),
919            unsaved: texts.get("widgets.unsaved"),
920            wizard_back: texts.get("widgets.wizard_back"),
921            wizard_next: texts.get("widgets.wizard_next"),
922            wizard_finish: texts.get("widgets.wizard_finish"),
923            wizard_cancel: texts.get("widgets.wizard_cancel"),
924            wizard_done: texts.get("widgets.wizard_done"),
925            wizard_error: texts.get("widgets.wizard_error"),
926            split_resize: texts.get("widgets.split_resize"),
927            panel_move: texts.get("widgets.panel_move"),
928            panel_minimize: texts.get("widgets.panel_minimize"),
929            panel_restore: texts.get("widgets.panel_restore"),
930            scroll_back: texts.get("widgets.scroll_back"),
931            scroll_forward: texts.get("widgets.scroll_forward"),
932            window_minimize: texts.get("widgets.window_minimize"),
933            window_maximize: texts.get("widgets.window_maximize"),
934            window_restore: texts.get("widgets.window_restore"),
935            value_adjust: texts.get("widgets.value_adjust"),
936            rename: texts.get("widgets.rename"),
937            rename_hint: texts.get("widgets.rename_hint"),
938            file_drop: texts.get("widgets.file_drop"),
939            file_choose: texts.get("widgets.file_choose"),
940            file_remove: texts.get("widgets.file_remove"),
941            file_wrong_kind: texts.get("widgets.file_wrong_kind"),
942            file_too_large: texts.get("widgets.file_too_large"),
943            file_too_many: texts.get("widgets.file_too_many"),
944            image_choose: texts.get("widgets.image_choose"),
945            image_replace: texts.get("widgets.image_replace"),
946            image_none: texts.get("widgets.image_none"),
947            image_invalid: texts.get("widgets.image_invalid"),
948            tile_move: texts.get("widgets.tile_move"),
949            tile_resize: texts.get("widgets.tile_resize"),
950            cards_name: texts.get("widgets.cards_name"),
951            grid_expand_row: texts.get("widgets.grid_expand_row"),
952            grid_collapse_row: texts.get("widgets.grid_collapse_row"),
953            tag_add: texts.get("widgets.tag_add"),
954            wizard_progress: texts.get("widgets.wizard_progress"),
955            culture: texts.get("widgets.culture"),
956            loading: texts.get("widgets.loading"),
957            decrease: texts.get("widgets.decrease"),
958            increase: texts.get("widgets.increase"),
959            required: texts.get("widgets.required"),
960            pick_date: texts.get("widgets.pick_date"),
961            select: texts.get("widgets.select"),
962            search: texts.get("widgets.search"),
963            no_results: texts.get("widgets.no_results"),
964            search_commands: texts.get("widgets.search_commands"),
965            no_commands: texts.get("widgets.no_commands"),
966            command_palette: texts.get("widgets.command_palette"),
967            theme: texts.get("widgets.theme"),
968            theme_dark: texts.get("widgets.theme_dark"),
969            theme_light: texts.get("widgets.theme_light"),
970            theme_glass: texts.get("widgets.theme_glass"),
971            theme_surfaces: texts.get("widgets.theme_surfaces"),
972            theme_text: texts.get("widgets.theme_text"),
973            theme_accent: texts.get("widgets.theme_accent"),
974            theme_status: texts.get("widgets.theme_status"),
975            theme_shape: texts.get("widgets.theme_shape"),
976            theme_sizes: texts.get("widgets.theme_sizes"),
977            theme_restore: texts.get("widgets.theme_restore"),
978            theme_copy: texts.get("widgets.theme_copy"),
979            theme_paste: texts.get("widgets.theme_paste"),
980            theme_invalid: texts.get("widgets.theme_invalid"),
981            theme_changed: texts.array("widgets.theme_changed"),
982            theme_contrast: texts.get("widgets.theme_contrast"),
983            copy: texts.get("widgets.copy"),
984            copied: texts.get("widgets.copied"),
985            release_versions: texts.get("widgets.release_versions"),
986            release_newer: texts.get("widgets.release_newer"),
987            release_older: texts.get("widgets.release_older"),
988            release_of: texts.get("widgets.release_of"),
989            diagnostics: texts.get("widgets.diagnostics"),
990            diagnostics_test: texts.get("widgets.diagnostics_test"),
991            diagnostics_testing: texts.get("widgets.diagnostics_testing"),
992            diagnostics_testing_detail: texts.get("widgets.diagnostics_testing_detail"),
993            diagnostics_test_good: texts.get("widgets.diagnostics_test_good"),
994            diagnostics_test_fair: texts.get("widgets.diagnostics_test_fair"),
995            diagnostics_test_poor: texts.get("widgets.diagnostics_test_poor"),
996            diagnostics_test_fps: texts.get("widgets.diagnostics_test_fps"),
997            diagnostics_test_cause_none: texts.get("widgets.diagnostics_test_cause_none"),
998            diagnostics_timeline: texts.get("widgets.diagnostics_timeline"),
999            diagnostics_timeline_detail: texts.get("widgets.diagnostics_timeline_detail"),
1000            diagnostics_why: texts.get("widgets.diagnostics_why"),
1001            diagnostics_why_none: texts.get("widgets.diagnostics_why_none"),
1002            diagnostics_causes: texts.array("widgets.diagnostics_causes"),
1003            diagnostics_views: texts.get("widgets.diagnostics_views"),
1004            diagnostics_batches: texts.get("widgets.diagnostics_batches"),
1005            diagnostics_memory: texts.get("widgets.diagnostics_memory"),
1006            diagnostics_copy_trace: texts.get("widgets.diagnostics_copy_trace"),
1007            diagnostics_test_cause_gpu: texts.get("widgets.diagnostics_test_cause_gpu"),
1008            diagnostics_test_cause_interface: texts.get("widgets.diagnostics_test_cause_interface"),
1009            diagnostics_software: texts.get("widgets.diagnostics_software"),
1010            diagnostics_software_detail: texts.get("widgets.diagnostics_software_detail"),
1011            diagnostics_unoptimized: texts.get("widgets.diagnostics_unoptimized"),
1012            diagnostics_unoptimized_detail: texts.get("widgets.diagnostics_unoptimized_detail"),
1013            diagnostics_hidden: texts.get("widgets.diagnostics_hidden"),
1014            diagnostics_no_gpu: texts.get("widgets.diagnostics_no_gpu"),
1015            diagnostics_frame: texts.get("widgets.diagnostics_frame"),
1016            diagnostics_update: texts.get("widgets.diagnostics_update"),
1017            diagnostics_acquire: texts.get("widgets.diagnostics_acquire"),
1018            diagnostics_render: texts.get("widgets.diagnostics_render"),
1019            diagnostics_report_bug: texts.get("widgets.diagnostics_report_bug"),
1020            diagnostics_report_shares: texts.get("widgets.diagnostics_report_shares"),
1021            diagnostics_report_shares_detail: texts.get("widgets.diagnostics_report_shares_detail"),
1022            diagnostics_report_failed: texts.get("widgets.diagnostics_report_failed"),
1023            diagnostics_report_failed_detail: texts.get("widgets.diagnostics_report_failed_detail"),
1024            diagnostics_report_questions: texts.get("widgets.diagnostics_report_questions"),
1025            diagnostics_report_truncated: texts.get("widgets.diagnostics_report_truncated"),
1026            previous_month: texts.get("widgets.previous_month"),
1027            next_month: texts.get("widgets.next_month"),
1028            today: texts.get("widgets.today"),
1029            weekdays: texts.array("widgets.weekdays"),
1030            months: texts.array("widgets.months"),
1031            month_year: texts.get("widgets.month_year"),
1032            short_date: texts.get("widgets.short_date"),
1033            form_errors: texts.get("widgets.form_errors"),
1034            clear: texts.get("widgets.clear"),
1035            filter_all: texts.get("widgets.filter_all"),
1036            filter_any: texts.get("widgets.filter_any"),
1037            filter_match: texts.get("widgets.filter_match"),
1038            filter_add_condition: texts.get("widgets.filter_add_condition"),
1039            filter_add_group: texts.get("widgets.filter_add_group"),
1040            filter_remove: texts.get("widgets.filter_remove"),
1041            filter_field: texts.get("widgets.filter_field"),
1042            filter_comparison: texts.get("widgets.filter_comparison"),
1043            filter_value: texts.get("widgets.filter_value"),
1044            filter_expression: texts.get("widgets.filter_expression"),
1045            filter_yes: texts.get("widgets.filter_yes"),
1046            filter_no: texts.get("widgets.filter_no"),
1047            filter_equal: texts.get("widgets.filter_equal"),
1048            filter_not_equal: texts.get("widgets.filter_not_equal"),
1049            filter_greater: texts.get("widgets.filter_greater"),
1050            filter_greater_or_equal: texts.get("widgets.filter_greater_or_equal"),
1051            filter_less: texts.get("widgets.filter_less"),
1052            filter_less_or_equal: texts.get("widgets.filter_less_or_equal"),
1053            filter_contains: texts.get("widgets.filter_contains"),
1054            filter_starts_with: texts.get("widgets.filter_starts_with"),
1055            filter_is_empty: texts.get("widgets.filter_is_empty"),
1056            filter_is_not_empty: texts.get("widgets.filter_is_not_empty"),
1057            filter_any_of: texts.get("widgets.filter_any_of"),
1058            filter_none_of: texts.get("widgets.filter_none_of"),
1059            ribbon: texts.get("widgets.ribbon"),
1060            ribbon_search: texts.get("widgets.ribbon_search"),
1061            ribbon_pin: texts.get("widgets.ribbon_pin"),
1062            ribbon_collapse: texts.get("widgets.ribbon_collapse"),
1063            carousel_previous: texts.get("widgets.carousel_previous"),
1064            carousel_next: texts.get("widgets.carousel_next"),
1065            carousel_slide: texts.get("widgets.carousel_slide"),
1066            verification_code: texts.get("widgets.verification_code"),
1067            cancel: texts.get("widgets.cancel"),
1068            confirm_by_typing: texts.get("widgets.confirm_by_typing"),
1069            more_commands: texts.get("widgets.more_commands"),
1070            decimal_separator: texts.char("format.decimal", '.'),
1071            group_separator: texts.char("format.thousands", ','),
1072            pick_time: texts.get("widgets.pick_time"),
1073            step_up: texts.get("widgets.step_up"),
1074            step_down: texts.get("widgets.step_down"),
1075            calendar_more: texts.get("widgets.calendar_more"),
1076            scheduler_resources: texts.get("widgets.scheduler_resources"),
1077            zoom_in: texts.get("widgets.zoom_in"),
1078            zoom_out: texts.get("widgets.zoom_out"),
1079            histogram: texts.get("widgets.histogram"),
1080            histogram_clipped_low: texts.get("widgets.histogram_clipped_low"),
1081            histogram_clipped_high: texts.get("widgets.histogram_clipped_high"),
1082            ruler: texts.get("widgets.ruler"),
1083            color_wheel: texts.get("widgets.color_wheel"),
1084            color_saturation: texts.get("widgets.color_saturation"),
1085            curve_editor: texts.get("widgets.curve_editor"),
1086            curve_point: texts.get("widgets.curve_point"),
1087            curve_points: texts.get("widgets.curve_points"),
1088            curve_input: texts.get("widgets.curve_input"),
1089            curve_output: texts.get("widgets.curve_output"),
1090            zoom: texts.get("widgets.zoom"),
1091            zoom_fit: texts.get("widgets.zoom_fit"),
1092            zoom_actual: texts.get("widgets.zoom_actual"),
1093            zoom_view: texts.get("widgets.zoom_view"),
1094            minimap: texts.get("widgets.minimap"),
1095            rubber_band: texts.get("widgets.rubber_band"),
1096            marquee: texts.get("widgets.marquee"),
1097            transform: texts.get("widgets.transform"),
1098            crop: texts.get("widgets.crop"),
1099            protractor: texts.get("widgets.protractor"),
1100            eyedropper: texts.get("widgets.eyedropper"),
1101            eyedropper_hint: texts.get("widgets.eyedropper_hint"),
1102            eyedropper_area: texts.get("widgets.eyedropper_area"),
1103            compare: texts.get("widgets.compare"),
1104            compare_first: texts.get("widgets.compare_first"),
1105            compare_second: texts.get("widgets.compare_second"),
1106            lightbox: texts.get("widgets.lightbox"),
1107            lightbox_previous: texts.get("widgets.lightbox_previous"),
1108            lightbox_next: texts.get("widgets.lightbox_next"),
1109            lightbox_counter: texts.get("widgets.lightbox_counter"),
1110            recurrence_name: texts.get("widgets.recurrence_name"),
1111            recurrence_frequencies: texts.array("widgets.recurrence_frequencies"),
1112            recurrence_every: texts.get("widgets.recurrence_every"),
1113            recurrence_units: texts.pairs("widgets.recurrence_units"),
1114            recurrence_each: texts.array("widgets.recurrence_each"),
1115            recurrence_ends_name: texts.get("widgets.recurrence_ends_name"),
1116            recurrence_ends: texts.array("widgets.recurrence_ends"),
1117            recurrence_times: texts.get("widgets.recurrence_times"),
1118            recurrence_until: texts.get("widgets.recurrence_until"),
1119            recurrence_next: texts.get("widgets.recurrence_next"),
1120            grid_drag_hint: texts.get("widgets.grid_drag_hint"),
1121            grid_grouped_by: texts.get("widgets.grid_grouped_by"),
1122            grid_remove_group: texts.get("widgets.grid_remove_group"),
1123            grid_expand_all: texts.get("widgets.grid_expand_all"),
1124            grid_collapse_all: texts.get("widgets.grid_collapse_all"),
1125            grid_sort_ascending: texts.get("widgets.grid_sort_ascending"),
1126            grid_sort_descending: texts.get("widgets.grid_sort_descending"),
1127            grid_clear_sort: texts.get("widgets.grid_clear_sort"),
1128            grid_group_by_column: texts.get("widgets.grid_group_by_column"),
1129            grid_ungroup_column: texts.get("widgets.grid_ungroup_column"),
1130            grid_pin_column: texts.get("widgets.grid_pin_column"),
1131            grid_unpin_column: texts.get("widgets.grid_unpin_column"),
1132            grid_hide_column: texts.get("widgets.grid_hide_column"),
1133            grid_fit_column: texts.get("widgets.grid_fit_column"),
1134            grid_show_panel: texts.get("widgets.grid_show_panel"),
1135            grid_hide_panel: texts.get("widgets.grid_hide_panel"),
1136            grid_column_menu: texts.get("widgets.grid_column_menu"),
1137            grid_filter_values: texts.get("widgets.grid_filter_values"),
1138            grid_clear_filter: texts.get("widgets.grid_clear_filter"),
1139            expression_text: texts.get("widgets.expression_text"),
1140            expression_search: texts.get("widgets.expression_search"),
1141            expression_insert: texts.get("widgets.expression_insert"),
1142            expression_valid: texts.get("widgets.expression_valid"),
1143            expression_error_at: texts.get("widgets.expression_error_at"),
1144            expression_unknown: texts.get("widgets.expression_unknown"),
1145            expression_no_match: texts.get("widgets.expression_no_match"),
1146            expression_groups: texts.array("widgets.expression_groups"),
1147            expression_operators: texts.pair_list("widgets.expression_operators"),
1148            expression_constants: texts.pair_list("widgets.expression_constants"),
1149            grid_filter_label: texts.get("widgets.grid_filter_label"),
1150            grid_edit_filter: texts.get("widgets.grid_edit_filter"),
1151            grid_all_values: texts.get("widgets.grid_all_values"),
1152            grid_scenario: texts.get("widgets.grid_scenario"),
1153            grid_scenario_save: texts.get("widgets.grid_scenario_save"),
1154            grid_scenario_update: texts.get("widgets.grid_scenario_update"),
1155            grid_scenario_delete: texts.get("widgets.grid_scenario_delete"),
1156            grid_scenario_original: texts.get("widgets.grid_scenario_original"),
1157            grid_scenario_name: texts.get("widgets.grid_scenario_name"),
1158            grid_save: texts.get("widgets.grid_save"),
1159            grid_rows_per_page: texts.get("widgets.grid_rows_per_page"),
1160            grid_try_again: texts.get("widgets.grid_try_again"),
1161            grid_page: texts.get("widgets.grid_page"),
1162            grid_previous: texts.get("widgets.grid_previous"),
1163            grid_next: texts.get("widgets.grid_next"),
1164            grid_edit_summary: texts.get("widgets.grid_edit_summary"),
1165            grid_summary_of: texts.get("widgets.grid_summary_of"),
1166            grid_summary_none: texts.get("widgets.grid_summary_none"),
1167            grid_summary_formula: texts.get("widgets.grid_summary_formula"),
1168            grid_formula_hint: texts.get("widgets.grid_formula_hint"),
1169            grid_formula_result: texts.get("widgets.grid_formula_result"),
1170            grid_formula_error: texts.get("widgets.grid_formula_error"),
1171            grid_formula_columns: texts.get("widgets.grid_formula_columns"),
1172            grid_formula_functions: texts.get("widgets.grid_formula_functions"),
1173            grid_apply: texts.get("widgets.grid_apply"),
1174            grid_search: texts.get("widgets.grid_search"),
1175            grid_group: texts.get("widgets.grid_group"),
1176            grid_clear_grouping: texts.get("widgets.grid_clear_grouping"),
1177            grid_columns: texts.get("widgets.grid_columns"),
1178            grid_reset: texts.get("widgets.grid_reset"),
1179            grid_export: texts.get("widgets.grid_export"),
1180            grid_export_file: texts.get("widgets.grid_export_file"),
1181            grid_add_row: texts.get("widgets.grid_add_row"),
1182            grid_delete_rows: texts.get("widgets.grid_delete_rows"),
1183            grid_no_rows: texts.get("widgets.grid_no_rows"),
1184            grid_name: texts.get("widgets.grid_name"),
1185            grid_select_row: texts.get("widgets.grid_select_row"),
1186            grid_sorted_ascending: texts.get("widgets.grid_sorted_ascending"),
1187            grid_sorted_descending: texts.get("widgets.grid_sorted_descending"),
1188            grid_filter_hint: texts.get("widgets.grid_filter_hint"),
1189            grid_number_filter_hint: texts.get("widgets.grid_number_filter_hint"),
1190            grid_filter_column: texts.get("widgets.grid_filter_column"),
1191            grid_empty: texts.get("widgets.grid_empty"),
1192            grid_of: texts.get("widgets.grid_of"),
1193            grid_rows: texts.get("widgets.grid_rows"),
1194            grid_selected: texts.get("widgets.grid_selected"),
1195            rating: texts.get("widgets.rating"),
1196            rating_value: texts.get("widgets.rating_value"),
1197            yesterday: texts.get("widgets.yesterday"),
1198            shortcut_sheet: texts.get("widgets.shortcut_sheet"),
1199            favorite: texts.get("widgets.favorite"),
1200            swatches: texts.get("widgets.swatches"),
1201            anchor_point: texts.get("widgets.anchor_point"),
1202            anchor_names: texts.array("widgets.anchor_names"),
1203            color_foreground: texts.get("widgets.color_foreground"),
1204            color_background: texts.get("widgets.color_background"),
1205            color_swap: texts.get("widgets.color_swap"),
1206            color_reset: texts.get("widgets.color_reset"),
1207            grid_summaries: texts.array("widgets.grid_summaries"),
1208            playground_run: texts.get("widgets.playground_run"),
1209            playground_restore: texts.get("widgets.playground_restore"),
1210            playground_example: texts.get("widgets.playground_example"),
1211            playground_code: texts.get("widgets.playground_code"),
1212            playground_result: texts.get("widgets.playground_result"),
1213            playground_last_good: texts.get("widgets.playground_last_good"),
1214            playground_line: texts.get("widgets.playground_line"),
1215            playground_column: texts.get("widgets.playground_column"),
1216            playground_download: texts.get("widgets.playground_download"),
1217            playground_output: texts.get("widgets.playground_output"),
1218            playground_console: texts.get("widgets.playground_console"),
1219            playground_problems: texts.get("widgets.playground_problems"),
1220            playground_no_problems: texts.get("widgets.playground_no_problems"),
1221            playground_nothing_printed: texts.get("widgets.playground_nothing_printed"),
1222            playground_clear_output: texts.get("widgets.playground_clear_output"),
1223            playground_hide_output: texts.get("widgets.playground_hide_output"),
1224            playground_show_output: texts.get("widgets.playground_show_output"),
1225            playground_more: texts.get("widgets.playground_more"),
1226            playground_full_screen: texts.get("widgets.playground_full_screen"),
1227            playground_exit_full_screen: texts.get("widgets.playground_exit_full_screen"),
1228        }
1229    }
1230
1231    /// Brazilian Portuguese.
1232    pub fn pt_br() -> Self {
1233        Self::from_texts(&Texts::new(Language::BrazilianPortuguese))
1234    }
1235
1236    /// A place of a [`DockArea`](crate::DockArea).
1237    pub fn dock_place(&self, side: crate::DockSide) -> &str {
1238        match side {
1239            crate::DockSide::Left => &self.dock_left,
1240            crate::DockSide::Right => &self.dock_right,
1241            crate::DockSide::Bottom => &self.dock_bottom,
1242            _ => &self.dock_center,
1243        }
1244    }
1245
1246    /// A place in the middle of a sentence.
1247    fn dock_place_lower(&self, side: crate::DockSide) -> String {
1248        self.dock_place(side).to_lowercase()
1249    }
1250
1251    /// The item that joins the group where `title` shows.
1252    pub fn dock_with_name(&self, title: &str) -> String {
1253        self.dock_with.replace("{title}", title)
1254    }
1255
1256    /// The name of the button that closes the panel `title`.
1257    pub fn dock_close_name(&self, title: &str) -> String {
1258        self.dock_close_panel.replace("{title}", title)
1259    }
1260
1261    /// The name of the button with the menu of the panel `title`.
1262    pub fn dock_options_name(&self, title: &str) -> String {
1263        self.dock_options.replace("{title}", title)
1264    }
1265
1266    /// The name of the strip that collapses a dock.
1267    pub fn dock_hide_name(&self, side: crate::DockSide) -> String {
1268        self.dock_hide.replace("{place}", &self.dock_place_lower(side))
1269    }
1270
1271    /// The name of the strip that brings a dock back.
1272    pub fn dock_show_name(&self, side: crate::DockSide) -> String {
1273        self.dock_show.replace("{place}", &self.dock_place_lower(side))
1274    }
1275
1276    /// The name of the bar that resizes a dock.
1277    pub fn dock_resize_name(&self, side: crate::DockSide) -> String {
1278        self.dock_resize.replace("{place}", &self.dock_place_lower(side))
1279    }
1280
1281    /// The name of the bar between two parts of a split.
1282    pub fn dock_resize_between(&self, first: &str, second: &str) -> String {
1283        self.dock_resize_pair.replace("{first}", first).replace("{second}", second)
1284    }
1285
1286    /// What is announced after a panel went to a place.
1287    pub fn dock_moved_to(&self, side: crate::DockSide) -> String {
1288        self.dock_moved.replace("{place}", &self.dock_place_lower(side))
1289    }
1290
1291    /// What is announced after the panel `title` closed.
1292    pub fn dock_closed_name(&self, title: &str) -> String {
1293        self.dock_closed.replace("{title}", title)
1294    }
1295
1296    /// What is announced after a reorder, such as "Moved to position 2 of 5".
1297    pub fn moved_to_position(&self, position: usize, total: usize) -> String {
1298        self.moved_to.replace("{position}", &position.to_string()).replace("{total}", &total.to_string())
1299    }
1300
1301    /// The name of a page, such as "Page 2 of 9".
1302    pub fn page_name(&self, number: usize, total: usize) -> String {
1303        format!("{} {number}{}{total}", self.page_word, self.page_of)
1304    }
1305
1306    /// A date the way people here write it, for a date picker.
1307    pub fn short_date(&self, date: Date) -> String {
1308        let month = &self.months[usize::from(date.month().clamp(1, 12)) - 1];
1309        format_with(&self.short_date, |index, out| {
1310            match index {
1311                0 => write!(out, "{:02}", date.day()),
1312                1 => write!(out, "{:02}", date.month()),
1313                2 => write!(out, "{:04}", date.year()),
1314                3 => write!(out, "{}", date.day()),
1315                4 => {
1316                    out.extend(month.chars().take(3));
1317                    Ok(())
1318                }
1319                _ => return false,
1320            }
1321            .is_ok()
1322        })
1323    }
1324
1325    /// What a [`TagBox`](crate::TagBox) option says when it adds `typed`.
1326    pub fn tag_add(&self, typed: &str) -> String {
1327        ravenrs_app_i18n::format(&self.tag_add, &[typed])
1328    }
1329
1330    /// Where a [`Wizard`](crate::Wizard) stands, at `step` of `count`.
1331    pub fn wizard_progress(&self, step: usize, count: usize) -> String {
1332        two_numbers(&self.wizard_progress, step, count)
1333    }
1334
1335    /// How many tokens changed.
1336    pub fn theme_changed(&self, count: usize) -> String {
1337        two_numbers(&self.theme_changed[count.min(2)], count, 0)
1338    }
1339
1340    /// A contrast, and the token it is measured over.
1341    pub fn theme_contrast(&self, ratio: f32, ground: &str) -> String {
1342        format_with(&self.theme_contrast, |index, out| match index {
1343            0 => {
1344                let at = out.len();
1345                let written = write!(out, "{ratio:.1}").is_ok();
1346                if let Some(point) = out[at..].find('.') {
1347                    let mut separator = [0; 4];
1348                    out.replace_range(
1349                        at + point..=at + point,
1350                        self.decimal_separator.encode_utf8(&mut separator),
1351                    );
1352                }
1353                written
1354            }
1355            1 => {
1356                out.push_str(ground);
1357                true
1358            }
1359            _ => false,
1360        })
1361    }
1362
1363    /// Which picture of how many an [`ImageLightbox`](crate::ImageLightbox) is showing.
1364    pub fn lightbox_counter(&self, at: usize, of: usize) -> String {
1365        two_numbers(&self.lightbox_counter, at, of)
1366    }
1367
1368    /// Where a [`Rating`](crate::Rating) stands, from its score and its maximum.
1369    pub fn rating_value(&self, score: u32, max: u32) -> String {
1370        two_numbers(&self.rating_value, score as usize, max as usize)
1371    }
1372
1373    /// A month and its year: `November 2026`, `novembro de 2026`.
1374    pub fn month_title(&self, date: Date) -> String {
1375        let month = &self.months[usize::from(date.month().clamp(1, 12)) - 1];
1376        format!("{month}{}{}", self.month_year, date.year())
1377    }
1378
1379    /// A full date, for screen readers: `15 November 2026`, `15 novembro de 2026`.
1380    pub fn long_date(&self, date: Date) -> String {
1381        format!("{} {}", date.day(), self.month_title(date))
1382    }
1383
1384    /// The word for one period of this frequency; `count` picks singular or plural.
1385    pub fn recurrence_unit(&self, frequency: Frequency, count: u32) -> &str {
1386        let unit = match frequency {
1387            Frequency::Daily => &self.recurrence_units[0],
1388            Frequency::Weekly => &self.recurrence_units[1],
1389            Frequency::Yearly => &self.recurrence_units[3],
1390            _ => &self.recurrence_units[2],
1391        };
1392        if count > 1 { &unit.1 } else { &unit.0 }
1393    }
1394
1395    /// A rule in words, with its next days: `Every month, 3 times. Next: 05/11/2026, 05/12/2026`.
1396    pub fn recurrence_summary(&self, rule: &RecurrenceRule, start: Date) -> String {
1397        let how = match (rule.frequency, rule.interval.max(1)) {
1398            (Frequency::Daily, 1) => self.recurrence_each[0].clone(),
1399            (Frequency::Weekly, 1) => self.recurrence_each[1].clone(),
1400            (Frequency::Monthly, 1) => self.recurrence_each[2].clone(),
1401            (Frequency::Yearly, 1) => self.recurrence_each[3].clone(),
1402            (Frequency::Daily | Frequency::Weekly | Frequency::Monthly | Frequency::Yearly, n) => {
1403                format!("{} {n} {}", self.recurrence_every, self.recurrence_unit(rule.frequency, n))
1404            }
1405            _ => self.recurrence_frequencies[0].clone(),
1406        };
1407        let until = match rule.end {
1408            RecurrenceEnd::Until(day) => format!(" {} {}", self.recurrence_until, self.short_date(day)),
1409            RecurrenceEnd::After(count) => format!(", {count} {}", self.recurrence_times),
1410            _ => String::new(),
1411        };
1412        let next: Vec<String> = rule.days_from(start).take(3).map(|day| self.short_date(day)).collect();
1413        format!("{how}{until}. {}: {}", self.recurrence_next, next.join(", "))
1414    }
1415
1416    /// What a grid's footer calls this summary.
1417    pub fn summary(&self, summary: Summary) -> &str {
1418        let index = match summary {
1419            Summary::Count => 0,
1420            Summary::Sum => 1,
1421            Summary::Average => 2,
1422            Summary::Min => 3,
1423            _ => 4,
1424        };
1425        &self.grid_summaries[index]
1426    }
1427}
1428
1429/// Everything inside uses these words instead of the English defaults: wrap the
1430/// root of an app, or just the part that speaks another language.
1431///
1432/// ```
1433/// use ravenrs_widgets::{DatePicker, Date, Labels, Localized};
1434/// use ravenrs_reactive::State;
1435///
1436/// let day = State::new(Date::new(2026, 11, 15));
1437/// let app = Localized::new(Labels::pt_br(), DatePicker::new(day.binding(), Date::new(2026, 11, 1).unwrap_or(Date::from_days(0))));
1438/// # let _ = app;
1439/// ```
1440#[derive(Debug)]
1441pub struct Localized<V> {
1442    labels: std::rc::Rc<Labels>,
1443    content: V,
1444}
1445
1446#[cfg_attr(feature = "live", ravenrs_live::expose)]
1447impl<V: View> Localized<V> {
1448    /// `content`, using `labels`.
1449    pub fn new(labels: Labels, content: V) -> Self {
1450        Self { labels: std::rc::Rc::new(labels), content }
1451    }
1452}
1453
1454impl<V: View> View for Localized<V> {
1455    fn build(&self, cx: &mut BuildCx<'_>) -> NodeId {
1456        let outer = cx.replace_labels(self.labels.clone());
1457        let node = cx.child(&self.content);
1458        cx.replace_labels(outer);
1459        node
1460    }
1461}
1462
1463/// A template with `{0}` and `{1}` filled in with these, each written where it goes.
1464fn two_numbers(template: &str, first: usize, second: usize) -> String {
1465    format_with(template, |index, out| match index {
1466        0 => write!(out, "{first}").is_ok(),
1467        1 => write!(out, "{second}").is_ok(),
1468        _ => false,
1469    })
1470}