fluent-fallback_for_carbide 0.7.0

High-level abstraction model for managing localization resources and runtime localization lifecycle.
Documentation
// //! This is an example of a simple application
// //! which calculates the Collatz conjecture.
// //!
// //! The function itself is trivial on purpose,
// //! so that we can focus on understanding how
// //! the application can be made localizable
// //! via Fluent.
// //!
// //! To try the app launch `cargo run --example simple-fallback NUM (LOCALES)`
// //!
// //! NUM is a number to be calculated, and LOCALES is an optional
// //! parameter with a comma-separated list of locales requested by the user.
// //!
// //! Example:
// //!
// //!   cargo run --example simple-fallback 123 de,pl
// //!
// //! If the second argument is omitted, `en-US` locale is used as the
// //! default one.
//
// use std::{env, fs, io, path::PathBuf, str::FromStr};
//
// use fluent_bundle::{FluentArgs, FluentBundle, FluentResource};
// use fluent_fallback::{
//     generator::{BundleGenerator, FluentBundleResult},
//     types::ResourceId,
//     Localization,
// };
// use fluent_langneg::{negotiate_languages, NegotiationStrategy};
//
// use rustc_hash::FxHashSet;
// use icu::locid::{locale, Locale};
//
// /// This helper struct holds the scheme for converting
// /// resource paths into full paths. It is used to customise
// /// `fluent-fallback::SyncLocalization`.
// struct Bundles {
//     res_path_scheme: PathBuf,
// }
//
// /// This helper function allows us to read the list
// /// of available locales by reading the list of
// /// directories in `./examples/resources`.
// ///
// /// It is expected that every directory inside it
// /// has a name that is a valid BCP47 language tag.
// fn get_available_locales() -> io::Result<Vec<Locale>> {
//     let mut dir = env::current_dir()?;
//     if dir.to_string_lossy().ends_with("fluent-rs") {
//         dir.push("fluent-fallback");
//     }
//     dir.push("examples");
//     dir.push("resources");
//     let res_dir = fs::read_dir(dir)?;
//
//     let locales = res_dir
//         .into_iter()
//         .filter_map(|entry| entry.ok())
//         .filter(|entry| entry.path().is_dir())
//         .filter_map(|dir| {
//             let file_name = dir.file_name();
//             let name = file_name.to_str()?;
//             Some(name.parse().expect("Parsing failed."))
//         })
//         .collect();
//     Ok(locales)
// }
//
// fn resolve_app_locales<'l>(args: &[String]) -> Vec<Locale> {
//     let default_locale = locale!("en-US");
//     let available = get_available_locales().expect("Retrieving available locales failed.");
//
//     let requested: Vec<Locale> = args.get(2).map_or(vec![], |arg| {
//         arg.split(',')
//             .map(|s| s.parse().expect("Parsing locale failed."))
//             .collect()
//     });
//
//     negotiate_languages(
//         &requested,
//         &available,
//         Some(&default_locale),
//         NegotiationStrategy::Filtering,
//     )
//     .into_iter()
//     .cloned()
//     .collect()
// }
//
// fn get_resource_manager() -> Bundles {
//     let mut res_path_scheme = env::current_dir().expect("Failed to retrieve current dir.");
//
//     if res_path_scheme.to_string_lossy().ends_with("fluent-rs") {
//         res_path_scheme.push("fluent-fallback");
//     }
//     res_path_scheme.push("examples");
//     res_path_scheme.push("resources");
//
//     res_path_scheme.push("{locale}");
//     res_path_scheme.push("{res_id}");
//
//     Bundles { res_path_scheme }
// }
//
// static L10N_RESOURCES: &[&str] = &["simple.ftl"];
//
// fn main() {
//     let args: Vec<String> = env::args().collect();
//
//     let app_locales: Vec<Locale> = resolve_app_locales(&args);
//
//     let bundles = get_resource_manager();
//
//     let loc = Localization::with_env(
//         L10N_RESOURCES.iter().map(|&res| res.into()),
//         true,
//         app_locales,
//         bundles,
//     );
//     let bundles = loc.bundles();
//
//     let mut errors = vec![];
//
//     match args.get(1) {
//         Some(input) => match isize::from_str(input) {
//             Ok(i) => {
//                 let mut args = FluentArgs::new();
//                 args.set("input", i);
//                 args.set("value", collatz(i));
//                 let value = bundles
//                     .format_value_sync("response-msg", Some(&args), &mut errors)
//                     .unwrap()
//                     .unwrap();
//                 println!("{}", value);
//             }
//             Err(err) => {
//                 let mut args = FluentArgs::new();
//                 args.set("input", input.as_str());
//                 args.set("reason", err.to_string());
//                 let value = bundles
//                     .format_value_sync("input-parse-error-msg", Some(&args), &mut errors)
//                     .unwrap()
//                     .unwrap();
//                 println!("{}", value);
//             }
//         },
//         None => {
//             let value = bundles
//                 .format_value_sync("missing-arg-error", None, &mut errors)
//                 .unwrap()
//                 .unwrap();
//             println!("{}", value);
//         }
//     }
// }
//
// /// Collatz conjecture calculating function.
// fn collatz(n: isize) -> isize {
//     match n {
//         1 => 0,
//         _ => match n % 2 {
//             0 => 1 + collatz(n / 2),
//             _ => 1 + collatz(n * 3 + 1),
//         },
//     }
// }
//
// /// Bundle iterator used by BundleGeneratorSync implementation for Locales.
// struct BundleIter {
//     res_path_scheme: String,
//     locales: <Vec<Locale> as IntoIterator>::IntoIter,
//     res_ids: FxHashSet<ResourceId>,
// }
//
// impl Iterator for BundleIter {
//     type Item = FluentBundleResult<FluentResource>;
//
//     fn next(&mut self) -> Option<Self::Item> {
//         let locale = self.locales.next()?;
//         let res_path_scheme = self
//             .res_path_scheme
//             .as_str()
//             .replace("{locale}", &locale.to_string());
//         let mut bundle = FluentBundle::new(vec![locale]);
//
//         let mut errors = vec![];
//
//         for res_id in &self.res_ids {
//             let res_path = res_path_scheme.as_str().replace("{res_id}", &res_id.value);
//             let source = fs::read_to_string(res_path).unwrap();
//             let res = match FluentResource::try_new(source) {
//                 Ok(res) => res,
//                 Err((res, err)) => {
//                     errors.extend(err.into_iter().map(Into::into));
//                     res
//                 }
//             };
//             bundle.add_resource(res).unwrap();
//         }
//
//         if errors.is_empty() {
//             Some(Ok(bundle))
//         } else {
//             Some(Err((bundle, errors)))
//         }
//     }
// }
//
// impl futures::Stream for BundleIter {
//     type Item = FluentBundleResult<FluentResource>;
//
//     fn poll_next(
//         self: std::pin::Pin<&mut Self>,
//         _cx: &mut std::task::Context<'_>,
//     ) -> std::task::Poll<Option<Self::Item>> {
//         todo!()
//     }
// }
//
// impl BundleGenerator for Bundles {
//     type Resource = FluentResource;
//     type LocalesIter = std::vec::IntoIter<Locale>;
//     type Iter = BundleIter;
//     type Stream = BundleIter;
//
//     fn bundles_iter(
//         &self,
//         locales: std::vec::IntoIter<Locale>,
//         res_ids: FxHashSet<ResourceId>,
//     ) -> Self::Iter {
//         BundleIter {
//             res_path_scheme: self.res_path_scheme.to_string_lossy().to_string(),
//             locales,
//             res_ids,
//         }
//     }
// }

fn main() {

}