🔒 Repository is read-only – file editing is disabled.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
//! Minimalna, zależnościowo „lekka" lokalizacja PL/EN.
//!
//! Świadomie NIE używamy `fluent`, `gettext` ani plików `.po`: dla toolkitu
//! wystarczy statyczna tablica napisów. Dzięki temu:
//!
//! * zero dodatkowych zależności i zero kodu generowanego w czasie budowy,
//! * `tr()` jest w pełni `const`-owalne (zwraca `&'static str`),
//! * rozbudowa to dopisanie jednego wariantu w [`MsgKey`] i trzech napisów w [`tr`].
//!
//! Język wybieramy ze zmiennej środowiskowej `PAGAN_LANG` (`pl` / `en`).
/// Obsługiwane języki interfejsu.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Locale {
/// Polski.
Pl,
/// Angielski (domyślny, bezpieczny fallback).
En,
}
impl Default for Locale {
fn default() -> Self {
Locale::En
}
}
/// Klucze komunikatów UI. Dodawanie nowych napisów zaczyna się tutaj.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MsgKey {
/// Tytuł okna demo.
WindowTitle,
/// Etykieta przycisku „Menu".
Menu,
/// Pozycja paska menu: plik.
MenuFile,
/// Pozycja paska menu: edycja.
MenuEdit,
/// Pozycja paska menu: widok.
MenuView,
/// Pozycja paska menu: pomoc.
MenuHelp,
/// Etykieta/tooltip przycisku zamykania.
Close,
/// Etykieta/tooltip przycisku minimalizacji.
Minimize,
/// Etykieta/tooltip przycisku maksymalizacji.
Maximize,
/// Etykieta/tooltip przywrócenia rozmiaru.
Restore,
/// Log: zamykanie okna.
LogClosing,
/// Log: rozpoczęto przeciąganie okna.
LogDrag,
/// Log: rozpoczęto zmianę rozmiaru za krawędź/róg.
LogResize,
/// Log: otwarto/zamknięto menu.
LogMenu,
/// Log: zakończono pętlę zdarzeń.
LogExit,
/// Log: zmieniono stan maksymalizacji.
LogMaximize,
}
/// Zwraca przetłumaczony napis dla pary `(język, klucz)`.
///
/// Funkcja jest czysta (brak stanu, brak alokacji) i zwraca `&'static str`,
/// więc można ją wywoływać bez obaw w każdym miejscu, także w kodzie rysującym.
pub fn tr(locale: Locale, key: MsgKey) -> &'static str {
match locale {
Locale::Pl => match key {
MsgKey::WindowTitle => "Pagan Toolkit — okno demo",
MsgKey::Menu => "Menu",
MsgKey::MenuFile => "Plik",
MsgKey::MenuEdit => "Edycja",
MsgKey::MenuView => "Widok",
MsgKey::MenuHelp => "Pomoc",
MsgKey::Close => "Zamknij",
MsgKey::Minimize => "Minimalizuj",
MsgKey::Maximize => "Maksymalizuj",
MsgKey::Restore => "Przywróć",
MsgKey::LogClosing => "Zamykanie okna na życzenie użytkownika.",
MsgKey::LogDrag => "Rozpoczęto przeciąganie okna (xdg_toplevel.move).",
MsgKey::LogResize => "Rozpoczęto zmianę rozmiaru okna (xdg_toplevel.resize).",
MsgKey::LogMenu => "Naciśnięto przycisk menu.",
MsgKey::LogExit => "Pętla zdarzeń zakończona. Do zobaczenia!",
MsgKey::LogMaximize => "Zmieniono stan maksymalizacji okna.",
},
Locale::En => match key {
MsgKey::WindowTitle => "Pagan Toolkit — demo window",
MsgKey::Menu => "Menu",
MsgKey::MenuFile => "File",
MsgKey::MenuEdit => "Edit",
MsgKey::MenuView => "View",
MsgKey::MenuHelp => "Help",
MsgKey::Close => "Close",
MsgKey::Minimize => "Minimize",
MsgKey::Maximize => "Maximize",
MsgKey::Restore => "Restore",
MsgKey::LogClosing => "Closing the window at user request.",
MsgKey::LogDrag => "Started interactive move (xdg_toplevel.move).",
MsgKey::LogResize => "Started interactive resize (xdg_toplevel.resize).",
MsgKey::LogMenu => "Menu button pressed.",
MsgKey::LogExit => "Event loop finished. Goodbye!",
MsgKey::LogMaximize => "Toggled window maximize state.",
},
}
}
impl From<&str> for Locale {
/// Mapuje dowolny string (np. z `PAGAN_LANG`) na język. Nieznane wartości →
/// [`Locale::En`], żeby aplikacja nigdy nie wyświetlała pustych napisów.
fn from(value: &str) -> Self {
let normalized = value.trim().to_ascii_lowercase();
match normalized.as_str() {
"pl" | "pol" | "polski" | "pl_pl" | "pl-pl" => Locale::Pl,
_ => Locale::En,
}
}
}
impl From<String> for Locale {
fn from(value: String) -> Self {
Locale::from(value.as_str())
}
}
impl Locale {
/// Odczytuje język ze zmiennej środowiskowej `PAGAN_LANG`.
pub fn from_env() -> Self {
std::env::var("PAGAN_LANG")
.map(|value| Locale::from(value.as_str()))
.unwrap_or_default()
}
}