Skip to content

Commit 1d95bab

Browse files
Jonathan D.A. Jewellclaude
andcommitted
feat: add i18n module and rename audience → axial
Add a centralized i18n module with 5 languages (EN/ES/FR/DE/JA) and 47 translation keys covering all subcommand report output. Replaces the hardcoded tr()/tr_lang() functions in the old audience module with catalog-based t(lang, key) lookups that fall back to English. Rename the audience subcommand to axial — better fit for the multi-axis attack observation theme and consistent with the all-A naming convention (assail, attack, assault, ambush, amuck, abduct, adjudicate, axial). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 62395e8 commit 1d95bab

7 files changed

Lines changed: 781 additions & 215 deletions

File tree

src/a2ml/mod.rs

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::report::formatter::nickel_escape_string;
66
use crate::report::ReportOutputFormat;
77
use crate::storage::StorageMode;
88
use crate::types::{AssailReport, AssaultReport, AttackResult};
9-
use crate::{abduct, adjudicate, amuck, audience};
9+
use crate::{abduct, adjudicate, amuck, axial};
1010
use anyhow::{anyhow, Context, Result};
1111
use serde::de::DeserializeOwned;
1212
use serde_json;
@@ -26,7 +26,7 @@ pub enum ReportBundleKind {
2626
Amuck,
2727
Abduct,
2828
Adjudicate,
29-
Audience,
29+
Axial,
3030
}
3131

3232
impl ReportBundleKind {
@@ -39,7 +39,7 @@ impl ReportBundleKind {
3939
Self::Amuck => "amuck",
4040
Self::Abduct => "abduct",
4141
Self::Adjudicate => "adjudicate",
42-
Self::Audience => "audience",
42+
Self::Axial => "axial",
4343
}
4444
}
4545

@@ -52,7 +52,7 @@ impl ReportBundleKind {
5252
"amuck" => Some(Self::Amuck),
5353
"abduct" => Some(Self::Abduct),
5454
"adjudicate" => Some(Self::Adjudicate),
55-
"audience" => Some(Self::Audience),
55+
"axial" => Some(Self::Axial),
5656
_ => None,
5757
}
5858
}
@@ -67,7 +67,7 @@ pub enum ReportBundlePayload {
6767
Amuck(amuck::AmuckReport),
6868
Abduct(abduct::AbductReport),
6969
Adjudicate(adjudicate::AdjudicateReport),
70-
Audience(audience::AudienceReport),
70+
Axial(axial::AxialReport),
7171
}
7272

7373
impl ReportBundlePayload {
@@ -80,7 +80,7 @@ impl ReportBundlePayload {
8080
Self::Amuck(_) => ReportBundleKind::Amuck,
8181
Self::Abduct(_) => ReportBundleKind::Abduct,
8282
Self::Adjudicate(_) => ReportBundleKind::Adjudicate,
83-
Self::Audience(_) => ReportBundleKind::Audience,
83+
Self::Axial(_) => ReportBundleKind::Axial,
8484
}
8585
}
8686

@@ -93,7 +93,7 @@ impl ReportBundlePayload {
9393
Self::Amuck(v) => serde_json::to_string(v),
9494
Self::Abduct(v) => serde_json::to_string(v),
9595
Self::Adjudicate(v) => serde_json::to_string(v),
96-
Self::Audience(v) => serde_json::to_string(v),
96+
Self::Axial(v) => serde_json::to_string(v),
9797
}
9898
.context("serializing report payload as json")?;
9999
Ok(encoded)
@@ -262,7 +262,7 @@ pub fn import_report_file(input: &Path, output: &Path) -> Result<ReportBundleKin
262262
ReportBundlePayload::Amuck(v) => serde_json::to_string_pretty(v),
263263
ReportBundlePayload::Abduct(v) => serde_json::to_string_pretty(v),
264264
ReportBundlePayload::Adjudicate(v) => serde_json::to_string_pretty(v),
265-
ReportBundlePayload::Audience(v) => serde_json::to_string_pretty(v),
265+
ReportBundlePayload::Axial(v) => serde_json::to_string_pretty(v),
266266
}
267267
.context("serializing imported report")?;
268268
fs::write(output, json).with_context(|| format!("writing {}", output.display()))?;
@@ -292,8 +292,8 @@ fn load_payload_for_kind(kind: ReportBundleKind, input: &Path) -> Result<ReportB
292292
ReportBundleKind::Adjudicate => ReportBundlePayload::Adjudicate(load_json_or_yaml::<
293293
adjudicate::AdjudicateReport,
294294
>(input)?),
295-
ReportBundleKind::Audience => {
296-
ReportBundlePayload::Audience(load_json_or_yaml::<audience::AudienceReport>(input)?)
295+
ReportBundleKind::Axial => {
296+
ReportBundlePayload::Axial(load_json_or_yaml::<axial::AxialReport>(input)?)
297297
}
298298
})
299299
}
@@ -431,8 +431,8 @@ fn parse_payload(kind: ReportBundleKind, payload_json: &str) -> Result<ReportBun
431431
ReportBundleKind::Adjudicate => ReportBundlePayload::Adjudicate(serde_json::from_str::<
432432
adjudicate::AdjudicateReport,
433433
>(payload_json)?),
434-
ReportBundleKind::Audience => ReportBundlePayload::Audience(serde_json::from_str::<
435-
audience::AudienceReport,
434+
ReportBundleKind::Axial => ReportBundlePayload::Axial(serde_json::from_str::<
435+
axial::AxialReport,
436436
>(payload_json)?),
437437
})
438438
}
@@ -908,18 +908,18 @@ mod tests {
908908
}
909909
}
910910

