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}