inspector_gguf/localization/
provider.rs

1//! Language provider trait for accessing localized text.
2//!
3//! This module defines the [`LanguageProvider`] trait which provides a unified interface
4//! for accessing translated text throughout the application. Any type that needs to
5//! display localized text should implement this trait.
6//!
7//! # Design Pattern
8//!
9//! The trait uses a simple key-based lookup system where translation keys use dot notation
10//! to access nested translation structures (e.g., "buttons.load" accesses the "load" key
11//! within the "buttons" section).
12//!
13//! # Examples
14//!
15//! ```rust
16//! use inspector_gguf::localization::{LanguageProvider, LocalizationManager};
17//!
18//! // LocalizationManager implements LanguageProvider
19//! let manager = LocalizationManager::new()?;
20//! let title = manager.t("app.title");
21//! assert!(!title.is_empty());
22//! # Ok::<(), Box<dyn std::error::Error>>(())
23//! ```
24
25/// Trait for types that provide access to localized text.
26///
27/// This trait defines the interface for accessing translated strings throughout
28/// the application. It provides methods for simple text lookup and parameterized
29/// text formatting with placeholder substitution.
30///
31/// # Implementation
32///
33/// The primary implementation is [`LocalizationManager`], which loads translations
34/// from JSON files and provides fallback mechanisms for missing keys.
35///
36/// # Examples
37///
38/// ## Basic Text Retrieval
39///
40/// ```rust
41/// use inspector_gguf::localization::{LanguageProvider, LocalizationManager, Language};
42///
43/// let mut manager = LocalizationManager::new()?;
44/// manager.set_language(Language::English)?;
45///
46/// // Get simple translated text
47/// let load_button = manager.t("buttons.load");
48/// assert_eq!(load_button, "Load");
49/// # Ok::<(), Box<dyn std::error::Error>>(())
50/// ```
51///
52/// ## Parameterized Text
53///
54/// ```rust
55/// use inspector_gguf::localization::{LanguageProvider, LocalizationManager};
56///
57/// let manager = LocalizationManager::new()?;
58///
59/// // Get text with parameter substitution
60/// let error_msg = manager.t_with_args("messages.export_failed", &["file not found"]);
61/// assert!(error_msg.contains("file not found"));
62/// # Ok::<(), Box<dyn std::error::Error>>(())
63/// ```
64///
65/// See also [`LocalizationManager`] for the main implementation and
66/// [`crate::localization::Language`] for supported languages.
67///
68/// [`LocalizationManager`]: crate::localization::LocalizationManager
69pub trait LanguageProvider {
70    /// Retrieves translated text for the specified key.
71    ///
72    /// This method looks up the translation for the given key in the current language,
73    /// with automatic fallback to English if the key is not found. If no translation
74    /// exists in any language, the key itself is returned.
75    ///
76    /// # Arguments
77    ///
78    /// * `key` - Translation key in dot notation (e.g., "app.title", "buttons.load")
79    ///
80    /// # Returns
81    ///
82    /// The translated string, or the key itself if no translation is available.
83    ///
84    /// # Examples
85    ///
86    /// ```rust
87    /// use inspector_gguf::localization::{LanguageProvider, LocalizationManager, Language};
88    ///
89    /// let mut manager = LocalizationManager::new()?;
90    ///
91    /// // Get English translation
92    /// manager.set_language(Language::English)?;
93    /// assert_eq!(manager.t("app.title"), "Inspector GGUF");
94    ///
95    /// // Get Russian translation
96    /// manager.set_language(Language::Russian)?;
97    /// let russian_title = manager.t("app.title");
98    /// assert!(!russian_title.is_empty());
99    /// # Ok::<(), Box<dyn std::error::Error>>(())
100    /// ```
101    fn t(&self, key: &str) -> String;
102
103    /// Retrieves translated text with parameter substitution.
104    ///
105    /// This method retrieves a translation and performs placeholder substitution,
106    /// replacing `{0}`, `{1}`, etc. with the provided arguments in order.
107    ///
108    /// # Arguments
109    ///
110    /// * `key` - Translation key in dot notation
111    /// * `args` - Array of string arguments to substitute into placeholders
112    ///
113    /// # Returns
114    ///
115    /// The translated string with placeholders replaced by the provided arguments.
116    ///
117    /// # Examples
118    ///
119    /// ```rust
120    /// use inspector_gguf::localization::{LanguageProvider, LocalizationManager};
121    ///
122    /// let manager = LocalizationManager::new()?;
123    ///
124    /// // Translation: "Export failed: {0}"
125    /// let error = manager.t_with_args("messages.export_failed", &["disk full"]);
126    /// assert!(error.contains("disk full"));
127    ///
128    /// // Translation: "New version available: {0}"
129    /// let update = manager.t_with_args("messages.update_available", &["v2.0.0"]);
130    /// assert!(update.contains("v2.0.0"));
131    /// # Ok::<(), Box<dyn std::error::Error>>(())
132    /// ```
133    fn t_with_args(&self, key: &str, args: &[&str]) -> String {
134        let mut text = self.t(key);
135        for (i, arg) in args.iter().enumerate() {
136            text = text.replace(&format!("{{{}}}", i), arg);
137        }
138        text
139    }
140}
141
142/// Implementation of LanguageProvider for LocalizationManager.
143///
144/// This implementation delegates to the manager's internal translation lookup
145/// system, providing access to all loaded translations with automatic fallback.
146impl LanguageProvider for crate::localization::LocalizationManager {
147    fn t(&self, key: &str) -> String {
148        self.get_text(key)
149    }
150}