From 200c13a14e2ad8b5777a3602ce6c1bb0559357ad Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Sat, 22 Feb 2025 18:39:32 -0500 Subject: [PATCH] Add a configuration file --- l10n-db/Cargo.toml | 1 + l10n-db/config.toml | 8 ++++++ l10n-db/i18n/OpenSandbox.toml | 9 +++++-- l10n-db/src/bin/main.rs | 46 ++++++++++++++++++++++++++--------- l10n-db/src/editor.rs | 22 ++++++++++------- l10n-db/src/lib.rs | 3 +++ l10n-db/src/types.rs | 2 +- l10n-db/src/utils.rs | 31 +++++++++++++++++++++++ 8 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 l10n-db/config.toml create mode 100644 l10n-db/src/utils.rs diff --git a/l10n-db/Cargo.toml b/l10n-db/Cargo.toml index 977cd68..e36077b 100644 --- a/l10n-db/Cargo.toml +++ b/l10n-db/Cargo.toml @@ -9,6 +9,7 @@ clap = { version = "4.5.30", features = ["derive"] } icu_locid = { version = "1.5.0", features = ["serde"] } serde = { version = "1.0.218", features = ["derive"] } tempfile = "3.17.1" +thiserror = "2.0.11" toml = "0.8.20" # [lib] diff --git a/l10n-db/config.toml b/l10n-db/config.toml new file mode 100644 index 0000000..913bdbb --- /dev/null +++ b/l10n-db/config.toml @@ -0,0 +1,8 @@ +db_path = "./i18n" +base_locale = "en" +locales = [ + "en", + "eo", + "de", + "es", +] diff --git a/l10n-db/i18n/OpenSandbox.toml b/l10n-db/i18n/OpenSandbox.toml index 4c963f6..81b7d4f 100644 --- a/l10n-db/i18n/OpenSandbox.toml +++ b/l10n-db/i18n/OpenSandbox.toml @@ -1,7 +1,12 @@ key = "OpenSandbox" description = "A sandbox vault refers to a stock vault that contains test data and allows the user to make edits and run experiments on test data." -[variants.en-US] -locale = "en-US" +[variants.eo] +locale = "eo" +content = "Malfermi sekurkofro" +modified = "2025-02-22T23:35:29.692299091Z" + +[variants.en] +locale = "en" content = "Open Sandbox vault" modified = "2025-02-22T21:35:02.032300406Z" diff --git a/l10n-db/src/bin/main.rs b/l10n-db/src/bin/main.rs index ecd079f..1860136 100644 --- a/l10n-db/src/bin/main.rs +++ b/l10n-db/src/bin/main.rs @@ -1,9 +1,14 @@ -use std::{io::{BufReader, Read, Write}, path::PathBuf, process::Command}; +use std::{ + io::{BufReader, Read, Write}, + path::PathBuf, + process::Command, +}; use clap::{Parser, Subcommand}; use icu_locid::{langid, LanguageIdentifier}; -use l10n_db::{self, Bundle, Editor}; +use l10n_db::{self, read_file, Bundle, Editor, ReadError}; +use serde::Deserialize; #[derive(Parser)] #[command(version, about, long_about = None)] @@ -15,7 +20,12 @@ struct Cli { #[derive(Subcommand)] enum Commands { /// Edit, potentially creating, a key - EditKey { name: String, locale: String }, + EditKey { + #[arg(short, long)] + name: String, + #[arg(short, long)] + locale: String, + }, /// List al keys in the database ListKeys, // Search the database @@ -25,10 +35,17 @@ enum Commands { #[arg(short, long)] format: String, #[arg(short, long)] - locale: String + locale: String, }, } +#[derive(Debug, Deserialize)] +struct Config { + db_path: PathBuf, + base_locale: LanguageIdentifier, + locales: Vec, +} + fn edit_key(bundle: &mut Bundle, key: String, locale: LanguageIdentifier, editor: &str) { let message = bundle.message(key); Editor::edit(message, locale, editor); @@ -36,21 +53,28 @@ fn edit_key(bundle: &mut Bundle, key: String, locale: LanguageIdentifier, editor } fn main() { - let editor = std::env::var("EDITOR").unwrap(); - let db_path = std::env::var("DB_PATH").unwrap(); + let editor = std::env::var("EDITOR").expect("Set EDITOR to the path to your favorite editor"); + + let config: Config = read_file(&PathBuf::from("./config.toml")) + .and_then(|bytes| String::from_utf8(bytes).map_err(|_| ReadError::InvalidFormat)) + .and_then(|content| toml::from_str(&content).map_err(|_| ReadError::InvalidFormat)) + .unwrap(); let cli = Cli::parse(); - let mut bundle = Bundle::load_from_disk(PathBuf::from(&db_path)); + let mut bundle = Bundle::load_from_disk(PathBuf::from(&config.db_path)); match &cli.command { - Some(Commands::EditKey{ name, locale } ) => edit_key(&mut bundle, name.to_owned(), langid!("en-US"), &editor), + Some(Commands::EditKey { name, locale }) => { + let identifier = locale.parse::().unwrap(); + edit_key(&mut bundle, name.to_owned(), identifier, &editor) + } Some(Commands::ListKeys) => { for (key, _) in bundle.message_iter() { println!("{}", key); } - }, - Some(Commands::Export{..}) => todo!(), - None => {}, + } + Some(Commands::Export { .. }) => todo!(), + None => {} } } diff --git a/l10n-db/src/editor.rs b/l10n-db/src/editor.rs index a650b39..c51d580 100644 --- a/l10n-db/src/editor.rs +++ b/l10n-db/src/editor.rs @@ -1,17 +1,19 @@ use std::{io::{BufReader, Read, Write}, path::Path, process::Command}; -use icu_locid::LanguageIdentifier; +use icu_locid::{langid, LanguageIdentifier}; use serde::{Deserialize, Serialize}; -use crate::{Message, Variant}; +use crate::{read_fh, Message, Variant}; #[derive(Serialize, Deserialize, Debug, Clone)] struct EditorMessage { description: String, + source: String, content: String, } +/* impl EditorMessage { fn from_variant(description: String, variant: &Variant) -> Self { Self { @@ -20,6 +22,7 @@ impl EditorMessage { } } } +*/ pub struct Editor { } @@ -27,8 +30,14 @@ pub struct Editor { impl Editor { pub fn edit(msg: &mut Message, locale: LanguageIdentifier, editor: &str) { let description = msg.description().to_owned(); + let source_string = msg.variant_mut(langid!("en")).content().to_owned(); let variant = msg.variant_mut(locale); - let editable_content = EditorMessage::from_variant(description, &variant); + // let editable_content = EditorMessage::from_variant(description, &variant); + let editable_content = EditorMessage { + description, + source: source_string, + content: variant.content().to_owned(), + }; let mut file = tempfile::NamedTempFile::new().unwrap(); let _ = file.write(toml::to_string(&editable_content).unwrap().as_bytes()); @@ -36,12 +45,7 @@ impl Editor { let mut cmd = Command::new(editor).args([file.path()]).spawn().unwrap(); cmd.wait().unwrap(); let file = file.reopen().unwrap(); - let mut reader = BufReader::new(file); - let mut content = Vec::new(); - let _ = reader.read_to_end(&mut content); - - println!("content"); - println!("{}", String::from_utf8(content.clone()).unwrap()); + let content = read_fh(&file).unwrap(); let new_variant: EditorMessage = toml::from_str(&String::from_utf8(content).unwrap()).unwrap(); diff --git a/l10n-db/src/lib.rs b/l10n-db/src/lib.rs index 9dd0718..ab1eec2 100644 --- a/l10n-db/src/lib.rs +++ b/l10n-db/src/lib.rs @@ -7,6 +7,9 @@ pub use editor::Editor; mod types; pub use types::{Message, Variant}; +mod utils; +pub use utils::*; + /* #[cfg(test)] mod test { diff --git a/l10n-db/src/types.rs b/l10n-db/src/types.rs index 32c4268..13b447d 100644 --- a/l10n-db/src/types.rs +++ b/l10n-db/src/types.rs @@ -45,7 +45,7 @@ impl Message { } } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, Clone)] pub struct Variant { locale: LanguageIdentifier, content: String, diff --git a/l10n-db/src/utils.rs b/l10n-db/src/utils.rs new file mode 100644 index 0000000..b499b9d --- /dev/null +++ b/l10n-db/src/utils.rs @@ -0,0 +1,31 @@ +use std::{fs::File, io::{BufReader, ErrorKind, Read}, path::Path}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum ReadError { + #[error("file not found")] + FileNotFound, + + #[error("invalid file format")] + InvalidFormat, + + #[error("unhandled read error")] + Unhandled(ErrorKind), +} + +pub fn read_file(path: &Path) -> Result, ReadError> { + let file = File::open(path).map_err(|err| { + match err.kind() { + ErrorKind::NotFound => ReadError::FileNotFound, + _ => ReadError::Unhandled( err.kind()), + } + })?; + read_fh(&file) +} + +pub fn read_fh(file: &File) -> Result, ReadError> { + let mut content = Vec::new(); + let mut reader = BufReader::new(file); + reader.read_to_end(&mut content).map_err(|err| ReadError::Unhandled(err.kind()))?; + Ok(content) +}