Internationalize user-facing strings and export them for translations
Changelog-Added: Internationalized user-facing strings and exported them for translations Signed-off-by: Terry Yiu <git@tyiu.xyz>
This commit is contained in:
@@ -233,7 +233,7 @@ impl Notedeck {
|
||||
// Initialize localization
|
||||
let i18n_resource_dir = Path::new("assets/translations");
|
||||
let localization_manager = Arc::new(
|
||||
LocalizationManager::new(&i18n_resource_dir).unwrap_or_else(|e| {
|
||||
LocalizationManager::new(i18n_resource_dir).unwrap_or_else(|e| {
|
||||
error!("Failed to initialize localization manager: {}", e);
|
||||
// Create a fallback manager with a temporary directory
|
||||
LocalizationManager::new(&std::env::temp_dir().join("notedeck_i18n_fallback"))
|
||||
|
||||
@@ -78,7 +78,7 @@ impl LocalizationManager {
|
||||
locale: &LanguageIdentifier,
|
||||
) -> Result<Arc<FluentResource>, Box<dyn std::error::Error + Send + Sync>> {
|
||||
// Construct the path using the stored resource directory
|
||||
let expected_path = self.resource_dir.join(format!("{}/main.ftl", locale));
|
||||
let expected_path = self.resource_dir.join(format!("{locale}/main.ftl"));
|
||||
|
||||
// Try to open the file directly
|
||||
if let Err(e) = std::fs::File::open(&expected_path) {
|
||||
@@ -87,16 +87,16 @@ impl LocalizationManager {
|
||||
expected_path.display(),
|
||||
e
|
||||
);
|
||||
return Err(format!("Failed to open FTL file: {}", e).into());
|
||||
return Err(format!("Failed to open FTL file: {e}").into());
|
||||
}
|
||||
|
||||
// Load the FTL file directly instead of using ResourceManager
|
||||
let ftl_string = std::fs::read_to_string(&expected_path)
|
||||
.map_err(|e| format!("Failed to read FTL file: {}", e))?;
|
||||
.map_err(|e| format!("Failed to read FTL file: {e}"))?;
|
||||
|
||||
// Parse the FTL content
|
||||
let resource = FluentResource::try_new(ftl_string)
|
||||
.map_err(|e| format!("Failed to parse FTL content: {:?}", e))?;
|
||||
.map_err(|e| format!("Failed to parse FTL content: {e:?}"))?;
|
||||
|
||||
tracing::debug!(
|
||||
"Loaded and cached parsed FluentResource for locale: {}",
|
||||
@@ -182,15 +182,15 @@ impl LocalizationManager {
|
||||
let mut bundle = FluentBundle::new(vec![locale.clone()]);
|
||||
bundle
|
||||
.add_resource(resource.as_ref())
|
||||
.map_err(|e| format!("Failed to add resource to bundle: {:?}", e))?;
|
||||
.map_err(|e| format!("Failed to add resource to bundle: {e:?}"))?;
|
||||
|
||||
let message = bundle
|
||||
.get_message(id)
|
||||
.ok_or_else(|| format!("Message not found: {}", id))?;
|
||||
.ok_or_else(|| format!("Message not found: {id}"))?;
|
||||
|
||||
let pattern = message
|
||||
.value()
|
||||
.ok_or_else(|| format!("Message has no value: {}", id))?;
|
||||
.ok_or_else(|| format!("Message has no value: {id}"))?;
|
||||
|
||||
// Format the message
|
||||
let mut errors = Vec::new();
|
||||
@@ -243,16 +243,16 @@ impl LocalizationManager {
|
||||
locale,
|
||||
self.available_locales
|
||||
);
|
||||
return Err(format!("Locale {} is not available", locale).into());
|
||||
return Err(format!("Locale {locale} is not available").into());
|
||||
}
|
||||
|
||||
let mut current = self
|
||||
.current_locale
|
||||
.write()
|
||||
.map_err(|e| format!("Lock error: {e}"))?;
|
||||
tracing::info!("Switching locale from {} to {}", *current, locale);
|
||||
tracing::info!("Switching locale from {} to {locale}", *current);
|
||||
*current = locale.clone();
|
||||
tracing::info!("Successfully set locale to: {}", locale);
|
||||
tracing::info!("Successfully set locale to: {locale}");
|
||||
|
||||
// Clear caches when locale changes since they are locale-specific
|
||||
let mut string_cache = self
|
||||
@@ -406,7 +406,7 @@ impl LocalizationContext {
|
||||
pub fn get_string_with_args(&self, id: &str, args: Option<&FluentArgs>) -> String {
|
||||
self.manager
|
||||
.get_string_with_args(id, args)
|
||||
.unwrap_or_else(|_| format!("[MISSING: {}]", id))
|
||||
.unwrap_or_else(|_| format!("[MISSING: {id}]"))
|
||||
}
|
||||
|
||||
/// Sets the current locale
|
||||
@@ -447,7 +447,7 @@ pub trait Localizable {
|
||||
impl Localizable for LocalizationContext {
|
||||
fn get_localized_string(&self, id: &str) -> String {
|
||||
self.get_string(id)
|
||||
.unwrap_or_else(|| format!("[MISSING: {}]", id))
|
||||
.unwrap_or_else(|| format!("[MISSING: {id}]"))
|
||||
}
|
||||
|
||||
fn get_localized_string_with_args(&self, id: &str, args: Option<&FluentArgs>) -> String {
|
||||
|
||||
@@ -54,7 +54,7 @@ fn simple_hash(s: &str) -> String {
|
||||
pub fn normalize_ftl_key(key: &str, comment: Option<&str>) -> String {
|
||||
// Try to get from cache first
|
||||
let cache_key = if let Some(comment) = comment {
|
||||
format!("{}:{}", key, comment)
|
||||
format!("{key}:{comment}")
|
||||
} else {
|
||||
key.to_string()
|
||||
};
|
||||
@@ -76,8 +76,8 @@ pub fn normalize_ftl_key(key: &str, comment: Option<&str>) -> String {
|
||||
result = result.trim_matches('_').to_string();
|
||||
|
||||
// Ensure the key starts with a letter (Fluent requirement)
|
||||
if !(result.len() > 0 && result.chars().next().unwrap().is_ascii_alphabetic()) {
|
||||
result = format!("k_{}", result);
|
||||
if result.is_empty() || !result.chars().next().unwrap().is_ascii_alphabetic() {
|
||||
result = format!("k_{result}");
|
||||
}
|
||||
|
||||
// If we have a comment, append a hash of it to reduce collisions
|
||||
|
||||
@@ -153,8 +153,8 @@ impl From<nwc::Error> for NwcError {
|
||||
impl Display for NwcError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
NwcError::NIP47(err) => write!(f, "NIP47 error: {}", err),
|
||||
NwcError::Relay(err) => write!(f, "Relay error: {}", err),
|
||||
NwcError::NIP47(err) => write!(f, "NIP47 error: {err}"),
|
||||
NwcError::Relay(err) => write!(f, "Relay error: {err}"),
|
||||
NwcError::PrematureExit => write!(f, "Premature exit"),
|
||||
NwcError::Timeout => write!(f, "Request timed out"),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user