Skip to content

Commit 9041cbb

Browse files
authoredMar 6, 2025··
Add new parameter fill_translations to leptos_fluent! (#293)
1 parent 1135f42 commit 9041cbb

File tree

13 files changed

+288
-47
lines changed

13 files changed

+288
-47
lines changed
 

‎CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# CHANGELOG
22

3+
## Unreleased - [0.2.6]
4+
5+
### New features
6+
7+
- Add a new parameter `fill_translations` to `leptos_fluent!` macro to add
8+
messages found in `tr!` and `move_tr!` macros to Fluent translations files.
9+
310
## 2025-03-06 - [0.2.5]
411

512
### Bug fixes
@@ -654,6 +661,7 @@ version to `0.1` during installation.
654661

655662
- Added all ISO-639-1 and ISO-639-2 languages.
656663

664+
[0.2.6]: https://github.com/mondeja/leptos-fluent/compare/v0.2.5...master
657665
[0.2.5]: https://github.com/mondeja/leptos-fluent/compare/v0.2.4...v0.2.5
658666
[0.2.4]: https://github.com/mondeja/leptos-fluent/compare/v0.2.3...v0.2.4
659667
[0.2.3]: https://github.com/mondeja/leptos-fluent/compare/v0.2.2...v0.2.3

‎Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎book/src/leptos_fluent.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,32 @@ Must be a [glob] relative to the _Cargo.toml_ file.
247247
}
248248
```
249249

250+
### `fill_translations`
251+
252+
Add new messages found in `tr!` and `move_tr!` macros to translations files.
253+
254+
- For single crate projects:
255+
256+
```rust
257+
leptos_fluent! {
258+
locales: "./locales",
259+
translations: [TRANSLATIONS],
260+
fill_translations: "./src/**/*.rs",
261+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
262+
}
263+
```
264+
265+
- For workspace projects:
266+
267+
```rust
268+
leptos_fluent! {
269+
locales: "./locales",
270+
translations: [TRANSLATIONS],
271+
fill_translations: "../{app,components}/src/**/*.rs",
272+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
273+
}
274+
```
275+
250276
### <span style="opacity:.5">CSR </span> | `sync_html_tag_lang`
251277

252278
Synchronize the global [`<html lang="...">` attribute] with current language

‎examples/csr-minimal/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ pub fn I18n(children: Children) -> impl IntoView {
1515
children: children(),
1616
translations: [TRANSLATIONS],
1717
locales: "./locales",
18+
check_translations: "./src/**/*.rs",
19+
fill_translations: "./src/**/*.rs",
1820
}
1921
}
2022

‎leptos-fluent-macros/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "leptos-fluent-macros"
33
description = "Macros for leptos-fluent"
44
edition.workspace = true
5-
version = "0.2.5"
5+
version = "0.2.6"
66
rust-version = "1.79.0"
77
license = "MIT"
88
documentation.workspace = true

‎leptos-fluent-macros/src/translations_checker/fluent_entries.rs renamed to ‎leptos-fluent-macros/src/fluent_entries.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use fluent_syntax::ast::{
55
use std::collections::HashMap;
66
use std::rc::Rc;
77

8-
pub(in crate::translations_checker) type FluentEntries =
9-
HashMap<Rc<String>, Vec<FluentEntry>>;
8+
pub(crate) type FluentEntries = HashMap<Rc<String>, Vec<FluentEntry>>;
109

1110
#[cfg_attr(any(debug_assertions, feature = "tracing"), derive(Debug))]
1211
#[derive(Clone, PartialEq)]
@@ -39,7 +38,7 @@ struct MaybeReferencedFluentEntry {
3938

4039
#[cfg_attr(any(debug_assertions, feature = "tracing"), derive(Debug))]
4140
#[derive(Clone, PartialEq)]
42-
pub(in crate::translations_checker) struct FluentEntry {
41+
pub(crate) struct FluentEntry {
4342
pub(crate) message_name: String,
4443
pub(crate) placeables: Vec<String>,
4544
}

‎leptos-fluent-macros/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@ extern crate proc_macro;
1111
pub(crate) mod cookie;
1212
mod exprpath;
1313
mod files_tracker;
14+
#[cfg(not(feature = "ssr"))]
15+
pub(crate) mod fluent_entries;
1416
mod fluent_resources;
1517
mod languages;
1618
mod loader;
1719
#[cfg(not(feature = "ssr"))]
20+
pub(crate) mod tr_macros;
21+
#[cfg(not(feature = "ssr"))]
1822
mod translations_checker;
23+
#[cfg(not(feature = "ssr"))]
24+
mod translations_filler;
1925

2026
pub(crate) use exprpath::evaluate_exprpath;
2127
use files_tracker::build_files_tracker_quote;
@@ -109,6 +115,7 @@ pub fn leptos_fluent(
109115
locales_path,
110116
core_locales_path,
111117
check_translations,
118+
fill_translations,
112119
provide_meta_context,
113120
sync_html_tag_lang,
114121
sync_html_tag_dir,
@@ -1671,6 +1678,8 @@ pub fn leptos_fluent(
16711678
maybe_some_litstr_param(&raw_languages_path);
16721679
let check_translations_quote =
16731680
maybe_some_litstr_param(&check_translations);
1681+
let fill_translations_quote =
1682+
maybe_some_litstr_param(&fill_translations);
16741683
let sync_html_tag_lang_quote =
16751684
lit_bool_exprs(&sync_html_tag_lang);
16761685
let sync_html_tag_dir_quote =
@@ -1811,6 +1820,7 @@ pub fn leptos_fluent(
18111820
core_locales: #core_locales_quote,
18121821
languages: #languages_quote,
18131822
check_translations: #check_translations_quote,
1823+
fill_translations: #fill_translations_quote,
18141824
sync_html_tag_lang: #sync_html_tag_lang_quote,
18151825
sync_html_tag_dir: #sync_html_tag_dir_quote,
18161826
url_param: #url_param_quote,

‎leptos-fluent-macros/src/loader.rs

Lines changed: 117 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ pub(crate) struct I18nLoader {
400400
pub locales_path: String,
401401
pub core_locales_path: Option<String>,
402402
pub check_translations: Option<String>,
403+
pub fill_translations: Option<String>,
403404
pub provide_meta_context: Vec<LitBool>,
404405
pub sync_html_tag_lang: Vec<LitBoolExpr>,
405406
pub sync_html_tag_dir: Vec<LitBoolExpr>,
@@ -459,6 +460,7 @@ impl Parse for I18nLoader {
459460
let mut core_locales_path: Option<syn::LitStr> = None;
460461
let mut translations: Option<Translations> = None;
461462
let mut check_translations: Option<syn::LitStr> = None;
463+
let mut fill_translations: Option<syn::LitStr> = None;
462464
let mut provide_meta_context: Vec<LitBool> = Vec::new();
463465
let mut sync_html_tag_lang: Vec<LitBoolExpr> = Vec::new();
464466
let mut sync_html_tag_dir: Vec<LitBoolExpr> = Vec::new();
@@ -681,6 +683,17 @@ impl Parse for I18nLoader {
681683
k,
682684
check_translations
683685
);
686+
} else if k == "fill_translations" {
687+
struct_field_init_shorthand_not_supported!(
688+
struct_field_init_shorthand,
689+
k
690+
);
691+
fill_translations = Some(input.parse()?);
692+
evaluate_compile_time_exprpath_set_none!(
693+
exprpath,
694+
k,
695+
fill_translations
696+
);
684697
} else if k == "sync_html_tag_lang" {
685698
let mut param = LitBoolExpr::new();
686699
clone_runtime_exprpath!(exprpath, param);
@@ -1455,40 +1468,113 @@ impl Parse for I18nLoader {
14551468
}
14561469

14571470
#[cfg(not(feature = "ssr"))]
1458-
if let Some(ref check_translations_globstr) = check_translations {
1459-
{
1460-
let (fluent_resources, ref fluent_file_paths) =
1461-
fluent_resources_and_file_paths;
1462-
let (check_messages, errors) = crate::translations_checker::run(
1463-
&check_translations_globstr.value(),
1464-
&workspace_path,
1465-
&fluent_resources,
1466-
fluent_file_paths,
1467-
&core_locales_path_str,
1468-
&core_locales_content,
1469-
);
1471+
if check_translations.is_some() || fill_translations.is_some() {
1472+
let mut f_resources_and_file_paths =
1473+
fluent_resources_and_file_paths.clone();
1474+
1475+
if let Some(ref fill_translations_globstr) = fill_translations {
1476+
{
1477+
let (ref fluent_resources, ref fluent_file_paths) =
1478+
f_resources_and_file_paths;
1479+
let (fill_messages, errors) =
1480+
crate::translations_filler::run(
1481+
&fill_translations_globstr.value(),
1482+
&workspace_path,
1483+
fluent_resources,
1484+
fluent_file_paths,
1485+
&core_locales_path_str,
1486+
&core_locales_content,
1487+
);
1488+
1489+
let mut report = String::new();
1490+
if !fill_messages.is_empty() {
1491+
report.push_str(
1492+
"Translations filled by leptos-fluent:\n",
1493+
);
1494+
for (file_path, message_names) in fill_messages {
1495+
report.push_str(&format!(" {file_path}\n",));
1496+
for message_name in message_names {
1497+
report.push_str(&format!(
1498+
" - {message_name}\n",
1499+
));
1500+
}
1501+
}
1502+
}
1503+
if !report.is_empty() {
1504+
report.push('\n');
1505+
eprintln!("{report}");
1506+
1507+
// resources must be recreated because new fluent entries
1508+
// have been added to them
1509+
let (
1510+
f_resources_and_file_paths_,
1511+
resources_file_paths_errors,
1512+
) = build_fluent_resources_and_file_paths(
1513+
&locales_path_str,
1514+
);
1515+
if !resources_file_paths_errors.is_empty() {
1516+
return Err(syn::Error::new(
1517+
locales_path.unwrap().span(),
1518+
format!(
1519+
"Errors while reading fluent resources from {}:\n- {}",
1520+
locales_path_str,
1521+
resources_file_paths_errors.join("\n- "),
1522+
),
1523+
));
1524+
}
1525+
f_resources_and_file_paths =
1526+
f_resources_and_file_paths_;
1527+
}
14701528

1471-
let mut report = String::new();
1472-
if !check_messages.is_empty() {
1473-
report.push_str(&format!(
1474-
"Translations check failed:\n- {}",
1475-
check_messages.join("\n- "),
1476-
));
14771529
if !errors.is_empty() {
1478-
report.push_str("\n\n");
1530+
let message = &format!(
1531+
"Unrecoverable errors:\n- {}",
1532+
errors.join("\n- "),
1533+
);
1534+
return Err(syn::Error::new(
1535+
fill_translations_globstr.span(),
1536+
message,
1537+
));
14791538
}
14801539
}
1481-
if !errors.is_empty() {
1482-
report.push_str(&format!(
1483-
"Unrecoverable errors:\n- {}",
1484-
errors.join("\n- "),
1485-
));
1486-
}
1487-
if !report.is_empty() {
1488-
return Err(syn::Error::new(
1489-
check_translations_globstr.span(),
1490-
report,
1491-
));
1540+
}
1541+
1542+
if let Some(ref check_translations_globstr) = check_translations {
1543+
{
1544+
let (ref fluent_resources, ref fluent_file_paths) =
1545+
f_resources_and_file_paths;
1546+
let (check_messages, errors) =
1547+
crate::translations_checker::run(
1548+
&check_translations_globstr.value(),
1549+
&workspace_path,
1550+
fluent_resources,
1551+
fluent_file_paths,
1552+
&core_locales_path_str,
1553+
&core_locales_content,
1554+
);
1555+
1556+
let mut report = String::new();
1557+
if !check_messages.is_empty() {
1558+
report.push_str(&format!(
1559+
"Translations check failed:\n- {}",
1560+
check_messages.join("\n- "),
1561+
));
1562+
if !errors.is_empty() {
1563+
report.push_str("\n\n");
1564+
}
1565+
}
1566+
if !errors.is_empty() {
1567+
report.push_str(&format!(
1568+
"Unrecoverable errors:\n- {}",
1569+
errors.join("\n- "),
1570+
));
1571+
}
1572+
if !report.is_empty() {
1573+
return Err(syn::Error::new(
1574+
check_translations_globstr.span(),
1575+
report,
1576+
));
1577+
}
14921578
}
14931579
}
14941580
}
@@ -1516,6 +1602,7 @@ impl Parse for I18nLoader {
15161602
locales_path: locales_path.unwrap().value(),
15171603
core_locales_path: core_locales_path_str,
15181604
check_translations: check_translations.map(|x| x.value()),
1605+
fill_translations: fill_translations.map(|x| x.value()),
15191606
provide_meta_context,
15201607
sync_html_tag_lang,
15211608
sync_html_tag_dir,

‎leptos-fluent-macros/src/translations_checker/tr_macros.rs renamed to ‎leptos-fluent-macros/src/tr_macros.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ use std::path::Path;
33
use syn::visit::Visit;
44

55
pub(crate) fn gather_tr_macro_defs_from_rs_files(
6-
check_translations_globstr: &Path,
6+
globstr: &Path,
77
#[cfg(not(test))] workspace_path: &Path,
88
) -> (Vec<TranslationMacro>, Vec<String>) {
99
let mut errors = Vec::new();
10-
let glob_pattern = check_translations_globstr.to_string_lossy();
10+
let glob_pattern = globstr.to_string_lossy();
1111

1212
match globwalk::glob(&glob_pattern) {
1313
Ok(paths) => {

‎leptos-fluent-macros/src/translations_checker/mod.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1-
mod fluent_entries;
2-
mod tr_macros;
3-
1+
use crate::fluent_entries::{build_fluent_entries, FluentEntries};
2+
use crate::tr_macros::{gather_tr_macro_defs_from_rs_files, TranslationMacro};
43
use crate::{FluentFilePaths, FluentResources};
5-
use fluent_entries::build_fluent_entries;
6-
use fluent_entries::FluentEntries;
74
use std::path::Path;
8-
use tr_macros::{gather_tr_macro_defs_from_rs_files, TranslationMacro};
95

106
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
117
pub(crate) fn run(
12-
check_translations_globstr: &str,
8+
globstr: &str,
139
workspace_path: &Path,
1410
fluent_resources: &FluentResources,
1511
fluent_file_paths: &FluentFilePaths,
@@ -19,7 +15,7 @@ pub(crate) fn run(
1915
let mut errors = Vec::new();
2016

2117
let (tr_macros, tr_macros_errors) = gather_tr_macro_defs_from_rs_files(
22-
&workspace_path.join(check_translations_globstr),
18+
&workspace_path.join(globstr),
2319
#[cfg(not(test))]
2420
workspace_path,
2521
);

0 commit comments

Comments
 (0)
Please sign in to comment.