Skip to content

Commit

Permalink
[WIP] Added locales folder for translations and added translation to …
Browse files Browse the repository at this point in the history
…strings that are used
  • Loading branch information
florian-nagel authored and Mastermindaxe committed Jun 9, 2024
1 parent 5d4ddcb commit a367e99
Show file tree
Hide file tree
Showing 26 changed files with 444 additions and 141 deletions.
222 changes: 222 additions & 0 deletions locales/app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
_version: 2

"Dry running:":
en: "Dry running:"
"Rebooting...":
en: "Rebooting..."
"Plugins upgraded":
en: "Plugins upgraded"
"Would self-update":
en: "Would self-update"
"Pulling":
en: "Pulling"
"No Breaking changes":
en: "No Breaking changes"
"in":
en: "in"
"Dropping you to shell. Fix what you need and then exit the shell.":
en: "Dropping you to shell. Fix what you need and then exit the shell."
"Topgrade launched in a new tmux session":
en: "Topgrade launched in a new tmux session"
"Topgrade upgraded to ":
en: "Topgrade upgraded to "
"Topgrade is up-to-date":
en: "Topgrade is up-to-date"
"Updating modules...":
en: "Updating modules..."
"Powershell Modules Update":
en: "Powershell Modules Update"
"Powershell is not installed":
en: "Powershell is not installed"
"Error detecting current distribution:":
en: "Error detecting current distribution:"
"Error:":
en: "Error:"
"Failed":
en: "Failed"
"pulling":
en: "pulling"
"Failed to pull":
en: "Failed to pull"
"Changed":
en: "Changed"
"Up-to-date":
en: "Up-to-date"
"Self update":
en: "Self update"
"Would pull":
en: "Would pull"
"Only":
en: "Only"
"updated repositories will be shown...":
en: "updated repositories will be shown..."
"because it has no remotes":
en: "because it has no remotes"
"Skipping":
en: "Skipping"
"Aura requires sudo installed to work with AUR packages":
en: "Aura requires sudo installed to work with AUR packages"
"Pacman backup configuration files found:":
en: "Pacman backup configuration files found:"
"The package audit was successful, but vulnerable packages still remain on the system":
en: "The package audit was successful, but vulnerable packages still remain on the system"
"Syncing portage":
en: "Syncing portage"
"Finding available software":
en: "Finding available software"
"A system update is available. Do you wish to install it?":
en: "A system update is available. Do you wish to install it?"
"No new software available.":
en: "No new software available."
"No Xcode releases installed.":
en: "No Xcode releases installed."
"Would you like to move the former Xcode release to the trash?":
en: "Would you like to move the former Xcode release to the trash?"
"New Xcode release detected:":
en: "New Xcode release detected:"
"Would you like to install it?":
en: "Would you like to install it?"
"No global packages installed":
en: "No global packages installed"
"Connecting to":
en: "Connecting to"
"Remote Topgrade launched in Tmux":
en: "Remote Topgrade launched in Tmux"
"Remote Topgrade launched in an external terminal":
en: "Remote Topgrade launched in an external terminal"
"Collecting Vagrant boxes":
en: "Collecting Vagrant boxes"
"No Vagrant directories were specified in the configuration file":
en: "No Vagrant directories were specified in the configuration file"
"Vagrant output in":
en: "Vagrant output in"
"Vagrant line":
en: "Vagrant line"
"Error collecting vagrant boxes from":
en: "Error collecting vagrant boxes from"
"Skipping powered off box":
en: "Skipping powered off box"
"Vagrant boxes":
en: "Vagrant boxes"
"No outdated boxes":
en: "No outdated boxes"
"No home directory":
en: "No home directory"
"Version":
en: "Version"
"OS":
en: "OS"
"Binary path":
en: "Binary path"
"self-update Feature Enabled":
en: "self-update Feature Enabled"
"Configuration":
en: "Configuration"
"Summary":
en: "Summary"
"Failed to execute shell":
en: "Failed to execute shell"
"Failed to reboot":
en: "Failed to reboot"
"Topgrade finished with errors":
en: "Topgrade finished with errors"
"Topgrade finished successfully":
en: "Topgrade finished successfully"
"Topgrade version is not semantic":
en: "Topgrade version is not semantic"
"Topgrade version is not dot-separated numbers":
en: "Topgrade version is not dot-separated numbers"
"Version numbers can not be all 0s":
en: "Version numbers can not be all 0s"
"should be a valid version":
en: "should be a valid version"
"Breaking Changes":
en: "Breaking Changes"
"Stdout contained invalid UTF-8":
en: "Stdout contained invalid UTF-8"
"Stderr contained invalid UTF-8":
en: "Stderr contained invalid UTF-8"
"Failed to execute":
en: "Failed to execute"
"Command failed":
en: "Command failed"
"Executing command":
en: "Executing command"
"Configuration at":
en: "Configuration at"
"No configuration exists":
en: "No configuration exists"
"Unable to write the example configuration file to":
en: "Unable to write the example configuration file to %{location}: %{error}. Using blank config."
"Found additional (directory) configuration file at":
en: "Found additional (directory) configuration file at %{path}"
"No additional configuration directory exists, creating one":
en: "No additional configuration directory exists, creating one"
"Unable to read":
en: "Unable to read"
"Failed to deserialize":
en: "Failed to deserialize"
"Failed to compile regex":
en: "Failed to compile regex"
"Failed to deserialize an include section of":
en: "Failed to deserialize an include section of"
"Path expanded to":
en: "Path expanded %{path} to %{expanded}"
"Loaded configuration":
en: "Loaded configuration"
"Editor":
en: "Editor"
"Failed to open configuration file editor":
en: "Failed to open configuration file editor"
"Adding [misc] section to":
en: "Adding [misc] section to %{path}"
"Tried to auto-migrate the config file, unable to write to config file.\nPlease add \"[misc]\" section manually to the first line of the file.\nError":
en: "Tried to auto-migrate the config file, unable to write to config file.\nPlease add \"[misc]\" section manually to the first line of the file.\nError"
"failed to load configuration":
en: "failed to load configuration"
"Configuration directory {} does not exist":
en: "Configuration directory %{directory} does not exist"
"Failed to parse `tmux_arguments`":
en: "Failed to parse `tmux_arguments`"
"Running":
en: "Running"
"{key} already reported":
en: "%{key} already reported"
"Step":
en: "Step"
"failed":
en: "failed"
"Current exe in":
en: "Current exe in"
"Moving it to":
en: "Moving it to"
"exists. Topgrade was probably upgraded":
en: "exists. Topgrade was probably upgraded"
"Moved Topgrade back from":
en: "Moved Topgrade back from"
"to":
en: "to"
"Could not move Topgrade from {} back to {}: {}":
en: "Could not move Topgrade from %{temp_path} back to %{exe_path}: {error}"
"Failed to elevate permissions":
en: "Failed to elevate permissions"
"Desktop notification":
en: "Desktop notification"
"Error reading from terminal":
en: "Error reading from terminal"
"Quit from user input":
en: "Quit from user input"
"Path":
en: "Path"
"exists":
en: "exists"
"doesn't exist":
en: "doesn't exist"
"Detected":
en: "Detected"
"as":
en: "as"
"Cannot find":
en: "Cannot find"
"Detecting":
en: "Detecting"
24 changes: 13 additions & 11 deletions src/breaking_changes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::WINDOWS_DIRS;
use crate::XDG_DIRS;
use color_eyre::eyre::Result;
use etcetera::base_strategy::BaseStrategy;
use rust_i18n::t;
use std::{
env::var,
fs::{read_to_string, OpenOptions},
Expand All @@ -34,18 +35,19 @@ impl FromStr for Version {
type Err = std::convert::Infallible;

fn from_str(s: &str) -> Result<Self, Self::Err> {
const NOT_SEMVER: &str = "Topgrade version is not semantic";
const NOT_NUMBER: &str = "Topgrade version is not dot-separated numbers";
let not_semver = t!("Topgrade version is not semantic").to_string();
let not_number = t!("Topgrade version is not dot-separated numbers").to_string();

let mut iter = s.split('.').take(3);
let major = iter.next().expect(NOT_SEMVER).parse().expect(NOT_NUMBER);
let minor = iter.next().expect(NOT_SEMVER).parse().expect(NOT_NUMBER);
let patch = iter.next().expect(NOT_SEMVER).parse().expect(NOT_NUMBER);
let major = iter.next().expect(&not_semver).parse().expect(&not_number);
let minor = iter.next().expect(&not_semver).parse().expect(&not_number);
let patch = iter.next().expect(&not_semver).parse().expect(&not_number);

// They cannot be all 0s
assert!(
!(major == 0 && minor == 0 && patch == 0),
"Version numbers can not be all 0s"
"{}",
t!("Version numbers can not be all 0s")
);

Ok(Self {
Expand Down Expand Up @@ -102,7 +104,7 @@ pub(crate) fn should_skip() -> bool {

/// True if this is the first execution of a major release.
pub(crate) fn first_run_of_major_release() -> Result<bool> {
let version = VERSION_STR.parse::<Version>().expect("should be a valid version");
let version = VERSION_STR.parse::<Version>().expect(&*t!("should be a valid version"));
let keep_file = keep_file_path();

// disable this lint here as the current code has better readability
Expand All @@ -118,12 +120,12 @@ pub(crate) fn first_run_of_major_release() -> Result<bool> {

/// Print breaking changes to the user.
pub(crate) fn print_breaking_changes() {
let header = format!("Topgrade {VERSION_STR} Breaking Changes");
let header = format!("Topgrade {VERSION_STR} {}", t!("Breaking Changes"));
print_separator(header);
let contents = if BREAKINGCHANGES.is_empty() {
"No Breaking changes"
t!("No Breaking changes").to_string()
} else {
BREAKINGCHANGES
BREAKINGCHANGES.to_string()
};
println!("{contents}\n");
}
Expand Down Expand Up @@ -159,7 +161,7 @@ mod test {
}

#[test]
#[should_panic(expected = "Version numbers can not be all 0s")]
#[should_panic(expected = "Version numbers can not be all 0s")] // TODO: Problems with i18n?

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment
fn invalid_version() {
let all_0 = "0.0.0";
all_0.parse::<Version>().unwrap();
Expand Down
29 changes: 17 additions & 12 deletions src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::process::{Command, ExitStatus, Output};
use color_eyre::eyre;
use color_eyre::eyre::eyre;
use color_eyre::eyre::Context;
use rust_i18n::t;

use crate::error::TopgradeError;

Expand All @@ -26,13 +27,15 @@ impl TryFrom<Output> for Utf8Output {
fn try_from(Output { status, stdout, stderr }: Output) -> Result<Self, Self::Error> {
let stdout = String::from_utf8(stdout).map_err(|err| {
eyre!(
"Stdout contained invalid UTF-8: {}",
"{}: {}",
t!("Stdout contained invalid UTF-8"),
String::from_utf8_lossy(err.as_bytes())
)
})?;
let stderr = String::from_utf8(stderr).map_err(|err| {
eyre!(
"Stderr contained invalid UTF-8: {}",
"{}: {}",
t!("Stderr contained invalid UTF-8"),
String::from_utf8_lossy(err.as_bytes())
)
})?;
Expand All @@ -47,13 +50,15 @@ impl TryFrom<&Output> for Utf8Output {
fn try_from(Output { status, stdout, stderr }: &Output) -> Result<Self, Self::Error> {
let stdout = String::from_utf8(stdout.to_vec()).map_err(|err| {
eyre!(
"Stdout contained invalid UTF-8: {}",
"{}: {}",
t!("Stdout contained invalid UTF-8"),
String::from_utf8_lossy(err.as_bytes())
)
})?;
let stderr = String::from_utf8(stderr.to_vec()).map_err(|err| {
eyre!(
"Stderr contained invalid UTF-8: {}",
"{}: {}",
t!("Stderr contained invalid UTF-8"),
String::from_utf8_lossy(err.as_bytes())
)
})?;
Expand Down Expand Up @@ -163,12 +168,12 @@ impl CommandExt for Command {
#[allow(clippy::disallowed_methods)]
let output = self
.output()
.with_context(|| format!("Failed to execute `{command}`"))?;
.with_context(|| format!("{} `{command}`", t!("Failed to execute")))?;

if succeeded(&output).is_ok() {
Ok(output)
} else {
let mut message = format!("Command failed: `{command}`");
let mut message = format!("{}: `{command}`", t!("Command failed"));
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);

Expand All @@ -185,14 +190,14 @@ impl CommandExt for Command {
let err = TopgradeError::ProcessFailedWithOutput(program, output.status, stderr.into_owned());

let ret = Err(err).with_context(|| message);
debug!("Command failed: {ret:?}");
debug!("{}: {ret:?}", t!("Command failed"));
ret
}
}

fn status_checked_with(&mut self, succeeded: impl Fn(ExitStatus) -> Result<(), ()>) -> eyre::Result<()> {
let command = log(self);
let message = format!("Failed to execute `{command}`");
let message = format!("{} `{command}`", t!("Failed to execute"));

// This is where we implement `status_checked`, which is what we prefer to use instead of
// `status`, so we allow `Command::status` here.
Expand All @@ -204,15 +209,15 @@ impl CommandExt for Command {
} else {
let (program, _) = get_program_and_args(self);
let err = TopgradeError::ProcessFailed(program, status);
let ret = Err(err).with_context(|| format!("Command failed: `{command}`"));
debug!("Command failed: {ret:?}");
let ret = Err(err).with_context(|| format!("{}: `{command}`", t!("Command failed")));
debug!("{}: {ret:?}", t!("Command failed"));
ret
}
}

fn spawn_checked(&mut self) -> eyre::Result<Self::Child> {
let command = log(self);
let message = format!("Failed to execute `{command}`");
let message = format!("{} `{command}`", t!("Failed to execute"));

// This is where we implement `spawn_checked`, which is what we prefer to use instead of
// `spawn`, so we allow `Command::spawn` here.
Expand Down Expand Up @@ -241,6 +246,6 @@ fn format_program_and_args(cmd: &Command) -> String {

fn log(cmd: &Command) -> String {
let command = format_program_and_args(cmd);
debug!("Executing command `{command}`");
debug!("{} `{command}`", t!("Executing command"));
command
}
Loading

0 comments on commit a367e99

Please sign in to comment.