From dce4938b91cc864c050b649ae2b8fc1de9899a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?= Date: Sun, 30 Jun 2024 23:57:45 +0200 Subject: [PATCH] Don't panic if no language name found (#186) --- book/src/install.md | 28 +- book/src/languages.md | 20 -- leptos-fluent-macros/src/languages.rs | 26 +- leptos-fluent-macros/src/lib.rs | 499 ++++++++++++++------------ leptos-fluent-macros/src/loader.rs | 68 ++-- 5 files changed, 343 insertions(+), 298 deletions(-) diff --git a/book/src/install.md b/book/src/install.md index 9e10017e..f0b30932 100644 --- a/book/src/install.md +++ b/book/src/install.md @@ -89,14 +89,16 @@ By default, **leptos-fluent** supports JSON languages files. To use other formats to load custom languages, the `json5` or `yaml` features can be enabled: + + ```toml [dependencies] fluent-templates = "0.9" -leptos-fluent = { - version = "0.1", features = ["json5"], default-features = false -} +leptos-fluent = { version = "0.1", features = ["json5"], default-features = false } ``` + + ```admonish tip See [**4. Languages**](https://mondeja.github.io/leptos-fluent/languages.html). ``` @@ -113,5 +115,25 @@ See [**4. Languages**](https://mondeja.github.io/leptos-fluent/languages.html). - **YAML languages file**: `yaml` - **JSON5 languages file**: `json5` +## Tracking locales files with [`cargo leptos`] + +Using [`cargo leptos`] watch of the _locales/_ folder for reloads: + +```toml +# Relative to Cargo.toml file +[package.metadata.leptos] +watch-additional-files = ["locales"] +``` + +When inside a workspace, use the full path to the folder from the +workspace _Cargo.toml_ file: + +```toml + # Relative to workspace Cargo.toml file +[package.metadata.leptos] +watch-additional-files = ["examples/csr/locales"] +``` + [`fluent-templates`]: https://github.com/XAMPPRocky/fluent-templates [`leptos_fluent!`]: https://mondeja.github.io/leptos-fluent/leptos_fluent.html +[`cargo leptos`]: https://github.com/leptos-rs/cargo-leptos diff --git a/book/src/languages.md b/book/src/languages.md index c969161f..17a725cf 100644 --- a/book/src/languages.md +++ b/book/src/languages.md @@ -127,25 +127,5 @@ Available features for languages file formats are: - `yaml`: YAML - `json5`: JSON5 -## Tracking locales files with [`cargo leptos`] - -Using [`cargo leptos`] watch of the _locales/_ folder for reloads: - -```toml -# Relative to Cargo.toml file -[package.metadata.leptos] -watch-additional-files = ["locales"] -``` - -When inside a workspace, use the full path to the folder from the -workspace _Cargo.toml_ file: - -```toml - # Relative to workspace Cargo.toml file -[package.metadata.leptos] -watch-additional-files = ["examples/csr/locales"] -``` - [ISO 639-1 code]: https://en.wikipedia.org/wiki/ISO_639-1 -[`cargo leptos`]: https://github.com/leptos-rs/cargo-leptos [`leptos_fluent!`]: https://mondeja.github.io/leptos-fluent/leptos_fluent.html diff --git a/leptos-fluent-macros/src/languages.rs b/leptos-fluent-macros/src/languages.rs index 88120bc5..1abb3376 100644 --- a/leptos-fluent-macros/src/languages.rs +++ b/leptos-fluent-macros/src/languages.rs @@ -1,7 +1,7 @@ use std::fs; use std::path::PathBuf; -type BuiltLanguagesFileLanguage = (String, String, String, Option); +pub(crate) type ParsedLanguage = (String, String, String, Option); #[cfg(any(feature = "json", feature = "yaml", feature = "json5"))] #[derive(serde::Deserialize)] @@ -15,7 +15,7 @@ enum RawLanguagesFileLanguage { #[cfg(any(feature = "json", feature = "yaml", feature = "json5"))] fn fill_languages_file( languages: &[RawLanguagesFileLanguage], -) -> Vec<(String, String, String, Option)> { +) -> Vec { let mut locales = vec![]; for tuple in languages { match tuple { @@ -69,7 +69,7 @@ fn fill_languages_file( pub(crate) fn read_languages_file( path: &PathBuf, -) -> Result, String> { +) -> Result, String> { #[cfg(feature = "json")] { let file_extension = path.extension().unwrap_or_default(); @@ -191,7 +191,9 @@ pub(crate) fn read_languages_file( pub(crate) fn read_locales_folder( path: &PathBuf, -) -> Vec<(String, String, String, Option)> { +) -> (Vec, Vec) { + let mut errors = vec![]; + let mut iso639_language_codes = vec![]; let mut entries = vec![]; for entry in fs::read_dir(path).expect("Couldn't read locales folder") { @@ -222,6 +224,16 @@ pub(crate) fn read_locales_folder( > 1; let lang_name = language_name_from_language_code(&lang_code, use_country_code); + if lang_name.is_empty() { + errors.push(format!( + concat!( + "Couldn't find language name for code \"{}\". Provide it", + " from a languages file (see `languages` parameter).", + ), + lang_code, + )); + continue; + } let lang_dir = iso639_to_dir(&iso639_code); let flag = match code_to_country_code(&lang_code) { Some(country_code) => country_code_to_emoji_flag(&country_code), @@ -235,11 +247,11 @@ pub(crate) fn read_locales_folder( )); } locales.sort_by(|a, b| a.1.cmp(&b.1)); - locales + (locales, errors) } pub(crate) fn build_languages_quote( - languages: &[(String, String, String, Option)], + languages: &[ParsedLanguage], ) -> proc_macro2::TokenStream { format!( "[{}]", @@ -1950,7 +1962,7 @@ fn language_name_from_language_code( "za" => "Saɯ cueŋƅ", "zh" => "中文", "zu" => "isiZulu", - _ => panic!("Language name for language code '{code}' not found",), + _ => "", } } diff --git a/leptos-fluent-macros/src/lib.rs b/leptos-fluent-macros/src/lib.rs index da5303dd..4fe2e854 100644 --- a/leptos-fluent-macros/src/lib.rs +++ b/leptos-fluent-macros/src/lib.rs @@ -25,6 +25,7 @@ pub(crate) use fluent_resources::{ build_fluent_resources_and_file_paths, FluentFilePaths, }; use languages::build_languages_quote; +pub(crate) use languages::ParsedLanguage; use loader::I18nLoader; use quote::quote; @@ -92,7 +93,6 @@ pub fn leptos_fluent( core_locales_path, check_translations, provide_meta_context, - provide_meta_context_exprpath, sync_html_tag_lang, sync_html_tag_dir, initial_language_from_url_param, @@ -355,7 +355,7 @@ pub fn leptos_fluent( #[cfg(all(feature = "system", not(feature = "ssr")))] let initial_language_from_data_file_quote = { let initial_language_from_data_file_quote = { - let quote = match initial_language_from_data_file.lit { + match initial_language_from_data_file.lit { Some(ref lit) => match lit.value() { true => quote! { #data_file_key_quote }, false => quote! { "" }, @@ -370,11 +370,6 @@ pub fn leptos_fluent( }, None => quote! { "" }, }, - }; - - match initial_language_from_data_file.exprpath { - Some(ref path) => quote! { #path{#quote} }, - None => quote, } }; @@ -392,7 +387,7 @@ pub fn leptos_fluent( } }; - match initial_language_from_data_file.lit { + let quote = match initial_language_from_data_file.lit { Some(ref lit) => match lit.value() { true => quote! { if lang.is_none() { @@ -409,6 +404,11 @@ pub fn leptos_fluent( }, None => quote! {}, }, + }; + + match initial_language_from_data_file.exprpath { + Some(ref path) => quote! { #path{#quote} }, + None => quote, } }; @@ -1547,254 +1547,277 @@ pub fn leptos_fluent( }} }; - let leptos_fluent_provide_meta_context_quote = match provide_meta_context { - true => { - let bool_param = |boolean: Option, - expr: Option| - -> proc_macro2::TokenStream { - match boolean { - Some(ref lit) => quote! { #lit }, - None => match expr { - Some(ref expr) => quote! { #expr }, - None => quote! { false }, - }, - } - }; - - let maybe_litstr_param = - |lit: Option| -> proc_macro2::TokenStream { - match lit { + let provide_meta_context_value = match provide_meta_context.lit { + Some(ref lit) => lit.value(), + None => false, + }; + let leptos_fluent_provide_meta_context_quote = + match provide_meta_context_value { + true => { + let bool_param = |boolean: Option, + expr: Option| + -> proc_macro2::TokenStream { + match boolean { Some(ref lit) => quote! { #lit }, - None => quote! { None }, - } - }; - - let maybe_some_litstr_param = - |lit: Option| -> proc_macro2::TokenStream { - match lit { - Some(ref lit) => quote! { Some(#lit) }, - None => quote! { None }, + None => match expr { + Some(ref expr) => quote! { #expr }, + None => quote! { false }, + }, } }; - let litstr_or_default = |lit: Option, - expr: Option, - default: &str| - -> proc_macro2::TokenStream { - match lit { - Some(ref lit) => quote! { #lit }, - None => match expr { - Some(ref expr) => quote! { #expr }, - None => quote! { #default }, - }, - } - }; + let maybe_litstr_param = + |lit: Option| -> proc_macro2::TokenStream { + match lit { + Some(ref lit) => quote! { #lit }, + None => quote! { None }, + } + }; - let core_locales_quote = maybe_litstr_param(core_locales_path); - let languages_quote = maybe_some_litstr_param(raw_languages_path); - let check_translations_quote = - maybe_some_litstr_param(check_translations); - let sync_html_tag_lang_quote = - bool_param(sync_html_tag_lang.lit, sync_html_tag_lang.expr); - let sync_html_tag_dir_quote = - bool_param(sync_html_tag_dir.lit, sync_html_tag_dir.expr); - let url_param_quote = - litstr_or_default(url_param.lit, url_param.expr, "lang"); - let initial_language_from_url_param_quote = bool_param( - initial_language_from_url_param.lit, - initial_language_from_url_param.expr, - ); - let initial_language_from_url_param_to_localstorage = bool_param( - initial_language_from_url_param_to_localstorage.lit, - initial_language_from_url_param_to_localstorage.expr, - ); - let initial_language_from_url_param_to_cookie_quote = bool_param( - initial_language_from_url_param_to_cookie.lit, - initial_language_from_url_param_to_cookie.expr, - ); - let initial_language_from_url_param_to_server_function_quote = - match initial_language_from_url_param_to_server_function.ident { - Some(_) => quote! { true }, - None => quote! { false }, - }; - let set_language_to_url_param_quote = bool_param( - set_language_to_url_param.lit, - set_language_to_url_param.expr, - ); - let localstorage_key_quote = litstr_or_default( - localstorage_key.lit, - localstorage_key.expr, - "lang", - ); - let initial_language_from_localstorage_quote = bool_param( - initial_language_from_localstorage.lit, - initial_language_from_localstorage.expr, - ); - let initial_language_from_localstorage_to_cookie_quote = bool_param( - initial_language_from_localstorage_to_cookie.lit, - initial_language_from_localstorage_to_cookie.expr, - ); - let initial_language_from_localstorage_to_server_function_quote = - match initial_language_from_localstorage_to_server_function - .ident - { - Some(_) => quote! { true }, - None => quote! { false }, - }; - let set_language_to_localstorage_quote = bool_param( - set_language_to_localstorage.lit, - set_language_to_localstorage.expr, - ); - let initial_language_from_navigator_quote = bool_param( - initial_language_from_navigator.lit, - initial_language_from_navigator.expr, - ); - let initial_language_from_navigator_to_localstorage_quote = - bool_param( - initial_language_from_navigator_to_localstorage.lit, - initial_language_from_navigator_to_localstorage.expr, + let maybe_some_litstr_param = + |lit: Option| -> proc_macro2::TokenStream { + match lit { + Some(ref lit) => quote! { Some(#lit) }, + None => quote! { None }, + } + }; + + let litstr_or_default = + |lit: Option, + expr: Option, + default: &str| + -> proc_macro2::TokenStream { + match lit { + Some(ref lit) => quote! { #lit }, + None => match expr { + Some(ref expr) => quote! { #expr }, + None => quote! { #default }, + }, + } + }; + + let core_locales_quote = maybe_litstr_param(core_locales_path); + let languages_quote = + maybe_some_litstr_param(raw_languages_path); + let check_translations_quote = + maybe_some_litstr_param(check_translations); + let sync_html_tag_lang_quote = + bool_param(sync_html_tag_lang.lit, sync_html_tag_lang.expr); + let sync_html_tag_dir_quote = + bool_param(sync_html_tag_dir.lit, sync_html_tag_dir.expr); + let url_param_quote = + litstr_or_default(url_param.lit, url_param.expr, "lang"); + let initial_language_from_url_param_quote = bool_param( + initial_language_from_url_param.lit, + initial_language_from_url_param.expr, ); - let initial_language_from_navigator_to_cookie_quote = bool_param( - initial_language_from_navigator_to_cookie.lit, - initial_language_from_navigator_to_cookie.expr, - ); - let initial_language_from_navigator_to_server_function_quote = - match initial_language_from_navigator_to_server_function.ident { - Some(_) => quote! { true }, - None => quote! { false }, - }; - let initial_language_from_accept_language_header_quote = bool_param( - initial_language_from_accept_language_header.lit, - initial_language_from_accept_language_header.expr, - ); - let cookie_name_quote = - litstr_or_default(cookie_name.lit, cookie_name.expr, "lf-lang"); - let cookie_attrs_quote = - litstr_or_default(cookie_attrs.lit, cookie_attrs.expr, ""); - let initial_language_from_cookie_quote = bool_param( - initial_language_from_cookie.lit, - initial_language_from_cookie.expr, - ); - let initial_language_from_cookie_to_localstorage_quote = bool_param( - initial_language_from_cookie_to_localstorage.lit, - initial_language_from_cookie_to_localstorage.expr, - ); - let initial_language_from_cookie_to_server_function_quote = - match initial_language_from_cookie_to_server_function.ident { - Some(_) => quote! { true }, - None => quote! { false }, - }; - let set_language_to_cookie_quote = bool_param( - set_language_to_cookie.lit, - set_language_to_cookie.expr, - ); - let initial_language_from_server_function_quote = - match initial_language_from_server_function.ident { - Some(_) => quote! { true }, - None => quote! { false }, - }; - let initial_language_from_server_function_to_cookie_quote = - bool_param( - initial_language_from_server_function_to_cookie.lit, - initial_language_from_server_function_to_cookie.expr, + let initial_language_from_url_param_to_localstorage = + bool_param( + initial_language_from_url_param_to_localstorage.lit, + initial_language_from_url_param_to_localstorage.expr, + ); + let initial_language_from_url_param_to_cookie_quote = + bool_param( + initial_language_from_url_param_to_cookie.lit, + initial_language_from_url_param_to_cookie.expr, + ); + let initial_language_from_url_param_to_server_function_quote = + match initial_language_from_url_param_to_server_function + .ident + { + Some(_) => quote! { true }, + None => quote! { false }, + }; + let set_language_to_url_param_quote = bool_param( + set_language_to_url_param.lit, + set_language_to_url_param.expr, ); - let initial_language_from_server_function_to_localstorage_quote = - bool_param( - initial_language_from_server_function_to_localstorage.lit, - initial_language_from_server_function_to_localstorage.expr, + let localstorage_key_quote = litstr_or_default( + localstorage_key.lit, + localstorage_key.expr, + "lang", ); - let set_language_to_server_function_quote = - match set_language_to_server_function.ident { - Some(_) => quote! { true }, - None => quote! { false }, - }; - - let system_quote = { - #[cfg(not(feature = "system"))] - quote! {} - - #[cfg(feature = "system")] - { - let initial_language_from_system_quote = bool_param( - initial_language_from_system.lit, - initial_language_from_system.expr, + let initial_language_from_localstorage_quote = bool_param( + initial_language_from_localstorage.lit, + initial_language_from_localstorage.expr, + ); + let initial_language_from_localstorage_to_cookie_quote = + bool_param( + initial_language_from_localstorage_to_cookie.lit, + initial_language_from_localstorage_to_cookie.expr, ); - let initial_language_from_data_file_quote = bool_param( - initial_language_from_data_file.lit, - initial_language_from_data_file.expr, + let initial_language_from_localstorage_to_server_function_quote = + match initial_language_from_localstorage_to_server_function + .ident + { + Some(_) => quote! { true }, + None => quote! { false }, + }; + let set_language_to_localstorage_quote = bool_param( + set_language_to_localstorage.lit, + set_language_to_localstorage.expr, + ); + let initial_language_from_navigator_quote = bool_param( + initial_language_from_navigator.lit, + initial_language_from_navigator.expr, + ); + let initial_language_from_navigator_to_localstorage_quote = + bool_param( + initial_language_from_navigator_to_localstorage.lit, + initial_language_from_navigator_to_localstorage.expr, ); - let initial_language_from_system_to_data_file_quote = - bool_param( - initial_language_from_system_to_data_file.lit, - initial_language_from_system_to_data_file.expr, - ); - let set_language_to_data_file_quote = bool_param( - set_language_to_data_file.lit, - set_language_to_data_file.expr, + let initial_language_from_navigator_to_cookie_quote = + bool_param( + initial_language_from_navigator_to_cookie.lit, + initial_language_from_navigator_to_cookie.expr, + ); + let initial_language_from_navigator_to_server_function_quote = + match initial_language_from_navigator_to_server_function + .ident + { + Some(_) => quote! { true }, + None => quote! { false }, + }; + let initial_language_from_accept_language_header_quote = + bool_param( + initial_language_from_accept_language_header.lit, + initial_language_from_accept_language_header.expr, + ); + let cookie_name_quote = litstr_or_default( + cookie_name.lit, + cookie_name.expr, + "lf-lang", + ); + let cookie_attrs_quote = + litstr_or_default(cookie_attrs.lit, cookie_attrs.expr, ""); + let initial_language_from_cookie_quote = bool_param( + initial_language_from_cookie.lit, + initial_language_from_cookie.expr, + ); + let initial_language_from_cookie_to_localstorage_quote = + bool_param( + initial_language_from_cookie_to_localstorage.lit, + initial_language_from_cookie_to_localstorage.expr, ); - let data_file_key_quote = litstr_or_default( - data_file_key.lit, - data_file_key.expr, - "leptos-fluent", + let initial_language_from_cookie_to_server_function_quote = + match initial_language_from_cookie_to_server_function.ident + { + Some(_) => quote! { true }, + None => quote! { false }, + }; + let set_language_to_cookie_quote = bool_param( + set_language_to_cookie.lit, + set_language_to_cookie.expr, + ); + let initial_language_from_server_function_quote = + match initial_language_from_server_function.ident { + Some(_) => quote! { true }, + None => quote! { false }, + }; + let initial_language_from_server_function_to_cookie_quote = + bool_param( + initial_language_from_server_function_to_cookie.lit, + initial_language_from_server_function_to_cookie.expr, ); + let initial_language_from_server_function_to_localstorage_quote = + bool_param( + initial_language_from_server_function_to_localstorage + .lit, + initial_language_from_server_function_to_localstorage + .expr, + ); + let set_language_to_server_function_quote = + match set_language_to_server_function.ident { + Some(_) => quote! { true }, + None => quote! { false }, + }; + + let system_quote = { + #[cfg(not(feature = "system"))] + quote! {} + + #[cfg(feature = "system")] + { + let initial_language_from_system_quote = bool_param( + initial_language_from_system.lit, + initial_language_from_system.expr, + ); + let initial_language_from_data_file_quote = bool_param( + initial_language_from_data_file.lit, + initial_language_from_data_file.expr, + ); + let initial_language_from_system_to_data_file_quote = + bool_param( + initial_language_from_system_to_data_file.lit, + initial_language_from_system_to_data_file.expr, + ); + let set_language_to_data_file_quote = bool_param( + set_language_to_data_file.lit, + set_language_to_data_file.expr, + ); + let data_file_key_quote = litstr_or_default( + data_file_key.lit, + data_file_key.expr, + "leptos-fluent", + ); - quote! { - initial_language_from_system: #initial_language_from_system_quote, - initial_language_from_data_file: #initial_language_from_data_file_quote, - initial_language_from_system_to_data_file: #initial_language_from_system_to_data_file_quote, - set_language_to_data_file: #set_language_to_data_file_quote, - data_file_key: #data_file_key_quote, + quote! { + initial_language_from_system: #initial_language_from_system_quote, + initial_language_from_data_file: #initial_language_from_data_file_quote, + initial_language_from_system_to_data_file: #initial_language_from_system_to_data_file_quote, + set_language_to_data_file: #set_language_to_data_file_quote, + data_file_key: #data_file_key_quote, + } } - } - }; + }; - let quote = quote! { - const meta: ::leptos_fluent::LeptosFluentMeta = ::leptos_fluent::LeptosFluentMeta { - locales: #locales_path, - core_locales: #core_locales_quote, - languages: #languages_quote, - check_translations: #check_translations_quote, - sync_html_tag_lang: #sync_html_tag_lang_quote, - sync_html_tag_dir: #sync_html_tag_dir_quote, - url_param: #url_param_quote, - initial_language_from_url_param: #initial_language_from_url_param_quote, - initial_language_from_url_param_to_localstorage: #initial_language_from_url_param_to_localstorage, - initial_language_from_url_param_to_cookie: #initial_language_from_url_param_to_cookie_quote, - initial_language_from_url_param_to_server_function: #initial_language_from_url_param_to_server_function_quote, - set_language_to_url_param: #set_language_to_url_param_quote, - localstorage_key: #localstorage_key_quote, - initial_language_from_localstorage: #initial_language_from_localstorage_quote, - initial_language_from_localstorage_to_cookie: #initial_language_from_localstorage_to_cookie_quote, - initial_language_from_localstorage_to_server_function: #initial_language_from_localstorage_to_server_function_quote, - set_language_to_localstorage: #set_language_to_localstorage_quote, - initial_language_from_navigator: #initial_language_from_navigator_quote, - initial_language_from_navigator_to_localstorage: #initial_language_from_navigator_to_localstorage_quote, - initial_language_from_navigator_to_cookie: #initial_language_from_navigator_to_cookie_quote, - initial_language_from_navigator_to_server_function: #initial_language_from_navigator_to_server_function_quote, - initial_language_from_accept_language_header: #initial_language_from_accept_language_header_quote, - cookie_name: #cookie_name_quote, - cookie_attrs: #cookie_attrs_quote, - initial_language_from_cookie: #initial_language_from_cookie_quote, - initial_language_from_cookie_to_localstorage: #initial_language_from_cookie_to_localstorage_quote, - initial_language_from_cookie_to_server_function: #initial_language_from_cookie_to_server_function_quote, - set_language_to_cookie: #set_language_to_cookie_quote, - initial_language_from_server_function: #initial_language_from_server_function_quote, - initial_language_from_server_function_to_cookie: #initial_language_from_server_function_to_cookie_quote, - initial_language_from_server_function_to_localstorage: #initial_language_from_server_function_to_localstorage_quote, - set_language_to_server_function: #set_language_to_server_function_quote, - provide_meta_context: true, - #system_quote + let quote = quote! { + const meta: ::leptos_fluent::LeptosFluentMeta = ::leptos_fluent::LeptosFluentMeta { + locales: #locales_path, + core_locales: #core_locales_quote, + languages: #languages_quote, + check_translations: #check_translations_quote, + sync_html_tag_lang: #sync_html_tag_lang_quote, + sync_html_tag_dir: #sync_html_tag_dir_quote, + url_param: #url_param_quote, + initial_language_from_url_param: #initial_language_from_url_param_quote, + initial_language_from_url_param_to_localstorage: #initial_language_from_url_param_to_localstorage, + initial_language_from_url_param_to_cookie: #initial_language_from_url_param_to_cookie_quote, + initial_language_from_url_param_to_server_function: #initial_language_from_url_param_to_server_function_quote, + set_language_to_url_param: #set_language_to_url_param_quote, + localstorage_key: #localstorage_key_quote, + initial_language_from_localstorage: #initial_language_from_localstorage_quote, + initial_language_from_localstorage_to_cookie: #initial_language_from_localstorage_to_cookie_quote, + initial_language_from_localstorage_to_server_function: #initial_language_from_localstorage_to_server_function_quote, + set_language_to_localstorage: #set_language_to_localstorage_quote, + initial_language_from_navigator: #initial_language_from_navigator_quote, + initial_language_from_navigator_to_localstorage: #initial_language_from_navigator_to_localstorage_quote, + initial_language_from_navigator_to_cookie: #initial_language_from_navigator_to_cookie_quote, + initial_language_from_navigator_to_server_function: #initial_language_from_navigator_to_server_function_quote, + initial_language_from_accept_language_header: #initial_language_from_accept_language_header_quote, + cookie_name: #cookie_name_quote, + cookie_attrs: #cookie_attrs_quote, + initial_language_from_cookie: #initial_language_from_cookie_quote, + initial_language_from_cookie_to_localstorage: #initial_language_from_cookie_to_localstorage_quote, + initial_language_from_cookie_to_server_function: #initial_language_from_cookie_to_server_function_quote, + set_language_to_cookie: #set_language_to_cookie_quote, + initial_language_from_server_function: #initial_language_from_server_function_quote, + initial_language_from_server_function_to_cookie: #initial_language_from_server_function_to_cookie_quote, + initial_language_from_server_function_to_localstorage: #initial_language_from_server_function_to_localstorage_quote, + set_language_to_server_function: #set_language_to_server_function_quote, + provide_meta_context: true, + #system_quote + }; + ::leptos::provide_context::<::leptos_fluent::LeptosFluentMeta>(meta); }; - ::leptos::provide_context::<::leptos_fluent::LeptosFluentMeta>(meta); - }; - match provide_meta_context_exprpath { - Some(ref path) => quote! { #path{#quote}; }, - None => quote, + match provide_meta_context.exprpath { + Some(ref path) => quote! { #path{#quote}; }, + None => quote, + } } - } - false => quote! {}, - }; + false => quote! {}, + }; let quote = quote! { { diff --git a/leptos-fluent-macros/src/loader.rs b/leptos-fluent-macros/src/loader.rs index ba72d862..8031dc88 100644 --- a/leptos-fluent-macros/src/loader.rs +++ b/leptos-fluent-macros/src/loader.rs @@ -2,7 +2,7 @@ use crate::{ build_fluent_resources_and_file_paths, cookie::validate_cookie_attrs, languages::{read_languages_file, read_locales_folder}, - FluentFilePaths, + FluentFilePaths, ParsedLanguage, }; use quote::ToTokens; use std::path::PathBuf; @@ -198,6 +198,7 @@ macro_rules! exprpath_not_supported { }; } +#[derive(Default)] pub(crate) struct LitBoolExpr { pub lit: Option, pub expr: Option, @@ -206,14 +207,11 @@ pub(crate) struct LitBoolExpr { impl LitBoolExpr { pub fn new() -> Self { - Self { - lit: None, - expr: None, - exprpath: None, - } + Self::default() } } +#[derive(Default)] pub(crate) struct LitStrExpr { pub lit: Option, pub expr: Option, @@ -222,14 +220,11 @@ pub(crate) struct LitStrExpr { impl LitStrExpr { pub fn new() -> Self { - Self { - lit: None, - expr: None, - exprpath: None, - } + Self::default() } } +#[derive(Default)] pub(crate) struct Identifier { pub ident: Option, pub exprpath: Option, @@ -237,24 +232,32 @@ pub(crate) struct Identifier { impl Identifier { pub fn new() -> Self { - Self { - ident: None, - exprpath: None, - } + Self::default() + } +} + +#[derive(Default)] +pub(crate) struct LitBool { + pub lit: Option, + pub exprpath: Option, +} + +impl LitBool { + pub fn new() -> Self { + Self::default() } } pub(crate) struct I18nLoader { pub fluent_file_paths: FluentFilePaths, pub translations: Translations, - pub languages: Vec<(String, String, String, Option)>, + pub languages: Vec, pub languages_path: Option, pub raw_languages_path: Option, pub locales_path: String, pub core_locales_path: Option, pub check_translations: Option, - pub provide_meta_context: bool, - pub provide_meta_context_exprpath: Option, + pub provide_meta_context: LitBool, pub sync_html_tag_lang: LitBoolExpr, pub sync_html_tag_dir: LitBoolExpr, pub url_param: LitStrExpr, @@ -357,10 +360,7 @@ impl Parse for I18nLoader { #[cfg(feature = "system")] let mut initial_language_from_data_file = LitBoolExpr::new(); let mut data_file_key = LitStrExpr::new(); - let mut provide_meta_context: Option = None; - let mut provide_meta_context_exprpath: Option< - proc_macro2::TokenStream, - > = None; + let mut provide_meta_context = LitBool::new(); while !fields.is_empty() { let mut exprpath: Option = None; @@ -945,9 +945,9 @@ impl Parse for I18nLoader { _ = data_file_key.exprpath; } } else if k == "provide_meta_context" { - provide_meta_context = Some(fields.parse()?); + provide_meta_context.lit = Some(fields.parse()?); if exprpath.is_some() { - provide_meta_context_exprpath.clone_from(&exprpath); + provide_meta_context.exprpath.clone_from(&exprpath); } } else { return Err(syn::Error::new( @@ -1036,7 +1036,19 @@ impl Parse for I18nLoader { ), )); } else { - languages = read_locales_folder(&locales_folder_path); + let (langs, read_locales_folder_errors) = + read_locales_folder(&locales_folder_path); + if !read_locales_folder_errors.is_empty() { + return Err(syn::Error::new( + locales_path.as_ref().unwrap().span(), + format!( + "Errors while reading locales from {}:\n- {}", + locales_path.as_ref().unwrap().value(), + read_locales_folder_errors.join("\n- "), + ), + )); + } + languages = langs; } let locales_path_str = @@ -1146,11 +1158,7 @@ impl Parse for I18nLoader { locales_path: locales_path.unwrap().value(), core_locales_path: core_locales_path_str, check_translations: check_translations.map(|x| x.value()), - provide_meta_context: match provide_meta_context { - Some(x) => x.value, - None => false, - }, - provide_meta_context_exprpath, + provide_meta_context, sync_html_tag_lang, sync_html_tag_dir, url_param,