@@ -15,24 +15,51 @@ use std::io::prelude::*;
15
15
use std:: path:: Path ;
16
16
17
17
use fluent_bundle:: { FluentBundle , FluentResource , FluentValue } ;
18
+ use fluent_locale:: negotiate_languages;
18
19
19
20
lazy_static ! {
20
21
static ref CORE_RESOURCE : FluentResource =
21
22
read_from_file( "./locales/core.ftl" ) . expect( "cannot find core.ftl" ) ;
22
23
static ref RESOURCES : HashMap <String , Vec <FluentResource >> = build_resources( ) ;
23
24
static ref BUNDLES : HashMap <String , FluentBundle <' static >> = build_bundles( ) ;
25
+ static ref LOCALES : Vec <& ' static str > = RESOURCES . iter( ) . map( |( l, _) | & * * l) . collect( ) ;
26
+ static ref FALLBACKS : HashMap <String , Vec <String >> = build_fallbacks( ) ;
27
+ }
28
+
29
+ pub fn build_fallbacks ( ) -> HashMap < String , Vec < String > > {
30
+ LOCALES
31
+ . iter ( )
32
+ . map ( |locale| {
33
+ (
34
+ locale. to_string ( ) ,
35
+ negotiate_languages (
36
+ & [ locale] ,
37
+ & LOCALES ,
38
+ None ,
39
+ & fluent_locale:: NegotiationStrategy :: Filtering ,
40
+ )
41
+ . into_iter ( )
42
+ . map ( |x| x. to_string ( ) )
43
+ . collect ( ) ,
44
+ )
45
+ } )
46
+ . collect ( )
24
47
}
25
48
26
49
pub struct I18NHelper {
27
50
bundles : & ' static HashMap < String , FluentBundle < ' static > > ,
51
+ fallbacks : & ' static HashMap < String , Vec < String > > ,
28
52
}
29
53
30
54
impl I18NHelper {
31
55
pub fn new ( ) -> Self {
32
- Self { bundles : & * BUNDLES }
56
+ Self {
57
+ bundles : & * BUNDLES ,
58
+ fallbacks : & * FALLBACKS ,
59
+ }
33
60
}
34
61
35
- pub fn lookup (
62
+ pub fn lookup_single_language (
36
63
& self ,
37
64
lang : & str ,
38
65
text_id : & str ,
@@ -54,23 +81,41 @@ impl I18NHelper {
54
81
panic ! ( "Unknown language {}" , lang)
55
82
}
56
83
}
57
- pub fn lookup_with_fallback (
84
+
85
+ // Traverse the fallback chain,
86
+ pub fn lookup (
58
87
& self ,
59
88
lang : & str ,
60
89
text_id : & str ,
61
90
args : Option < & HashMap < & str , FluentValue > > ,
62
91
) -> String {
63
- if let Some ( val) = self . lookup ( lang, text_id, args) {
64
- val
65
- } else if lang != "en-US" {
66
- if let Some ( val) = self . lookup ( "en-US" , text_id, args) {
67
- val
68
- } else {
69
- format ! ( "Unknown localization {}" , text_id)
92
+ for l in self . fallbacks . get ( lang) . expect ( "language not found" ) {
93
+ if let Some ( val) = self . lookup_single_language ( l, text_id, args) {
94
+ return val;
95
+ }
96
+ }
97
+ if lang != "en-US" {
98
+ if let Some ( val) = self . lookup_single_language ( "en-US" , text_id, args) {
99
+ return val;
70
100
}
71
- } else {
72
- format ! ( "Unknown localization {}" , text_id)
73
101
}
102
+ format ! ( "Unknown localization {}" , text_id)
103
+ }
104
+
105
+ // Don't fall back to English
106
+ pub fn lookup_no_english (
107
+ & self ,
108
+ lang : & str ,
109
+ text_id : & str ,
110
+ args : Option < & HashMap < & str , FluentValue > > ,
111
+ ) -> Option < String > {
112
+ for l in self . fallbacks . get ( lang) . expect ( "language not found" ) {
113
+ if let Some ( val) = self . lookup_single_language ( l, text_id, args) {
114
+ return Some ( val) ;
115
+ }
116
+ }
117
+
118
+ None
74
119
}
75
120
}
76
121
@@ -173,7 +218,7 @@ impl HelperDef for I18NHelper {
173
218
. as_bool ( )
174
219
. expect ( "Pontoon must be boolean" ) ;
175
220
176
- let response = self . lookup_with_fallback ( lang, & id, args. as_ref ( ) ) ;
221
+ let response = self . lookup ( lang, & id, args. as_ref ( ) ) ;
177
222
if pontoon {
178
223
out. write ( & format ! ( "<span data-l10n-id='{}'>" , id) )
179
224
. map_err ( RenderError :: with) ?;
@@ -264,7 +309,7 @@ impl HelperDef for TeamHelper {
264
309
if lang == "en-US" {
265
310
let english = team[ "website_data" ] [ id] . as_str ( ) . unwrap ( ) ;
266
311
out. write ( & english) . map_err ( RenderError :: with) ?;
267
- } else if let Some ( value) = self . i18n . lookup ( lang, & fluent_id, None ) {
312
+ } else if let Some ( value) = self . i18n . lookup_no_english ( lang, & fluent_id, None ) {
268
313
out. write ( & value) . map_err ( RenderError :: with) ?;
269
314
} else {
270
315
let english = team[ "website_data" ] [ id] . as_str ( ) . unwrap ( ) ;
0 commit comments