911-
fn sample_audience_report() -> audience::AudienceReport {
911+
fn sample_axial_report() -> axial::AxialReport {
912912
let mut signal_counts = BTreeMap::new();
913913
signal_counts.insert("panic_signal".to_string(), 1);
914-
audience::AudienceReport {
914+
axial::AxialReport {
915915
created_at: chrono::Utc::now().to_rfc3339(),
916916
target: PathBuf::from("src/main.rs"),
917917
executed_program: Some("panic-attack".to_string()),
918918
repeat: 1,
919919
observed_runs: 1,
920920
observed_reports: 0,
921921
language: "en".to_string(),
922-
run_observations: vec![audience::RunObservation {
922+
run_observations: vec![axial::RunObservation {
923923
run_index: 1,
924924
success: false,
925925
exit_code: Some(1),
@@ -931,14 +931,14 @@ mod tests {
931931
stdout_tail: Vec::new(),
932932
stderr_head: vec!["panic".to_string()],
933933
stderr_tail: vec!["panic".to_string()],
934-
matches: vec![audience::PatternMatch {
934+
matches: vec![axial::PatternMatch {
935935
mode: "grep".to_string(),
936936
pattern: "panic".to_string(),
937937
line_no: 1,
938938
line: "panic".to_string(),
939939
distance: None,
940940
}],
941-
signals: vec![audience::Signal {
941+
signals: vec![axial::Signal {
942942
severity: "high".to_string(),
943943
name: "panic_signal".to_string(),
944944
evidence: "panic found in stderr".to_string(),
@@ -948,7 +948,7 @@ mod tests {
948948
report_observations: Vec::new(),
949949
signal_counts,
950950
recommendations: vec!["review panic path".to_string()],
951-
aspell: Some(audience::SpellcheckSummary {
951+
aspell: Some(axial::SpellcheckSummary {
952952
lang: "en".to_string(),
953953
total_misspellings: 0,
954954
run_observations_with_misspellings: 0,
@@ -1055,13 +1055,13 @@ mod tests {
10551055
}
10561056

10571057
#[test]
1058-
fn report_bundle_roundtrip_audience() {
1059-
let bundle = ReportBundle::new(ReportBundlePayload::Audience(sample_audience_report()));
1058+
fn report_bundle_roundtrip_axial() {
1059+
let bundle = ReportBundle::new(ReportBundlePayload::Axial(sample_axial_report()));
10601060
let rendered = render_report_bundle(&bundle).expect("render should succeed");
10611061
let parsed = parse_report_bundle(&rendered).expect("parse should succeed");
1062-
assert_eq!(parsed.kind(), ReportBundleKind::Audience);
1062+
assert_eq!(parsed.kind(), ReportBundleKind::Axial);
10631063
let payload = match parsed.payload {
1064-
ReportBundlePayload::Audience(v) => v,
1064+
ReportBundlePayload::Axial(v) => v,
10651065
_ => panic!("wrong payload type"),
10661066
};
10671067
assert_eq!(payload.observed_runs, 1);
@@ -1102,8 +1102,8 @@ mod tests {
11021102
ReportBundlePayload::Adjudicate(sample_adjudicate_report()),
11031103
),
11041104
(
1105-
ReportBundleKind::Audience,
1106-
ReportBundlePayload::Audience(sample_audience_report()),
1105+
ReportBundleKind::Axial,
1106+
ReportBundlePayload::Axial(sample_axial_report()),
11071107
),
11081108
];
11091109

@@ -1126,7 +1126,7 @@ mod tests {
11261126
ReportBundlePayload::Amuck(v) => serde_json::to_string_pretty(v),
11271127
ReportBundlePayload::Abduct(v) => serde_json::to_string_pretty(v),
11281128
ReportBundlePayload::Adjudicate(v) => serde_json::to_string_pretty(v),
1129-
ReportBundlePayload::Audience(v) => serde_json::to_string_pretty(v),
1129+
ReportBundlePayload::Axial(v) => serde_json::to_string_pretty(v),
11301130
}
11311131
.expect("payload should serialize");
11321132
fs::write(&input, json).expect("input should write");
@@ -1155,8 +1155,8 @@ mod tests {
11551155
ReportBundleKind::Adjudicate => {
11561156
serde_json::from_str::<adjudicate::AdjudicateReport>(&output_body).map(|_| ())
11571157
}
1158-
ReportBundleKind::Audience => {
1159-
serde_json::from_str::<audience::AudienceReport>(&output_body).map(|_| ())
1158+
ReportBundleKind::Axial => {
1159+
serde_json::from_str::<axial::AxialReport>(&output_body).map(|_| ())
11601160
}
11611161
};
11621162
assert!(

0 commit comments

Comments
 (0)