Repository: tauri-apps/tauri
File: tooling/bundler/src/bundle/windows/nsis.rs (Rust)

Code before:
      languages_data.push(data);
    } else {
      log::warn!("Custom tauri messages for {lang} are not translated.\nIf it is a valid language listed on <https://github.com/kichik/nsis/tree/9465c08046f00ccb6eda985abbdbf52c275c6c4d/Contrib/Language%20files>, please open a Tauri feature request\n or you can provide a custom language file for it in `tauri.conf.json > bundle > windows > nsis > custom_language_files`");
    }
  }

  data.insert("languages", to_json(languages.clone()));
  data.insert(
    "language_files",
    to_json(
      languages_data
        .iter()
        .map(|d| d.0.clone())
        .collect::<Vec<_>>(),
    ),
  );

  let main_binary = settings
    .binaries()
    .iter()
    .find(|bin| bin.main())
    .ok_or_else(|| anyhow::anyhow!("Failed to get main binary"))?;
  let main_binary_path = settings.binary_path(main_binary).with_extension("exe");
  data.insert(
    "main_binary_name",
    to_json(main_binary.name().strip_suffix(".exe")),
  );
  data.insert("main_binary_path", to_json(&main_binary_path));

  let out_file = "nsis-output.exe";
  data.insert("out_file", to_json(out_file));

  let resources = generate_resource_data(settings)?;
  let resources_dirs =
    std::collections::HashSet::<PathBuf>::from_iter(resources.values().map(|r| r.0.to_owned()));

  let mut resources_ancestors = resources_dirs
    .iter()
    .flat_map(|p| p.ancestors())
    .collect::<Vec<_>>();
  resources_ancestors.sort_unstable();
  resources_ancestors.dedup();
  resources_ancestors.sort_by_key(|p| std::cmp::Reverse(p.components().count()));
  resources_ancestors.pop(); // Last one is always ""

  // We need to convert / to \ for nsis to move the files into the correct dirs
  #[cfg(not(target_os = "windows"))]
  let resources: ResourcesMap = resources
    .into_iter()
    .map(|(r, p)| {
      (

Review comment (suggestion):
Let's add a fallback, just in case it doesn't end with `.exe`
```suggestion
    to_json(main_binary.name().strip_suffix(".exe").unwrap_or(main_binary.name())),
```

Code after:
    to_json(
      nsis
        .map(|nsis| nsis.display_language_selector && languages.len() > 1)
        .unwrap_or(false),
    ),
  );

  let custom_language_files = nsis.and_then(|nsis| nsis.custom_language_files.clone());

  let mut language_files_paths = Vec::new();
  for lang in &languages {
    // if user provided a custom lang file, we rewrite it with BOM
    if let Some(path) = custom_language_files.as_ref().and_then(|h| h.get(lang)) {
      let path = dunce::canonicalize(path)?;
      let path_with_bom = path
        .file_name()
        .map(|f| output_path.join(f))
        .unwrap_or_else(|| output_path.join(format!("{lang}_custom.nsh")));
      let content = std::fs::read(path)?;
      write_utf8_with_bom(&path_with_bom, content)?;
      language_files_paths.push(path_with_bom);
    } else {
      // if user has not provided a custom lang file,
      // we check our translated languages
      if let Some((file_name, content)) = get_lang_data(lang) {
        let path = output_path.join(file_name);
        write_utf8_with_bom(&path, content)?;
        language_files_paths.push(path);
      } else {
        log::warn!("Custom tauri messages for {lang} are not translated.\nIf it is a valid language listed on <https://github.com/kichik/nsis/tree/9465c08046f00ccb6eda985abbdbf52c275c6c4d/Contrib/Language%20files>, please open a Tauri feature request\n or you can provide a custom language file for it in `tauri.conf.json > bundle > windows > nsis > custom_language_files`");
      }
    }
  }
  data.insert("language_files", to_json(language_files_paths));

  let main_binary = settings
    .binaries()
    .iter()
    .find(|bin| bin.main())
    .ok_or_else(|| anyhow::anyhow!("Failed to get main binary"))?;
  let main_binary_path = settings.binary_path(main_binary).with_extension("exe");
  data.insert(
    "main_binary_name",
    to_json(
      main_binary_path
        .file_stem()
        .and_then(|file_name| file_name.to_str())
        .unwrap_or_else(|| main_binary.name()),
    ),
  );
  data.insert("main_binary_path", to_json(&main_binary_path));