1
1
use std:: borrow:: Cow ;
2
- use std:: sync:: { Arc , RwLock } ;
3
-
4
2
use fluent:: types:: { FluentNumber , FluentNumberOptions } ;
5
3
use fluent:: { FluentArgs , FluentBundle , FluentError , FluentResource , FluentValue } ;
6
4
use godot:: prelude:: * ;
@@ -19,7 +17,7 @@ pub struct TranslationFluent {
19
17
#[ var( get = get_message_pattern, set = set_message_pattern) ]
20
18
message_pattern : GString ,
21
19
message_pattern_regex : Option < Gd < RegEx > > ,
22
- bundles : Arc < RwLock < Vec < FluentBundle < FluentResource > > > > ,
20
+ bundle : Option < FluentBundle < FluentResource > > ,
23
21
base : Base < Translation > ,
24
22
}
25
23
@@ -35,7 +33,7 @@ impl ITranslation for TranslationFluent {
35
33
Self {
36
34
message_pattern : GString :: new ( ) ,
37
35
message_pattern_regex : None ,
38
- bundles : Arc :: new ( RwLock :: new ( Vec :: new ( ) ) ) ,
36
+ bundle : None ,
39
37
base,
40
38
}
41
39
}
@@ -89,15 +87,7 @@ impl TranslationFluent {
89
87
}
90
88
}
91
89
92
- let bundles = self . bundles . read ( ) . unwrap ( ) ;
93
-
94
- let result = bundles
95
- . iter ( )
96
- . filter_map ( |bundle| {
97
- Self :: translate ( bundle, & msg, & args. clone ( ) , if context. is_empty ( ) { None } else { Some ( & context) } )
98
- } )
99
- . next ( ) ;
100
-
90
+ let result = self . translate ( & msg, & args. clone ( ) , if context. is_empty ( ) { None } else { Some ( & context) } ) ;
101
91
match result {
102
92
Some ( text) => StringName :: from ( text) ,
103
93
None => StringName :: default ( ) ,
@@ -180,7 +170,13 @@ impl TranslationFluent {
180
170
output
181
171
}
182
172
183
- pub fn translate ( bundle : & FluentBundle < FluentResource > , message_id : & StringName , args : & Dictionary , attribute : Option < & StringName > ) -> Option < String > {
173
+ pub fn translate ( & self , message_id : & StringName , args : & Dictionary , attribute : Option < & StringName > ) -> Option < String > {
174
+ if self . bundle . is_none ( ) {
175
+ godot_error ! ( "Unable to translate before adding at least one FTL file to translation." ) ;
176
+ return None ;
177
+ }
178
+
179
+ let bundle = self . bundle . as_ref ( ) . unwrap ( ) ;
184
180
let message = bundle. get_message ( & String :: from ( message_id) ) ;
185
181
message. as_ref ( ) ?;
186
182
let message = message. unwrap ( ) ;
@@ -238,22 +234,49 @@ impl TranslationFluent {
238
234
239
235
#[ func]
240
236
pub fn add_bundle_from_text ( & mut self , text : String ) -> GdErr {
237
+ let bundle = match & mut self . bundle {
238
+ Some ( bundle) => bundle,
239
+ None => & mut {
240
+ let bundle = self . create_bundle ( ) ;
241
+ match bundle {
242
+ Ok ( bundle) => {
243
+ self . bundle = Some ( bundle) ;
244
+ self . bundle . as_mut ( ) . unwrap ( )
245
+ } ,
246
+ Err ( err) => return err
247
+ }
248
+ } ,
249
+ } ;
250
+
241
251
let res = FluentResource :: try_new ( text) ;
242
252
if res. is_err ( ) {
243
253
// TODO: I could give more parser error details here, and probably should? :)
244
254
return GdErr :: ERR_PARSE_ERROR ;
245
255
}
256
+ let res = res. unwrap ( ) ;
257
+
258
+ Self :: map_fluent_error ( & bundle. add_resource ( res) )
259
+ }
260
+
261
+ fn create_bundle ( & self ) -> Result < FluentBundle < FluentResource > , GdErr > {
262
+ let mut bundle = FluentBundle :: new ( self . get_fluent_locales ( ) ?) ;
263
+ let project_settings = ProjectSettings :: singleton ( ) ;
264
+ bundle. set_use_isolating ( bool:: from_variant ( & project_settings. get_setting ( PROJECT_SETTING_UNICODE_ISOLATION . into ( ) ) ) ) ;
265
+ Ok ( bundle)
266
+ }
267
+
268
+ // TODO: Listen to NOTIFICATION_TRANSLATION_CHANGED on MainLoop. On notification, update the existing bundle's "locales" field.
269
+ fn get_fluent_locales ( & self ) -> Result < Vec < LanguageIdentifier > , GdErr > {
246
270
let lang = self . base ( ) . get_locale ( ) ;
247
271
if lang. is_empty ( ) {
248
272
// Give a user-friendly message.
249
- godot_error ! ( "Failed to add bundle to TranslationFluent: locale has not been set." ) ;
250
- return GdErr :: ERR_DOES_NOT_EXIST ;
273
+ godot_error ! ( "Failed to create bundle for TranslationFluent: locale has not been set." ) ;
274
+ return Err ( GdErr :: ERR_DOES_NOT_EXIST ) ;
251
275
}
252
- let res = res. unwrap ( ) ;
253
- let mut bundles = self . bundles . write ( ) . unwrap ( ) ;
276
+
254
277
let lang_id = String :: from ( lang) . parse :: < LanguageIdentifier > ( ) ;
255
278
match lang_id {
256
- Err ( err) => Self :: map_langid_error ( err) ,
279
+ Err ( err) => Err ( Self :: map_langid_error ( err) ) ,
257
280
Ok ( lang_id) => {
258
281
let project_settings = ProjectSettings :: singleton ( ) ;
259
282
let mut locales = vec ! [ lang_id] ;
@@ -262,17 +285,13 @@ impl TranslationFluent {
262
285
if fallback_locale. len ( ) >= 2 {
263
286
let fallback_locale_id = fallback_locale. to_string ( ) . parse :: < LanguageIdentifier > ( ) ;
264
287
match fallback_locale_id {
265
- Err ( err) => return Self :: map_langid_error ( err) ,
288
+ Err ( err) => return Err ( Self :: map_langid_error ( err) ) ,
266
289
Ok ( fallback_locale_id) => {
267
290
locales. push ( fallback_locale_id) ;
268
291
}
269
292
}
270
293
}
271
- let mut bundle = FluentBundle :: new ( locales) ;
272
- bundle. set_use_isolating ( bool:: from_variant ( & project_settings. get_setting ( PROJECT_SETTING_UNICODE_ISOLATION . into ( ) ) ) ) ;
273
- let err = Self :: map_fluent_error ( & bundle. add_resource ( res) ) ;
274
- bundles. push ( bundle) ;
275
- err
294
+ Ok ( locales)
276
295
}
277
296
}
278
297
}
0 commit comments