tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

localization.rs (5744B)


      1 use std::borrow::Cow;
      2 
      3 use fluent_fallback::{
      4    env::LocalesProvider,
      5    types::{L10nKey, ResourceId},
      6    Localization,
      7 };
      8 use l10nregistry_tests::{
      9    FileSource, MockBundleAdapter, RegistrySetup, TestEnvironment, TestFileFetcher,
     10 };
     11 use serial_test::serial;
     12 use unic_langid::{langid, LanguageIdentifier};
     13 
     14 type L10nRegistry = l10nregistry::registry::L10nRegistry<TestEnvironment, MockBundleAdapter>;
     15 
     16 static LOCALES: &[LanguageIdentifier] = &[langid!("pl"), langid!("en-US")];
     17 static mut FILE_FETCHER: Option<TestFileFetcher> = None;
     18 static mut L10N_REGISTRY: Option<L10nRegistry> = None;
     19 
     20 const FTL_RESOURCE: &str = "toolkit/updates/history.ftl";
     21 const L10N_ID_PL_EN: (&str, Option<&str>) = ("history-title", Some("Historia aktualizacji"));
     22 const L10N_ID_MISSING: (&str, Option<&str>) = ("missing-id", None);
     23 const L10N_ID_ONLY_EN: (&str, Option<&str>) = (
     24    "history-intro",
     25    Some("The following updates have been installed"),
     26 );
     27 
     28 fn get_file_fetcher() -> &'static TestFileFetcher {
     29    let fetcher: &mut Option<TestFileFetcher> = unsafe { &mut FILE_FETCHER };
     30 
     31    fetcher.get_or_insert_with(|| TestFileFetcher::new())
     32 }
     33 
     34 fn get_l10n_registry() -> &'static L10nRegistry {
     35    let reg: &mut Option<L10nRegistry> = unsafe { &mut L10N_REGISTRY };
     36 
     37    reg.get_or_insert_with(|| {
     38        let fetcher = get_file_fetcher();
     39        let setup = RegistrySetup::new(
     40            "test",
     41            vec![
     42                FileSource::new(
     43                    "toolkit",
     44                    None,
     45                    get_app_locales().to_vec(),
     46                    "toolkit/{locale}/",
     47                ),
     48                FileSource::new(
     49                    "browser",
     50                    None,
     51                    get_app_locales().to_vec(),
     52                    "browser/{locale}/",
     53                ),
     54            ],
     55            get_app_locales().to_vec(),
     56        );
     57        fetcher.get_registry_and_environment(setup).1
     58    })
     59 }
     60 
     61 fn get_app_locales() -> &'static [LanguageIdentifier] {
     62    LOCALES
     63 }
     64 
     65 struct LocalesService;
     66 
     67 impl LocalesProvider for LocalesService {
     68    type Iter = std::vec::IntoIter<LanguageIdentifier>;
     69 
     70    fn locales(&self) -> Self::Iter {
     71        get_app_locales().to_vec().into_iter()
     72    }
     73 }
     74 
     75 fn sync_localization(
     76    reg: &'static L10nRegistry,
     77    res_ids: Vec<ResourceId>,
     78 ) -> Localization<L10nRegistry, LocalesService> {
     79    Localization::with_env(res_ids, true, LocalesService, reg.clone())
     80 }
     81 
     82 fn async_localization(
     83    reg: &'static L10nRegistry,
     84    res_ids: Vec<ResourceId>,
     85 ) -> Localization<L10nRegistry, LocalesService> {
     86    Localization::with_env(res_ids, false, LocalesService, reg.clone())
     87 }
     88 
     89 fn setup_sync_test() -> Localization<L10nRegistry, LocalesService> {
     90    sync_localization(get_l10n_registry(), vec![FTL_RESOURCE.into()])
     91 }
     92 
     93 fn setup_async_test() -> Localization<L10nRegistry, LocalesService> {
     94    async_localization(get_l10n_registry(), vec![FTL_RESOURCE.into()])
     95 }
     96 
     97 #[test]
     98 #[serial]
     99 fn localization_format_value_sync() {
    100    let loc = setup_sync_test();
    101    let bundles = loc.bundles();
    102    let mut errors = vec![];
    103 
    104    for query in &[L10N_ID_PL_EN, L10N_ID_MISSING, L10N_ID_ONLY_EN] {
    105        let value = bundles
    106            .format_value_sync(query.0, None, &mut errors)
    107            .unwrap();
    108        assert_eq!(value, query.1.map(|s| Cow::Borrowed(s)));
    109    }
    110 
    111    assert_eq!(errors.len(), 4);
    112 }
    113 
    114 #[test]
    115 #[serial]
    116 fn localization_format_values_sync() {
    117    let loc = setup_sync_test();
    118    let bundles = loc.bundles();
    119    let mut errors = vec![];
    120 
    121    let ids = &[L10N_ID_PL_EN, L10N_ID_MISSING, L10N_ID_ONLY_EN];
    122    let keys = ids
    123        .iter()
    124        .map(|query| L10nKey {
    125            id: query.0.into(),
    126            args: None,
    127        })
    128        .collect::<Vec<_>>();
    129 
    130    let values = bundles.format_values_sync(&keys, &mut errors).unwrap();
    131 
    132    assert_eq!(values.len(), ids.len());
    133 
    134    for (value, query) in values.iter().zip(ids) {
    135        if let Some(expected) = query.1 {
    136            assert_eq!(*value, Some(Cow::Borrowed(expected)));
    137        }
    138    }
    139    assert_eq!(errors.len(), 4);
    140 }
    141 
    142 #[tokio::test]
    143 #[serial]
    144 async fn localization_format_value_async() {
    145    let loc = setup_async_test();
    146    let bundles = loc.bundles();
    147    let mut errors = vec![];
    148 
    149    for query in &[L10N_ID_PL_EN, L10N_ID_MISSING, L10N_ID_ONLY_EN] {
    150        let value = bundles.format_value(query.0, None, &mut errors).await;
    151        if let Some(expected) = query.1 {
    152            assert_eq!(value, Some(Cow::Borrowed(expected)));
    153        }
    154    }
    155 }
    156 
    157 #[tokio::test]
    158 #[serial]
    159 async fn localization_format_values_async() {
    160    let loc = setup_async_test();
    161    let bundles = loc.bundles();
    162    let mut errors = vec![];
    163 
    164    let ids = &[L10N_ID_PL_EN, L10N_ID_MISSING, L10N_ID_ONLY_EN];
    165    let keys = ids
    166        .iter()
    167        .map(|query| L10nKey {
    168            id: query.0.into(),
    169            args: None,
    170        })
    171        .collect::<Vec<_>>();
    172 
    173    let values = bundles.format_values(&keys, &mut errors).await;
    174 
    175    assert_eq!(values.len(), ids.len());
    176 
    177    for (value, query) in values.iter().zip(ids) {
    178        if let Some(expected) = query.1 {
    179            assert_eq!(*value, Some(Cow::Borrowed(expected)));
    180        }
    181    }
    182 }
    183 
    184 #[tokio::test]
    185 #[serial]
    186 async fn localization_upgrade() {
    187    let mut loc = setup_sync_test();
    188    let bundles = loc.bundles();
    189    let mut errors = vec![];
    190    let value = bundles
    191        .format_value_sync(L10N_ID_PL_EN.0, None, &mut errors)
    192        .unwrap();
    193    assert_eq!(value, L10N_ID_PL_EN.1.map(|s| Cow::Borrowed(s)));
    194 
    195    loc.set_async();
    196    let bundles = loc.bundles();
    197    let value = bundles
    198        .format_value(L10N_ID_PL_EN.0, None, &mut errors)
    199        .await;
    200    assert_eq!(value, L10N_ID_PL_EN.1.map(|s| Cow::Borrowed(s)));
    201 }