@@ -710,6 +710,11 @@ pub fn generate(
710
710
711
711
let llr = llr:: lower_to_item_tree:: lower_to_item_tree ( & doc, compiler_config) ;
712
712
713
+ #[ cfg( feature = "bundle-translations" ) ]
714
+ if let Some ( translations) = & llr. translations {
715
+ generate_translation ( translations, & llr, & mut file. resources ) ;
716
+ }
717
+
713
718
// Forward-declare the root so that sub-components can access singletons, the window, etc.
714
719
file. declarations . extend (
715
720
llr. public_components
@@ -3369,6 +3374,16 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
3369
3374
)
3370
3375
}
3371
3376
Expression :: EmptyComponentFactory => panic ! ( "component-factory not yet supported in C++" ) ,
3377
+ Expression :: TranslationReference { format_args, string_index, plural } => {
3378
+ let args = compile_expression ( format_args, ctx) ;
3379
+ match plural {
3380
+ Some ( plural) => {
3381
+ let plural = compile_expression ( plural, ctx) ;
3382
+ format ! ( "slint::private_api::translate_from_bundle_with_plural(slint_translation_bundle_plural_{string_index}_str, slint_translation_bundle_plural_{string_index}_idx, slint_translated_plural_rules, {args}, {plural})" )
3383
+ }
3384
+ None => format ! ( "slint::private_api::translate_from_bundle(slint_translation_bundle_{string_index}, {args})" ) ,
3385
+ }
3386
+ } ,
3372
3387
}
3373
3388
}
3374
3389
@@ -3828,3 +3843,106 @@ fn generate_type_aliases(file: &mut File, doc: &Document) {
3828
3843
3829
3844
file. declarations . extend ( type_aliases) ;
3830
3845
}
3846
+
3847
+ #[ cfg( feature = "bundle-translations" ) ]
3848
+ fn generate_translation (
3849
+ translations : & llr:: translations:: Translations ,
3850
+ compilation_unit : & llr:: CompilationUnit ,
3851
+ declarations : & mut Vec < Declaration > ,
3852
+ ) {
3853
+ for ( idx, m) in translations. strings . iter ( ) . enumerate ( ) {
3854
+ declarations. push ( Declaration :: Var ( Var {
3855
+ ty : "const char8_t* const" . into ( ) ,
3856
+ name : format_smolstr ! ( "slint_translation_bundle_{idx}" ) ,
3857
+ array_size : Some ( m. len ( ) ) ,
3858
+ init : Some ( format ! (
3859
+ "{{ {} }}" ,
3860
+ m. iter( )
3861
+ . map( |s| match s {
3862
+ Some ( s) => format_smolstr!( "u8\" {}\" " , escape_string( s. as_str( ) ) ) ,
3863
+ None => "nullptr" . into( ) ,
3864
+ } )
3865
+ . join( ", " )
3866
+ ) ) ,
3867
+ ..Default :: default ( )
3868
+ } ) ) ;
3869
+ }
3870
+ for ( idx, ms) in translations. plurals . iter ( ) . enumerate ( ) {
3871
+ let all_strs = ms. iter ( ) . flatten ( ) . flatten ( ) ;
3872
+ let all_strs_len = all_strs. clone ( ) . count ( ) ;
3873
+ declarations. push ( Declaration :: Var ( Var {
3874
+ ty : "const char8_t* const" . into ( ) ,
3875
+ name : format_smolstr ! ( "slint_translation_bundle_plural_{}_str" , idx) ,
3876
+ array_size : Some ( all_strs_len) ,
3877
+ init : Some ( format ! (
3878
+ "{{ {} }}" ,
3879
+ all_strs. map( |s| format_smolstr!( "u8\" {}\" " , escape_string( s. as_str( ) ) ) ) . join( ", " )
3880
+ ) ) ,
3881
+ ..Default :: default ( )
3882
+ } ) ) ;
3883
+
3884
+ let mut count = 0 ;
3885
+ declarations. push ( Declaration :: Var ( Var {
3886
+ ty : "const uint32_t" . into ( ) ,
3887
+ name : format_smolstr ! ( "slint_translation_bundle_plural_{}_idx" , idx) ,
3888
+ array_size : Some ( ms. len ( ) ) ,
3889
+ init : Some ( format ! (
3890
+ "{{ {} }}" ,
3891
+ ms. iter( )
3892
+ . map( |x| {
3893
+ count += x. as_ref( ) . map_or( 0 , |x| x. len( ) ) ;
3894
+ count
3895
+ } )
3896
+ . join( ", " )
3897
+ ) ) ,
3898
+ ..Default :: default ( )
3899
+ } ) ) ;
3900
+ }
3901
+ let lang_len = translations. languages . len ( ) ;
3902
+ declarations. push ( Declaration :: Function ( Function {
3903
+ name : "slint_set_language" . into ( ) ,
3904
+ signature : "(std::string_view lang)" . into ( ) ,
3905
+ is_inline : true ,
3906
+ statements : Some ( vec ! [
3907
+ format!( "std::array<slint::cbindgen_private::Slice<uint8_t>, {lang_len}> languages {{ {} }};" , translations. languages. iter( ) . map( |l| format!( "slint::private_api::string_to_slice({l:?})" ) ) . join( ", " ) ) ,
3908
+ format!( "return slint::cbindgen_private::slint_translate_set_language(slint::private_api::string_to_slice(lang), {{ languages.data(), {lang_len} }});"
3909
+ ) ] ) ,
3910
+ ..Default :: default ( )
3911
+ } ) ) ;
3912
+
3913
+ let ctx = EvaluationContext {
3914
+ compilation_unit,
3915
+ current_sub_component : None ,
3916
+ current_global : None ,
3917
+ generator_state : CppGeneratorContext {
3918
+ global_access : "\n #error \" language rule can't access state\" ;" . into ( ) ,
3919
+ conditional_includes : & Default :: default ( ) ,
3920
+ } ,
3921
+ parent : None ,
3922
+ argument_types : & [ Type :: Int32 ] ,
3923
+ } ;
3924
+ declarations. push ( Declaration :: Var ( Var {
3925
+ ty : format_smolstr ! (
3926
+ "const std::array<uintptr_t (*const)(int32_t), {}>" ,
3927
+ translations. plural_rules. len( )
3928
+ ) ,
3929
+ name : "slint_translated_plural_rules" . into ( ) ,
3930
+ init : Some ( format ! (
3931
+ "{{ {} }}" ,
3932
+ translations
3933
+ . plural_rules
3934
+ . iter( )
3935
+ . map( |s| match s {
3936
+ Some ( s) => {
3937
+ format!(
3938
+ "[]([[maybe_unused]] int32_t arg_0) -> uintptr_t {{ return {}; }}" ,
3939
+ compile_expression( s, & ctx)
3940
+ )
3941
+ }
3942
+ None => "nullptr" . into( ) ,
3943
+ } )
3944
+ . join( ", " )
3945
+ ) ) ,
3946
+ ..Default :: default ( )
3947
+ } ) ) ;
3948
+ }
0 commit comments