Skip to main content

workshop_rs/output/
convert.rs

1use crate::catalog::{Catalog, Locale};
2use crate::core::error::Result;
3use crate::core::signatures::ExpectedDomain;
4use crate::frontend::parser;
5use crate::output::emitter::{self, EmitOptions};
6
7/// Conversion options: opt-in fallback for missing target-locale mappings.
8#[derive(Debug, Clone, Default, PartialEq, Eq)]
9#[non_exhaustive]
10pub struct ConvertOptions {
11    /// When a canonical identity has no spelling for the target locale, its
12    /// spelling in this declared locale is used instead. `None` (the
13    /// default) keeps missing mappings failing explicitly. The fallback
14    /// choice is visible in [`Conversion::fallback_ids`].
15    pub fallback_locale: Option<Locale>,
16}
17
18/// The result of a raw Workshop locale conversion.
19#[derive(Debug, Clone, PartialEq, Eq)]
20#[non_exhaustive]
21pub struct Conversion {
22    /// The converted localized Workshop text.
23    pub text: String,
24    /// Canonical identities (and the `settings` marker) whose spelling came
25    /// from the opt-in fallback locale instead of the target locale. Empty
26    /// when no fallback occurred.
27    pub fallback_ids: Vec<String>,
28}
29
30/// Convert raw Workshop text from `from` to `to`, parsing with the catalog as
31/// the canonical signature context (expected enum domains resolve ambiguous
32/// bare members that the catalog documents).
33pub fn convert(
34    input: &str,
35    catalog: &Catalog,
36    from: &Locale,
37    to: &Locale,
38    options: &ConvertOptions,
39) -> Result<Conversion> {
40    convert_with_context(input, catalog, from, to, options, catalog)
41}
42
43/// The context-aware form of [`convert`]: `context` supplies the expected
44/// enum domains for argument positions the catalog does not document (e.g. a
45/// provider manifest chained with the catalog via
46/// [`crate::core::signatures::ChainedExpectedDomain`]).
47pub fn convert_with_context(
48    input: &str,
49    catalog: &Catalog,
50    from: &Locale,
51    to: &Locale,
52    options: &ConvertOptions,
53    context: &dyn ExpectedDomain,
54) -> Result<Conversion> {
55    let program = parser::parse_with_context(input, catalog, from, context)?;
56    let emit_options = EmitOptions {
57        fallback_locale: options.fallback_locale.clone(),
58    };
59    let output = emitter::emit_with_options(&program, catalog, to, &emit_options)?;
60    Ok(Conversion {
61        text: output.text,
62        fallback_ids: output.fallback_ids,
63    })
64}