Skip to content

Commit

Permalink
feat(aura): respect LANG
Browse files Browse the repository at this point in the history
The environment variable `LANG` can be used to set Aura's language. This
can be overridden specifically for Aura via Aura's config as well.
Further, a language flag passed on the command line will have highest
priority and override all other settings.
  • Loading branch information
fosskers committed Jun 8, 2024
1 parent 065be3b commit b6e0f0c
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 36 deletions.
27 changes: 24 additions & 3 deletions rust/aura-pm/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
use crate::dirs;
use crate::error::Nested;
use crate::localization::{identifier_from_code, Localised, ENGLISH};
use crate::localization::{identifier_from_code, Localised};
use aura_pm::ENGLISH;
use from_variants::FromVariants;
use i18n_embed_fl::fl;
use log::{debug, error};
Expand Down Expand Up @@ -158,10 +159,16 @@ impl Env {
}

/// Allow CLI flags to override settings from `aura.toml`.
pub(crate) fn reconcile_cli(&mut self, flags: &aura_pm::flags::SubCmd) {
if let aura_pm::flags::SubCmd::Aur(a) = flags {
pub(crate) fn reconcile_cli(&mut self, flags: &aura_pm::flags::Args) {
if let aura_pm::flags::SubCmd::Aur(a) = &flags.subcmd {
self.aur.reconcile(a)
}

// Specifying a language on the command line overrides all other
// settings.
if let Some(l) = flags.language() {
self.general.language = l;
}
}

/// Before continuing, confirm that the settled `Env` is valid to use.
Expand Down Expand Up @@ -207,14 +214,28 @@ impl From<RawGeneral> for General {
cpus: raw.cpus.unwrap_or_else(|| num_cpus::get() as u32),
editor: raw.editor.unwrap_or_else(editor),
doas: raw.doas.unwrap_or(false),
// Precedence: We check config first for a language setting. If
// nothing, we check the environment. If nothing, we fall back to
// English. This can further be overridden by CLI flags.
language: raw
.language
.and_then(identifier_from_code)
.or_else(|| language())
.unwrap_or(ENGLISH),
}
}
}

/// An attempt to fetch a language setting from environment variables.
fn language() -> Option<LanguageIdentifier> {
let raw = std::env::var("LANG").ok()?;

match raw.as_str() {
"en_US.UTF-8" => Some(ENGLISH),
_ => None,
}
}

