1
1
use handlebars:: {
2
- Context , Handlebars , Helper , HelperDef , HelperResult , Output , RenderContext , RenderError ,
2
+ Context , Handlebars , Helper , HelperDef , HelperResult , Output , RenderContext , RenderError , Renderable ,
3
3
} ;
4
4
5
+ use handlebars:: template:: { TemplateElement , Parameter } ;
5
6
use rocket:: http:: RawStr ;
6
7
use rocket:: request:: FromParam ;
7
8
use serde_json:: Value as Json ;
@@ -43,13 +44,25 @@ impl I18NHelper {
43
44
}
44
45
}
45
46
47
+ #[ derive( Default ) ]
48
+ struct StringOutput {
49
+ pub s : String
50
+ }
51
+
52
+ impl Output for StringOutput {
53
+ fn write ( & mut self , seg : & str ) -> Result < ( ) , io:: Error > {
54
+ self . s . push_str ( seg) ;
55
+ Ok ( ( ) )
56
+ }
57
+ }
58
+
46
59
impl HelperDef for I18NHelper {
47
60
fn call < ' reg : ' rc , ' rc > (
48
61
& self ,
49
62
h : & Helper < ' reg , ' rc > ,
50
- _r : & ' reg Handlebars ,
63
+ reg : & ' reg Handlebars ,
51
64
context : & ' rc Context ,
52
- _rc : & mut RenderContext < ' reg > ,
65
+ rcx : & mut RenderContext < ' reg > ,
53
66
out : & mut dyn Output ,
54
67
) -> HelperResult {
55
68
let id = if let Some ( id) = h. param ( 0 ) {
@@ -66,11 +79,10 @@ impl HelperDef for I18NHelper {
66
79
return Err ( RenderError :: new ( "{{text}} takes an identifier parameter" ) ) ;
67
80
} ;
68
81
69
- let map;
70
- let args = if h. hash ( ) . is_empty ( ) {
82
+ let mut args = if h. hash ( ) . is_empty ( ) {
71
83
None
72
84
} else {
73
- map = h
85
+ let map = h
74
86
. hash ( )
75
87
. iter ( )
76
88
. filter_map ( |( k, v) | {
@@ -83,15 +95,43 @@ impl HelperDef for I18NHelper {
83
95
Some ( ( & * * k, val) )
84
96
} )
85
97
. collect ( ) ;
86
- Some ( & map)
98
+ Some ( map)
87
99
} ;
100
+
101
+ if let Some ( tpl) = h. template ( ) {
102
+ if args. is_none ( ) {
103
+ args = Some ( HashMap :: new ( ) ) ;
104
+ }
105
+ let args = args. as_mut ( ) . unwrap ( ) ;
106
+ for element in & tpl. elements {
107
+ if let TemplateElement :: HelperBlock ( ref block) = element {
108
+ if block. name != "textparam" {
109
+ return Err ( RenderError :: new ( format ! ( "{{{{text}}}} can only contain {{{{textparam}}}} elements, not {}" , block. name) ) ) ;
110
+ }
111
+ let id = if let Some ( el) = block. params . get ( 0 ) {
112
+ if let Parameter :: Name ( ref s) = * el {
113
+ s
114
+ } else {
115
+ return Err ( RenderError :: new ( "{{textparam}} takes an identifier parameter" ) ) ;
116
+ }
117
+ } else {
118
+ return Err ( RenderError :: new ( "{{textparam}} must have one parameter" ) ) ;
119
+ } ;
120
+ if let Some ( ref tpl) = block. template {
121
+ let mut s = StringOutput :: default ( ) ;
122
+ tpl. render ( reg, context, rcx, & mut s) ?;
123
+ args. insert ( & * id, FluentValue :: String ( s. s ) ) ;
124
+ }
125
+ }
126
+ }
127
+ }
88
128
let lang = context
89
129
. data ( )
90
130
. get ( "lang" )
91
131
. expect ( "Language not set in context" )
92
132
. as_str ( )
93
133
. expect ( "Language must be string" ) ;
94
- let response = self . i18n_token ( lang, & id, args) ;
134
+ let response = self . i18n_token ( lang, & id, args. as_ref ( ) ) ;
95
135
out. write ( & response) . map_err ( RenderError :: with)
96
136
}
97
137
}
0 commit comments