diff --git a/.changes/nsis-encoding.md b/.changes/nsis-encoding.md new file mode 100644 index 000000000..5e936e96e --- /dev/null +++ b/.changes/nsis-encoding.md @@ -0,0 +1,5 @@ +--- +'tauri-bundler': 'patch:bug' +--- + +Fix NSIS bundler failing to build when `productName` contained chinsese characters. diff --git a/tooling/bundler/Cargo.toml b/tooling/bundler/Cargo.toml index 88428c494..fdf20a098 100644 --- a/tooling/bundler/Cargo.toml +++ b/tooling/bundler/Cargo.toml @@ -31,7 +31,6 @@ handlebars = "4.3" tempfile = "3.5.0" log = { version = "0.4.17", features = [ "kv_unstable" ] } dirs-next = "2.0" -encoding_rs = "0.8" os_pipe = "1" attohttpc = { version = "0.25", default-features = false } hex = "0.4" diff --git a/tooling/bundler/src/bundle/windows/nsis.rs b/tooling/bundler/src/bundle/windows/nsis.rs index ed4f20657..57960c879 100644 --- a/tooling/bundler/src/bundle/windows/nsis.rs +++ b/tooling/bundler/src/bundle/windows/nsis.rs @@ -258,16 +258,14 @@ fn build_nsis_app_installer( }), ); - let languages_data = languages - .iter() - .filter_map(|lang| { - if let Some(data) = get_lang_data(lang, custom_language_files.as_ref()) { - Some(data) + let mut languages_data = Vec::new(); + for lang in &languages { + if let Some(data) = get_lang_data(lang, custom_language_files.as_ref())? { + languages_data.push(data); } else { log::warn!("Custom tauri messages for {lang} are not translated.\nIf it is a valid language listed on , please open a Tauri feature request\n or you can provide a custom language file for it in `tauri.conf.json > tauri > bundle > windows > nsis > custom_language_files`"); - None } - }).collect::>(); + } data.insert("languages", to_json(languages.clone())); data.insert( @@ -417,19 +415,14 @@ fn build_nsis_app_installer( .expect("Failed to setup handlebar template"); } let installer_nsi_path = output_path.join("installer.nsi"); - write( + write_ut16_le_with_bom( &installer_nsi_path, - encoding_rs::UTF_8 - .encode(handlebars.render("installer.nsi", &data)?.as_str()) - .0, + handlebars.render("installer.nsi", &data)?.as_str(), )?; for (lang, data) in languages_data.iter() { - if let Some((content, encoding)) = data { - write( - output_path.join(lang).with_extension("nsh"), - encoding.encode(content).0, - )?; + if let Some(content) = data { + write_ut16_le_with_bom(output_path.join(lang).with_extension("nsh"), content)?; } } @@ -553,113 +546,44 @@ fn generate_binaries_data(settings: &Settings) -> crate::Result { fn get_lang_data( lang: &str, custom_lang_files: Option<&HashMap>, -) -> Option<( - String, - Option<(&'static str, &'static encoding_rs::Encoding)>, -)> { - use encoding_rs::*; - +) -> crate::Result)>> { if let Some(path) = custom_lang_files.and_then(|h| h.get(lang)) { - return Some(( - dunce::canonicalize(path) - .unwrap() - .to_string_lossy() - .to_string(), - None, - )); + return Ok(Some((dunce::canonicalize(path)?, None))); } - let lang_file = format!("{lang}.nsh"); - match lang.to_lowercase().as_str() { - "arabic" => Some(( - lang_file, - Some(( - include_str!("./templates/nsis-languages/Arabic.nsh"), - UTF_16LE, - )), + let lang_path = PathBuf::from(format!("{lang}.nsh")); + let lang_content = match lang.to_lowercase().as_str() { + "arabic" => Some(include_str!("./templates/nsis-languages/Arabic.nsh")), + "dutch" => Some(include_str!("./templates/nsis-languages/Dutch.nsh")), + "english" => Some(include_str!("./templates/nsis-languages/English.nsh")), + "japanese" => Some(include_str!("./templates/nsis-languages/Japanese.nsh")), + "korean" => Some(include_str!("./templates/nsis-languages/Korean.nsh")), + "portuguesebr" => Some(include_str!("./templates/nsis-languages/PortugueseBR.nsh")), + "tradchinese" => Some(include_str!("./templates/nsis-languages/TradChinese.nsh")), + "simpchinese" => Some(include_str!("./templates/nsis-languages/SimpChinese.nsh")), + "french" => Some(include_str!("./templates/nsis-languages/French.nsh")), + "spanish" => Some(include_str!("./templates/nsis-languages/Spanish.nsh")), + "spanishinternational" => Some(include_str!( + "./templates/nsis-languages/SpanishInternational.nsh" )), - "dutch" => Some(( - lang_file, - Some((include_str!("./templates/nsis-languages/Dutch.nsh"), UTF_8)), - )), - "english" => Some(( - lang_file, - Some(( - include_str!("./templates/nsis-languages/English.nsh"), - UTF_8, - )), - )), - "japanese" => Some(( - lang_file, - Some(( - include_str!("./templates/nsis-languages/Japanese.nsh"), - UTF_8, - )), - )), - "korean" => Some(( - lang_file, - Some((include_str!("./templates/nsis-languages/Korean.nsh"), UTF_8)), - )), - "portuguesebr" => Some(( - lang_file, - Some(( - include_str!("./templates/nsis-languages/PortugueseBR.nsh"), - UTF_8, - )), - )), - "tradchinese" => Some(( - lang_file, - Some(( - include_str!("./templates/nsis-languages/TradChinese.nsh"), - UTF_8, - )), - )), - "simpchinese" => Some(( - lang_file, - Some(( - include_str!("./templates/nsis-languages/SimpChinese.nsh"), - UTF_8, - )), - )), - "french" => Some(( - lang_file, - Some((include_str!("./templates/nsis-languages/French.nsh"), UTF_8)), - )), - "spanish" => Some(( - lang_file, - Some(( - include_str!("./templates/nsis-languages/Spanish.nsh"), - UTF_8, - )), - )), - "spanishinternational" => Some(( - lang_file, - Some(( - include_str!("./templates/nsis-languages/SpanishInternational.nsh"), - UTF_8, - )), - )), - "persian" => Some(( - lang_file, - Some(( - include_str!("./templates/nsis-languages/Persian.nsh"), - UTF_16LE, - )), - )), - "turkish" => Some(( - lang_file, - Some(( - include_str!("./templates/nsis-languages/Turkish.nsh"), - UTF_8, - )), - )), - "swedish" => Some(( - lang_file, - Some(( - include_str!("./templates/nsis-languages/Swedish.nsh"), - UTF_8, - )), - )), - _ => None, - } + "persian" => Some(include_str!("./templates/nsis-languages/Persian.nsh")), + "turkish" => Some(include_str!("./templates/nsis-languages/Turkish.nsh")), + "swedish" => Some(include_str!("./templates/nsis-languages/Swedish.nsh")), + _ => return Ok(None), + }; + + Ok(Some((lang_path, lang_content))) +} + +fn write_ut16_le_with_bom>(path: P, content: &str) -> crate::Result<()> { + use std::fs::File; + use std::io::{BufWriter, Write}; + + let file = File::create(path)?; + let mut output = BufWriter::new(file); + output.write_all(&[0xFF, 0xFE])?; // the BOM part + for utf16 in content.encode_utf16() { + output.write_all(&utf16.to_le_bytes())?; + } + Ok(()) } diff --git a/tooling/bundler/src/bundle/windows/templates/nsis-languages/Persian.nsh b/tooling/bundler/src/bundle/windows/templates/nsis-languages/Persian.nsh index 1522bec2b..5e509f901 100644 --- a/tooling/bundler/src/bundle/windows/templates/nsis-languages/Persian.nsh +++ b/tooling/bundler/src/bundle/windows/templates/nsis-languages/Persian.nsh @@ -24,4 +24,4 @@ LangString webview2DownloadSuccess ${LANG_PERSIAN} "WebView2 بوت استرپر LangString webview2Downloading ${LANG_PERSIAN} "دانلود بوت استرپر WebView2..." LangString webview2InstallError ${LANG_PERSIAN} "ارور: نصب WebView2 با کد $1 شکست خورد" LangString webview2InstallSuccess ${LANG_PERSIAN} "WebView2 با موفقیت نصب شد" -LangString deleteAppData ${LANG_PERSIAN} "حذف دیتا های اپلیکیشن" \ No newline at end of file +LangString deleteAppData ${LANG_PERSIAN} "حذف دیتا های اپلیکیشن" diff --git a/tooling/cli/Cargo.lock b/tooling/cli/Cargo.lock index f1910b9af..24e0b3aa6 100644 --- a/tooling/cli/Cargo.lock +++ b/tooling/cli/Cargo.lock @@ -163,17 +163,17 @@ dependencies = [ [[package]] name = "attohttpc" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2" +checksum = "7e57d6e7a84f33ff3316e97af3180fe7f86597a6a60161c0be70c0e45f382620" dependencies = [ "http", "log", "native-tls", - "rustls", + "rustls 0.21.1", "url", "webpki", - "webpki-roots", + "webpki-roots 0.23.0", ] [[package]] @@ -2764,6 +2764,28 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-webpki" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "ryu" version = "1.0.13" @@ -3253,7 +3275,6 @@ dependencies = [ "bitness", "dirs-next", "dunce", - "encoding_rs", "glob", "handlebars", "heck", @@ -3762,10 +3783,10 @@ dependencies = [ "flate2", "log", "once_cell", - "rustls", + "rustls 0.20.8", "url", "webpki", - "webpki-roots", + "webpki-roots 0.22.6", ] [[package]] @@ -3952,6 +3973,15 @@ dependencies = [ "webpki", ] +[[package]] +name = "webpki-roots" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa54963694b65584e170cf5dc46aeb4dcaa5584e652ff5f3952e56d66aff0125" +dependencies = [ + "rustls-webpki", +] + [[package]] name = "weezl" version = "0.1.7"