@@ -17,6 +17,7 @@ mod errors;
17
17
mod models;
18
18
mod timer;
19
19
mod value;
20
+ use i_slint_core:: translations:: Translator ;
20
21
21
22
fn handle_unraisable ( py : Python < ' _ > , context : String , err : PyErr ) {
22
23
let exception = err. value ( py) ;
@@ -78,6 +79,83 @@ fn invoke_from_event_loop(callable: Py<PyAny>) -> Result<(), errors::PyEventLoop
78
79
. map_err ( |e| e. into ( ) )
79
80
}
80
81
82
+ #[ gen_stub_pyfunction]
83
+ #[ pyfunction]
84
+ fn init_translations ( _py : Python < ' _ > , translations : Bound < PyAny > ) -> PyResult < ( ) > {
85
+ i_slint_backend_selector:: with_global_context ( |ctx| {
86
+ ctx. set_external_translator ( if translations. is_none ( ) {
87
+ None
88
+ } else {
89
+ Some ( Box :: new ( PyGettextTranslator ( translations. unbind ( ) ) ) )
90
+ } ) ;
91
+ i_slint_core:: translations:: mark_all_translations_dirty ( ) ;
92
+ } )
93
+ . map_err ( |e| errors:: PyPlatformError ( e) ) ?;
94
+ Ok ( ( ) )
95
+ }
96
+
97
+ struct PyGettextTranslator (
98
+ /// A reference to a `gettext.GNUTranslations` object.
99
+ Py < PyAny > ,
100
+ ) ;
101
+
102
+ impl Translator for PyGettextTranslator {
103
+ fn translate < ' a > (
104
+ & ' a self ,
105
+ string : & ' a str ,
106
+ context : Option < & ' a str > ,
107
+ ) -> std:: borrow:: Cow < ' a , str > {
108
+ Python :: attach ( |py| {
109
+ match if let Some ( context) = context {
110
+ self . 0 . call_method ( py, pyo3:: intern!( py, "pgettext" ) , ( context, string) , None )
111
+ } else {
112
+ self . 0 . call_method ( py, pyo3:: intern!( py, "gettext" ) , ( string, ) , None )
113
+ } {
114
+ Ok ( translation) => Some ( translation) ,
115
+ Err ( err) => {
116
+ handle_unraisable ( py, "calling pgettext/gettext" . into ( ) , err) ;
117
+ None
118
+ }
119
+ }
120
+ . and_then ( |maybe_str| maybe_str. extract :: < String > ( py) . ok ( ) )
121
+ . map ( std:: borrow:: Cow :: Owned )
122
+ } )
123
+ . unwrap_or ( std:: borrow:: Cow :: Borrowed ( string) )
124
+ . into ( )
125
+ }
126
+
127
+ fn ntranslate < ' a > (
128
+ & ' a self ,
129
+ n : u64 ,
130
+ singular : & ' a str ,
131
+ plural : & ' a str ,
132
+ context : Option < & ' a str > ,
133
+ ) -> std:: borrow:: Cow < ' a , str > {
134
+ Python :: attach ( |py| {
135
+ match if let Some ( context) = context {
136
+ self . 0 . call_method (
137
+ py,
138
+ pyo3:: intern!( py, "npgettext" ) ,
139
+ ( context, singular, plural, n) ,
140
+ None ,
141
+ )
142
+ } else {
143
+ self . 0 . call_method ( py, pyo3:: intern!( py, "ngettext" ) , ( singular, plural, n) , None )
144
+ } {
145
+ Ok ( translation) => Some ( translation) ,
146
+ Err ( err) => {
147
+ handle_unraisable ( py, "calling npgettext/ngettext" . into ( ) , err) ;
148
+ None
149
+ }
150
+ }
151
+ . and_then ( |maybe_str| maybe_str. extract :: < String > ( py) . ok ( ) )
152
+ . map ( std:: borrow:: Cow :: Owned )
153
+ } )
154
+ . unwrap_or ( std:: borrow:: Cow :: Borrowed ( singular) )
155
+ . into ( )
156
+ }
157
+ }
158
+
81
159
use pyo3:: prelude:: * ;
82
160
83
161
#[ pymodule]
@@ -107,6 +185,7 @@ fn slint(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
107
185
m. add_function ( wrap_pyfunction ! ( quit_event_loop, m) ?) ?;
108
186
m. add_function ( wrap_pyfunction ! ( set_xdg_app_id, m) ?) ?;
109
187
m. add_function ( wrap_pyfunction ! ( invoke_from_event_loop, m) ?) ?;
188
+ m. add_function ( wrap_pyfunction ! ( init_translations, m) ?) ?;
110
189
111
190
Ok ( ( ) )
112
191
}
0 commit comments