/// The editor program to call in certain situations.
fn editor() -> String {
std::env::var("EDITOR").unwrap_or_else(|_| DEFAULT_EDITOR.to_string())
Expand Down
10 changes: 5 additions & 5 deletions rust/aura-pm/src/flags.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! Types and utilities for parsing flags from the command line.
use crate::Date;
use crate::{Date, ENGLISH, GERMAN, JAPANESE};
use clap::{ArgAction, Parser, Subcommand};
use simplelog::LevelFilter;
use std::ops::Not;
use std::path::PathBuf;
use unic_langid::{langid, LanguageIdentifier};
use unic_langid::LanguageIdentifier;

/// Global options only applicable to Aura that must be removed from the
/// top-level args list before sending it to Pacman.
Expand Down Expand Up @@ -60,9 +60,9 @@ impl Args {
/// corresponding standardized language code.
pub fn language(&self) -> Option<LanguageIdentifier> {
match () {
_ if self.english => Some(langid!("en-US")),
_ if self.german => Some(langid!("de-DE")),
_ if self.japanese => Some(langid!("ja-JP")),
_ if self.english => Some(ENGLISH),
_ if self.german => Some(GERMAN),
_ if self.japanese => Some(JAPANESE),
_ => None,
}
}
Expand Down
6 changes: 6 additions & 0 deletions rust/aura-pm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pub mod flags;

use std::str::FromStr;

use unic_langid::{langid, LanguageIdentifier};

/// A wrapper around [`time::Date`] to supply some trait instances.
#[derive(Debug, Clone)]
pub struct Date(pub time::Date);
Expand All @@ -19,3 +21,7 @@ impl FromStr for Date {
.map(Date)
}
}

pub const ENGLISH: LanguageIdentifier = langid!("en-US");
pub const GERMAN: LanguageIdentifier = langid!("de-DE");
pub const JAPANESE: LanguageIdentifier = langid!("ja-JP");
11 changes: 5 additions & 6 deletions rust/aura-pm/src/localization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
use crate::utils::PathStr;
use aura_core::aur::dependencies as deps;
use aura_core::Apply;
use aura_pm::{ENGLISH, GERMAN, JAPANESE};
use i18n_embed::fluent::{fluent_language_loader, FluentLanguageLoader};
use i18n_embed::{I18nEmbedError, LanguageLoader};
use i18n_embed_fl::fl;
use nonempty_collections::*;
use rust_embed::RustEmbed;
use std::collections::HashMap;
use unic_langid::{langid, LanguageIdentifier};

pub(crate) const ENGLISH: LanguageIdentifier = langid!("en-US");
use unic_langid::LanguageIdentifier;

#[derive(RustEmbed)]
#[folder = "i18n"]
Expand Down Expand Up @@ -43,9 +42,9 @@ where
S: AsRef<str>,
{
match code.as_ref() {
"en-US" => Some(langid!("en-US")),
"de-DE" => Some(langid!("de-DE")),
"ja-JP" => Some(langid!("ja-JP")),
"en-US" => Some(ENGLISH),
"de-DE" => Some(GERMAN),
"ja-JP" => Some(JAPANESE),
_ => None,
}
}
Expand Down
64 changes: 42 additions & 22 deletions rust/aura-pm/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use crate::command::{aur, cache, check, conf, deps, log as llog, open, orphans,
use crate::error::{Error, Nested};
use crate::localization::Localised;
use aura_pm::flags::{Args, Cache, SubCmd, AURA_GLOBALS};
use aura_pm::ENGLISH;
use clap::Parser;
use colored::Colorize;
use env::Env;
Expand All @@ -56,26 +57,55 @@ use std::process::ExitCode;
fn main() -> ExitCode {
// Parse all CLI input. Exits immediately if invalid input is given.
let args = aura_pm::flags::Args::parse();
debug!("{:#?}", args);

// --- Localisation --- //
match localization::load(args.language()) {
// --- Runtime Settings --- //
match env(&args) {
Err(e) => {
aln!("Failed to localise Aura!".red());
println!("\n {}", e);
match localization::load(Some(ENGLISH)) {
Err(e1) => {
aln!("Aura utterly failed to establish a runtime environment.".red());
println!("\n {}", e1);
}
Ok(fll) => {
aln!(e.localise(&fll).red());
}
}

ExitCode::FAILURE
}
Ok(fll) => match work(args, &fll) {
Err(e) => {
e.nested();
aln!(e.localise(&fll).red());
ExitCode::FAILURE
Ok(env) => {
debug!("{:#?}", env);

// --- Localisation --- //
match localization::load(Some(env.general.language.clone())) {
Err(e) => {
aln!("Runtime environment loaded, but failed to localise Aura!".red());
println!("\n {}", e);
ExitCode::FAILURE
}
Ok(fll) => match work(args, env, &fll) {
Err(e) => {
e.nested();
aln!(e.localise(&fll).red());
ExitCode::FAILURE
}
Ok(_) => ExitCode::SUCCESS,
},
}
Ok(_) => ExitCode::SUCCESS,
},
}
}
}

fn work(args: Args, fll: &FluentLanguageLoader) -> Result<(), Error> {
/// Initialize the runtime environment.
fn env(args: &Args) -> Result<Env, Error> {
let mut env = crate::env::Env::try_new()?;
env.reconcile_cli(&args);
env.validate()?;
Ok(env)
}

fn work(args: Args, env: Env, fll: &FluentLanguageLoader) -> Result<(), Error> {
// --- Terminal Logging --- //
if let Some(l) = args.log_level {
// Silently ignore logger init failure. Realistically it should never
Expand All @@ -84,16 +114,6 @@ fn work(args: Args, fll: &FluentLanguageLoader) -> Result<(), Error> {
let _ = TermLogger::init(l, Config::default(), TerminalMode::Mixed, ColorChoice::Auto);
}

// --- Runtime Settings --- //
let env = {
let mut env = crate::env::Env::try_new()?;
env.reconcile_cli(&args.subcmd);
env.validate()?;
env
};
debug!("{:#?}", env);
debug!("{:#?}", args);

match args.subcmd {
// --- Pacman Commands --- //
SubCmd::Database(d) => pacman(&env, d.needs_sudo())?,
Expand Down

0 comments on commit b6e0f0c

Please sign in to comment.