Merge pull request #9684 from yahya-nusseibeh/fix/nightly-v2-signatures

Nightly: sign each build for its own version (SHA256SUMS.v2.sig)
This commit is contained in:
Ludovic Marie authored and GitHub committed 2026-11-05 12:57:48 +01:00
commit f319701e8c
98 files changed
+788 -178

No files matched your search

+15 -2
View File
@@ -165,11 +165,15 @@ jobs:
path: dist
pattern: horizon-*
merge-multiple: true
- name: Sign the checksums (SHA256SUMS, SHA256SUMS.sig) for the nightly channel
- name: Sign the checksums for the nightly channel (SHA256SUMS.sig) and for this build (SHA256SUMS.v2.sig)
# SHA256SUMS.sig is for launchers from before v2 (signed for "nightly"); SHA256SUMS.v2.sig is signed for
# nightly-<date>-<commit>, the version the release title names, which current launchers and servers
# require (docs/security.md, "Nightly signatures"). The publish step titles the release from the same values.
env:
RELEASE_SIGNING_KEY: ${{ secrets.RELEASE_SIGNING_KEY }}
RELEASE_SIGNING_KEY_NEXT: ${{ secrets.RELEASE_SIGNING_KEY_NEXT }}
EPHEMERAL: ${{ needs.pick.outputs.dry_run == 'true' && 'yes' || '' }}
ALSO_FOR: nightly-${{ needs.pick.outputs.date }}-${{ needs.pick.outputs.short }}
run: |
# Windows ARM64's build may fail without holding the Nightly (game-build.yml): then it is left out.
arm64=(); if [[ -f dist/horizon-windows-arm64.zip ]]; then arm64=(dist/horizon-windows-arm64.zip)
@@ -208,12 +212,17 @@ jobs:
with:
path: dist
merge-multiple: true
- name: The signature, checked as launchers check it
- name: The signatures, checked as launchers check them
env:
EPHEMERAL: ${{ needs.pick.outputs.dry_run == 'true' && 'yes' || '' }}
DATE: ${{ needs.pick.outputs.date }}
SHORT: ${{ needs.pick.outputs.short }}
run: |
key=(); [[ -n "$EPHEMERAL" ]] && key=(--key "$(cat dist/ephemeral.pub)")
cargo run --locked --quiet -p horizon-release-sign -- verify --tag nightly --publishing "${key[@]}" dist
# The version's own signature, which current launchers require: the title below names the same version.
cargo run --locked --quiet -p horizon-release-sign -- verify --tag "nightly-${DATE}-${SHORT}" \
--signature SHA256SUMS.v2.sig --publishing "${key[@]}" dist
- name: Ready to publish (the smoke test drew a world, no release-blocker is open)
# Right before publishing, as for a release: an issue labelled while the builds ran still holds it. A dry run
# only reports what a real run would do (that is how a blocker's fix is tried).
@@ -230,12 +239,16 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
SHA: ${{ needs.pick.outputs.sha }}
SHORT: ${{ needs.pick.outputs.short }}
DATE: ${{ needs.pick.outputs.date }}
SOURCE_TAG: ${{ needs.pick.outputs.source_tag }}
run: |
set -euo pipefail
python3 tools/ci/nightly.py rotate
signature=(); [[ -f dist/SHA256SUMS.sig ]] && signature=(dist/SHA256SUMS.sig)
[[ -f dist/SHA256SUMS.v2.sig ]] && signature+=(dist/SHA256SUMS.v2.sig)
# The title is what launchers parse (strictly) into the version SHA256SUMS.v2.sig is signed for.
[[ "${SHA:0:7}" == "$SHORT" ]] || { echo "::error::the build's commit isn't the one signed"; exit 1; }
# The ARM64 archive only when its build succeeded (the sign job left it out of SHA256SUMS otherwise).
arm64=()
if [[ -f dist/horizon-windows-arm64.zip ]]; then
+145 -11
View File
@@ -20,6 +20,11 @@ use ring::signature::{ED25519, Ed25519KeyPair, KeyPair, UnparsedPublicKey};
pub const SUMS: &str = "SHA256SUMS";
/// Its signatures' asset name.
pub const SIGNATURE: &str = "SHA256SUMS.sig";
/// A Nightly's second signature file: the same checksum list signed for the Nightly's own version
/// (`horizon release nightly-<date>-<commit>`) rather than for the channel, so an older Nightly can't
/// be served as a newer one. Nightlies carry both while launchers that only read [`SIGNATURE`] are
/// in use (docs/security.md, "Nightly signatures"); current launchers and servers require this one.
pub const SIGNATURE_V2: &str = "SHA256SUMS.v2.sig";
const KEYS: &str = include_str!("../release-keys.txt");
const LEGACY: &str = include_str!("../legacy-releases.txt");
@@ -124,9 +129,10 @@ pub fn is_nightly(tag: &str) -> bool {
tag == NIGHTLY || tag.starts_with("nightly-")
}
/// The version a nightly installs as, from its release title ("Nightly 2026-10-28 · 0c02067"):
/// The version a nightly is listed as, from its release title ("Nightly 2026-10-28 · 0c02067"):
/// `nightly-2026-10-28-0c02067`. `published` (GitHub's `published_at`) dates a title without one.
/// The launcher and `horizon-server` name it the same way, and native mods read the commit back.
/// For listing only: what installs is checked against [`nightly_title_version`], which has no
/// fallback, since nothing signs `published`.
pub fn nightly_version(title: &str, published: &str) -> String {
let mut words = title
.strip_prefix("Nightly ")
@@ -182,15 +188,61 @@ pub fn signed_digest(
digest_in(tag, tag, asset, sums, signature, keys)
}
/// The signed SHA-256 of `asset` in the nightly build: its checksums must be signed for the
/// [`NIGHTLY`] channel, so a release's signed list (or one replayed from a release) is refused.
/// The version a Nightly's GitHub title names, strictly: `Nightly 2026-10-28 · 0c02067` (as
/// nightly-build.yml writes it) gives `nightly-2026-10-28-0c02067`. Anything else is None: a
/// Nightly is verified against the version it installs as, so a title that doesn't name its date
/// and commit is refused rather than dated by when GitHub says it was published.
pub fn nightly_title_version(title: &str) -> Option<String> {
let (date, commit) = title.strip_prefix("Nightly ")?.split_once(" · ")?;
let commit_ok = (7..=40).contains(&commit.len())
&& commit
.bytes()
.all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b));
(is_date(date) && commit_ok).then(|| format!("{NIGHTLY}-{date}-{commit}"))
}
/// Whether `version` is a Nightly build's full version, `nightly-<date>-<commit>`, the form its
/// [`SIGNATURE_V2`] is signed for.
pub fn is_nightly_build(version: &str) -> bool {
version
.strip_prefix("nightly-")
.and_then(|rest| rest.split_at_checked(10))
.is_some_and(|(date, commit)| {
is_date(date)
&& commit.strip_prefix('-').is_some_and(|c| {
(7..=40).contains(&c.len())
&& c.bytes()
.all(|b| b.is_ascii_digit() || (b'a'..=b'f').contains(&b))
})
})
}
/// The signed SHA-256 of `asset` in the Nightly that installs as `version`
/// (`nightly-<date>-<commit>`, from [`nightly_title_version`]): `signature` is its
/// [`SIGNATURE_V2`], which must sign `sums` for exactly that version. A release's list, the channel
/// signature (`nightly`) and another Nightly's are all refused, so an older Nightly can't be passed off
/// as tonight's.
pub fn nightly_digest(
version: &str,
asset: &str,
sums: Option<&[u8]>,
signature: Option<&str>,
keys: &[PublicKey],
) -> Result<String, String> {
digest_in(NIGHTLY, "The Nightly build", asset, sums, signature, keys)
if !is_nightly_build(version) {
return Err(format!(
"{version:?} doesn't name a Nightly's date and commit, so it can't be checked: not installed."
));
}
let Some(signature) = signature else {
return Err(format!(
"{version} has no {SIGNATURE_V2} (its signature for this exact build): it was published \
before Nightlies were signed for their own version, so it can't be checked and was not \
installed. Pick a Nightly published since then; `horizon-server rollback` still goes back \
to a build a server already has."
));
};
digest_in(version, version, asset, sums, Some(signature), keys)
}
/// `asset`'s SHA-256 in `sums`, once one of `keys` is found to have signed them for `signed_for`;
@@ -404,30 +456,112 @@ mod tests {
/// round: one key signs both, and only the message's channel keeps them apart.
#[test]
fn nightly_and_release_signatures_never_pass_for_each_other() {
let (nightly, sums, signature) = signed(NIGHTLY);
const TONIGHT: &str = "nightly-2026-10-28-0c02067";
let (nightly, sums, signature) = signed(TONIGHT);
let keys = [nightly.public()];
let asset = "horizon-windows-x64.zip";
let digest = nightly_digest(asset, Some(sums.as_bytes()), Some(&signature), &keys);
let digest = nightly_digest(
TONIGHT,
asset,
Some(sums.as_bytes()),
Some(&signature),
&keys,
);
assert_eq!(digest, Ok(sha256_hex(b"windows")));
// Served under a release's tag: the message names the nightly channel, not v0.2.81.
// Served under a release's tag: the message names the Nightly, not v0.2.81.
for tag in ["v0.2.81", "v2026.10.28", "0.2.81"] {
let as_release =
signed_digest(tag, asset, Some(sums.as_bytes()), Some(&signature), &keys);
assert!(as_release.is_err(), "{tag} took a nightly's signature");
}
// Asked for by a nightly tag on the release channel: refused before any signature is read.
for tag in [NIGHTLY, "nightly-2026-10-27"] {
for tag in [NIGHTLY, "nightly-2026-10-27", TONIGHT] {
let err = signed_digest(tag, asset, Some(sums.as_bytes()), Some(&signature), &keys);
assert!(err.unwrap_err().contains("Nightly build"), "{tag}");
}
// A release's signed list replayed as tonight's nightly.
let (release, sums, signature) = signed("v0.2.81");
let keys = [release.public()];
assert!(nightly_digest(asset, Some(sums.as_bytes()), Some(&signature), &keys).is_err());
assert!(nightly_digest(asset, Some(sums.as_bytes()), None, &keys).is_err());
assert!(
nightly_digest(
TONIGHT,
asset,
Some(sums.as_bytes()),
Some(&signature),
&keys
)
.is_err()
);
assert!(nightly_digest(TONIGHT, asset, Some(sums.as_bytes()), None, &keys).is_err());
assert!(is_nightly("nightly-2026-10-27") && !is_nightly("v0.2.81"));
}
#[test]
fn an_older_nightly_is_not_tonights() {
let asset = "horizon-windows-x64.zip";
// Last week's build, re-served under tonight's title: its v2 signature names last week.
let (key, sums, old) = signed("nightly-2026-10-21-aaaaaaa");
let keys = [key.public()];
let tonight = nightly_title_version("Nightly 2026-10-28 · 0c02067").unwrap();
let err = nightly_digest(&tonight, asset, Some(sums.as_bytes()), Some(&old), &keys);
assert!(err.is_err(), "an older Nightly passed as {tonight}");
// The channel signature (SHA256SUMS.sig, for launchers from before v2) is no v2 signature.
let (key, sums, channel) = signed(NIGHTLY);
let keys = [key.public()];
assert!(
nightly_digest(
&tonight,
asset,
Some(sums.as_bytes()),
Some(&channel),
&keys
)
.is_err()
);
// And a version that isn't a full Nightly build is refused whatever signs it.
for version in [NIGHTLY, "nightly-2026-10-28", "v0.2.81"] {
let (key, sums, signature) = signed(version);
let err = nightly_digest(
version,
asset,
Some(sums.as_bytes()),
Some(&signature),
&[key.public()],
);
assert!(err.unwrap_err().contains("doesn't name"), "{version}");
}
}
#[test]
fn a_nightlys_title_is_parsed_strictly() {
assert_eq!(
nightly_title_version("Nightly 2026-10-28 · 0c02067").as_deref(),
Some("nightly-2026-10-28-0c02067")
);
assert_eq!(
nightly_title_version(&format!("Nightly 2026-10-28 · {}", "a".repeat(40))),
Some(format!("nightly-2026-10-28-{}", "a".repeat(40)))
);
for title in [
"Something else",
"Nightly 2026-10-28",
"Nightly 2026-10-28 · ",
"Nightly 2026-10-28 · 0c020", // too short
"Nightly 2026-10-28 · 0C02067", // GitHub's short SHAs are lowercase
"Nightly 2026-10-28 · 0c02067 x", // trailing words
"Nightly 2026-1-28 · 0c02067", // not a date
"nightly 2026-10-28 · 0c02067",
" Nightly 2026-10-28 · 0c02067",
"Nightly 2026-10-28 · 0c02067/../x",
] {
assert_eq!(nightly_title_version(title), None, "{title:?}");
}
assert!(is_nightly_build("nightly-2026-10-28-0c02067"));
assert!(!is_nightly_build("nightly-2026-10-28"));
assert!(!is_nightly_build("nightly-2026-10-28-"));
assert!(!is_nightly_build("nightly-2026-10-28-0c02067-x"));
}
#[test]
fn a_nightly_is_named_by_its_date_and_commit() {
let v = nightly_version("Nightly 2026-10-28 · 0c02067", "2026-10-28T20:40:00Z");
+17 -6
View File
@@ -3,10 +3,11 @@
//! job that holds the private key runs only the runner's sha256sum and OpenSSL, no code from the
//! repository.
//!
//! horizon-release-sign verify --tag v2026.10.19 [--key <base64>] [--publishing] <folder>
//! horizon-release-sign verify --tag v2026.10.19 [--key <base64>] [--signature <file>] [--publishing] <folder>
//! horizon-release-sign keygen --public-out key.pub | gh secret set RELEASE_SIGNING_KEY --env release
//!
//! `verify` checks SHA256SUMS.sig and every file SHA256SUMS lists with the keys built in from
//! `verify` checks SHA256SUMS.sig (or `--signature`, e.g. a Nightly's SHA256SUMS.v2.sig with
//! `--tag nightly-<date>-<commit>`) and every file SHA256SUMS lists with the keys built in from
//! release-keys.txt (or `--key`), as the launcher does. With `--publishing` (release.yml) a release
//! may go out unsigned, or signed with a key nobody can check yet, only while release-keys.txt
//! lists no key; once it lists one, anything launchers would refuse fails the release.
@@ -22,8 +23,8 @@ fn main() -> ExitCode {
Some("verify") => check_folder(&args[1..]),
Some("keygen") => keygen(&args[1..]),
_ => Err(
"usage: horizon-release-sign verify --tag <tag> [--key <base64>]... [--publishing] \
<folder> | keygen --public-out <file>"
"usage: horizon-release-sign verify --tag <tag> [--key <base64>]... [--signature <file>] \
[--publishing] <folder> | keygen --public-out <file>"
.into(),
),
};
@@ -76,6 +77,16 @@ fn file_hash(path: &Path) -> Result<String, String> {
fn check_folder(args: &[String]) -> Result<(), String> {
let (tag, rest) = tag_of(args)?;
let (keys, rest) = options(&rest, "--key");
let (signature_file, rest) = options(&rest, "--signature");
let signature_file = signature_file
.into_iter()
.next()
.unwrap_or_else(|| SIGNATURE.to_owned());
if signature_file.contains(['/', '\\']) {
return Err(format!(
"--signature names a file of the folder, not {signature_file:?}"
));
}
let publishing = rest.iter().any(|a| a == "--publishing");
let folder = PathBuf::from(
rest.iter()
@@ -88,7 +99,7 @@ fn check_folder(args: &[String]) -> Result<(), String> {
parse_keys(&keys.join("\n"))?
};
let sums = std::fs::read(folder.join(SUMS)).map_err(|e| format!("{SUMS}: {e}"))?;
let listed = match std::fs::read_to_string(folder.join(SIGNATURE)) {
let listed = match std::fs::read_to_string(folder.join(&signature_file)) {
Ok(signature) if !keys.is_empty() => verify(&tag, &sums, &signature, &keys)?,
Ok(_) if publishing => {
println!(
@@ -105,7 +116,7 @@ fn check_folder(args: &[String]) -> Result<(), String> {
Ok(_) => return Err("no key to check the signature with".into()),
Err(_) => {
return Err(format!(
"{tag} has no {SIGNATURE}: launchers would refuse it (is the release environment's \
"{tag} has no {signature_file}: launchers would refuse it (is the release environment's \
RELEASE_SIGNING_KEY set?)"
));
}
+73 -2
View File
@@ -1,5 +1,5 @@
//! The release steps as release.yml runs them: `sums`, tools/ci/sign_release.sh (OpenSSL), `verify`.
use horizon_release_sign::{SIGNATURE, SUMS, SigningKey, trusted_keys};
use horizon_release_sign::{SIGNATURE, SIGNATURE_V2, SUMS, SigningKey, trusted_keys};
use std::path::{Path, PathBuf};
use std::process::{Command, Output};
@@ -60,10 +60,14 @@ fn openssl() -> Option<String> {
}
fn sign_script(dir: &Path, env: &[(&str, &str)]) -> Output {
sign_script_for(TAG, dir, env)
}
fn sign_script_for(tag: &str, dir: &Path, env: &[(&str, &str)]) -> Output {
let script = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../tools/ci/sign_release.sh");
let mut cmd = Command::new("bash");
cmd.arg(script)
.arg(TAG)
.arg(tag)
.arg(dir.join("horizon-linux-x86_64.tar.gz"))
.arg(dir.join("horizon-windows-x64.zip"))
.env_remove("RELEASE_SIGNING_KEY")
@@ -182,3 +186,70 @@ fn keygen_writes_the_secret_to_a_pipe_and_the_public_key_to_a_file() {
);
std::fs::remove_dir_all(dir).unwrap();
}
#[test]
fn a_nightly_is_signed_for_its_channel_and_for_its_version() {
if cfg!(windows) || openssl().is_none() {
eprintln!("skipped: tools/ci/sign_release.sh is tested on Linux (bash, OpenSSL 3)");
return;
}
const VERSION: &str = "nightly-2026-10-28-0c02067";
let dir = folder("nightly");
std::fs::remove_file(dir.join(SUMS)).unwrap();
let (key, secret) = SigningKey::generate().unwrap();
let out = sign_script_for(
"nightly",
&dir,
&[("RELEASE_SIGNING_KEY", &secret), ("ALSO_FOR", VERSION)],
);
assert!(
out.status.success(),
"{}",
String::from_utf8_lossy(&out.stderr)
);
let public = key.public_base64();
let check = |tag: &str, signature: &str| {
tool(
&[
"verify",
"--tag",
tag,
"--key",
&public,
"--signature",
signature,
],
&[&dir],
)
.status
.success()
};
// Launchers from before v2 check the channel's; current ones, the version's.
assert!(check("nightly", SIGNATURE));
assert!(check(VERSION, SIGNATURE_V2));
assert!(!check(VERSION, SIGNATURE));
assert!(!check("nightly", SIGNATURE_V2));
assert!(!check("nightly-2026-10-27-0c02067", SIGNATURE_V2));
// What a current launcher does with it.
let sums = std::fs::read(dir.join(SUMS)).unwrap();
let v2 = std::fs::read_to_string(dir.join(SIGNATURE_V2)).unwrap();
let digest = horizon_release_sign::nightly_digest(
VERSION,
"horizon-windows-x64.zip",
Some(&sums),
Some(&v2),
&[key.public()],
);
assert_eq!(
digest,
Ok(horizon_release_sign::sha256_hex(b"windows build"))
);
// A bad ALSO_FOR is refused before anything is signed.
let out = sign_script_for(
"nightly",
&dir,
&[("RELEASE_SIGNING_KEY", &secret), ("ALSO_FOR", "v0.2.81")],
);
assert!(!out.status.success());
std::fs::remove_dir_all(dir).unwrap();
}
+47 -16
View File
@@ -341,15 +341,18 @@ fn pick_for_assets(
}
};
let sums = attached(horizon_release_sign::SUMS)?;
let signature = attached(horizon_release_sign::SIGNATURE)?
.map(|bytes| String::from_utf8_lossy(&bytes).into_owned());
// A Nightly is signed for its channel, never for a tag, and installs under its date and commit.
let text = |bytes: Vec<u8>| String::from_utf8_lossy(&bytes).into_owned();
// A Nightly installs under its date and commit, which its title names (strictly: nothing signs
// GitHub's publication time), and its SHA256SUMS.v2.sig must sign the checksums for exactly that
// version, so an older Nightly can't be served as a newer one.
let (tag, sha256) = if horizon_release_sign::is_nightly(tag) {
let version = horizon_release_sign::nightly_version(
release["name"].as_str().unwrap_or_default(),
release["published_at"].as_str().unwrap_or_default(),
);
let title = release["name"].as_str().unwrap_or_default();
let version = horizon_release_sign::nightly_title_version(title).ok_or_else(|| {
format!("the Nightly's title {title:?} doesn't name its date and commit, so it can't be checked")
})?;
let signature = attached(horizon_release_sign::SIGNATURE_V2)?.map(text);
let sha256 = horizon_release_sign::nightly_digest(
&version,
name,
sums.as_deref(),
signature.as_deref(),
@@ -357,6 +360,7 @@ fn pick_for_assets(
)?;
(version, sha256)
} else {
let signature = attached(horizon_release_sign::SIGNATURE)?.map(text);
let sha256 = horizon_release_sign::signed_digest(
tag,
name,
@@ -684,6 +688,13 @@ pub fn command(dir: &Path, args: &[String]) -> Result<(), String> {
println!("Already on the newest release ({current}).");
return Ok(());
}
if newer(&current, &release.tag) {
// Asked for by --version: a rollback is allowed, never done without saying so.
println!(
"{} is older than {current}, which this server runs: installing it as a rollback.",
release.tag
);
}
println!("Downloading Horizon {} ({})...", release.tag, release.asset);
let archive = download(&install, &release)?;
(release.tag, archive, true)
@@ -967,36 +978,56 @@ mod tests {
}
#[test]
fn a_nightly_is_picked_with_its_channel_signature_and_named_by_its_build() {
fn a_nightly_is_picked_with_its_version_signature_and_named_by_its_build() {
use horizon_release_sign::{SigningKey, sha256_hex, sums_file};
let Some(first) = ASSETS.first() else { return };
let asset = |name: &str| json!({ "name": name, "browser_download_url": format!("https://example.invalid/{name}") });
let (key, _) = SigningKey::generate().unwrap();
let sums = sums_file(&[(first.to_string(), sha256_hex(b"server"))]);
let serving = |signed_for: &str| {
let (sums, signature) = (sums.clone(), key.sign(signed_for, sums.as_bytes()));
// SHA256SUMS.sig signed for `channel`, SHA256SUMS.v2.sig for `v2`.
let serving = |channel: &str, v2: &str| {
let sums = sums.clone();
let (one, two) = (
key.sign(channel, sums.as_bytes()),
key.sign(v2, sums.as_bytes()),
);
move |url: &str| -> Result<Vec<u8>, String> {
match url.rsplit('/').next() {
Some("SHA256SUMS") => Ok(sums.clone().into_bytes()),
Some("SHA256SUMS.sig") => Ok(signature.clone().into_bytes()),
Some("SHA256SUMS.sig") => Ok(one.clone().into_bytes()),
Some("SHA256SUMS.v2.sig") => Ok(two.clone().into_bytes()),
_ => Err("404".into()),
}
}
};
const TONIGHT: &str = "nightly-2026-10-28-0c02067";
let nightly = json!({
"tag_name": "nightly", "name": "Nightly 2026-10-28 · 0c02067",
"published_at": "2026-10-28T20:40:00Z",
"assets": [asset(first), asset("SHA256SUMS"), asset("SHA256SUMS.sig")],
"assets": [asset(first), asset("SHA256SUMS"), asset("SHA256SUMS.sig"), asset("SHA256SUMS.v2.sig")],
});
let picked = pick(&nightly, serving("nightly"), &[key.public()]).unwrap();
assert_eq!(picked.tag, "nightly-2026-10-28-0c02067");
let picked = pick(&nightly, serving("nightly", TONIGHT), &[key.public()]).unwrap();
assert_eq!(picked.tag, TONIGHT);
assert_eq!(picked.sha256, sha256_hex(b"server"));
// An older Nightly's files under tonight's title: refused.
let old = serving("nightly", "nightly-2026-10-21-aaaaaaa");
assert!(pick(&nightly, old, &[key.public()]).is_err());
// Only the channel's signature (a Nightly from before v2): refused.
let mut v1_only = nightly.clone();
v1_only["assets"] = json!([asset(first), asset("SHA256SUMS"), asset("SHA256SUMS.sig")]);
let err = pick(&v1_only, serving("nightly", TONIGHT), &[key.public()]).unwrap_err();
assert!(err.contains("SHA256SUMS.v2.sig"), "{err}");
// A title that doesn't name its date and commit: refused, never dated by `published_at`.
let mut untitled = nightly.clone();
untitled["name"] = json!("Nightly");
let err = pick(&untitled, serving("nightly", TONIGHT), &[key.public()]).unwrap_err();
assert!(err.contains("doesn't name"), "{err}");
// A release's signed list served as the Nightly: refused.
assert!(pick(&nightly, serving("v0.2.95"), &[key.public()]).is_err());
assert!(pick(&nightly, serving("v0.2.95", "v0.2.95"), &[key.public()]).is_err());
// A Nightly's signed list served as a release: refused.
let mut release = nightly.clone();
release["tag_name"] = json!("v0.2.95");
assert!(pick(&release, serving("nightly"), &[key.public()]).is_err());
assert!(pick(&release, serving(TONIGHT, TONIGHT), &[key.public()]).is_err());
}
#[test]
+18 -1
View File
@@ -66,6 +66,22 @@ and some are waiting for Ludovic:
a secret of GitHub's `release` environment, which only real releases from main can use. The job that signs runs
nothing from the repository but a short script calling OpenSSL, so no pull request can read the key by changing
the code that gets built. Nobody, Ludovic included, ever needs to see it.
- **Nightly signatures.** A Nightly carries two signatures over the same `SHA256SUMS`. `SHA256SUMS.sig` is signed
for the channel (`horizon release nightly`), for launchers and servers from before this change, which read only
that one. `SHA256SUMS.v2.sig` is signed for the Nightly's own version (`horizon release nightly-<date>-<commit>`),
which its release title names (`Nightly <date> · <commit>`). Current launchers, `horizon-server update` and
`install.sh` parse that title strictly, refuse a Nightly whose title doesn't parse, and install it only with a v2
signature for exactly that version. That way an older Nightly can't be served as tonight's: its signature names its own date. Installing
an older Nightly on purpose still works as a rollback, with a warning, and never happens as an automatic update.
**The changeover:** Nightlies published before this change have no `SHA256SUMS.v2.sig`, so they can't be installed
or picked with `--version` any more; they leave GitHub with the 7-day rotation. Until a v2 Nightly exists, a
launcher has nothing to update to, so the first Nightly is built right after this merges. A server can still go back
to a build it already has with `horizon-server rollback`, which checks nothing it hasn't already checked.
**When the old signature can go:** once every launcher and server still updating reads v2. That is, when the
telemetry live count shows no launcher (and the server update log no `horizon-server`) older than the first build
with this change, or at the latest 60 days after it shipped. Then drop `SHA256SUMS.sig` from nightly-build.yml's
publish step and the `--tag nightly` check before it, and remove `NIGHTLY` from horizon-release-sign. Releases (not
Nightlies) keep their single `SHA256SUMS.sig`, which is already signed for their tag.
- **The release machinery needs Ludovic.** The workflows, the release and signing tools, the update-checking code
and the installers are listed in `.github/CODEOWNERS`. Once main's protection requires code owners' reviews, a
change to any of them waits for Ludovic's approval. Everything else still merges as soon as its checks pass.
@@ -100,7 +116,8 @@ and some are waiting for Ludovic:
not a deliberate attack. The protection is review: only agents and maintainers push to this repository, and a
maintainer reads a fork's change before labelling it.
- **The first install** with `install.sh` checks the signature when OpenSSL 3 is installed: it verifies
`SHA256SUMS.sig` against the release key built into the script, then the archive against `SHA256SUMS`. With
`SHA256SUMS.sig` (a Nightly's `SHA256SUMS.v2.sig`, for its own version) against the release key built into the
script, then the archive against `SHA256SUMS`. With
an older OpenSSL, LibreSSL (what macOS ships) or none, it says so and checks only the SHA-256 GitHub
publishes. `install.ps1` still checks only that SHA-256. Every update after that checks the signature.
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Die Stigtersstel is joune.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "طقم المؤسسين أصبح لك.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Təsisçi dəsti artıq sizindir.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Нигеҙ һалыусылар йыйылмаһы — һеҙҙеке.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Набор заснавальнікаў цяпер ваш.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Основателският комплект е ваш.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Lakaet ar grouerien a zo deoc'h.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Osnivački set je vaš.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "El Conjunt del fundador és teu.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Zakladatelský set je váš.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Учредительсен пуххи — сирӗн.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Mae'r Set sylfaenydd yn eiddo i chi.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Stifter sæt er dit.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Das Gründer-Set gehört dir.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Το Ιδρυτικό σύνολο είναι δικό σου.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "La Fondinto-aro estas via.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "El Set fundador es tuyo.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Asutaja komplekt on sinu.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Sortzaile multzoa zurea da.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "مجموعه موسس مال شماست.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Perustaja-setti on sinun.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Sa iyo na ang Set ng founder.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Stovnara settið er títt.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Le Set fondateur est à vous.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "L'Insiemi di fondadôrs al è to.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "De Oprjochter set is fan dy.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Is leatsa an tSraith bunaitheoir.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "'S ann leatsa a tha an Seata stèidheadair.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "O Set fundador é teu.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Nou ka Hoʻonohonoho hoʻokumu.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "סט המייסד שלכם.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "फ़ाउंडर सेट अब आपका है।",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Osnivački set je vaš.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Az Alapító készlet a tiéd.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Հիմնադիր հավաքածուն ձերն է։",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Set pendiri kini milikmu.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Ntọala ntọala bụ nke gị.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Stofnandi settið er þitt.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "L'Insieme del fondatore è tuo.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "ファウンダーセットはあなたのものです。",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "დამფუძნებელი ნაკრები შენია.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Құрылтайшы жиынтығы енді сіздікі.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "ಸ್ಥಾಪಕ ಸೆಟ್ ಈಗ ನಿಮ್ಮದು.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "창립자 세트를 받았습니다.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Негиздөөчү топтому эми сиздики.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Conditor set tuum est.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "De Grënner Set gehéiert Iech.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "De Oprichter set is van dich.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "El Set fondatur l'è tò.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "ຊຸດຜູ້ກໍ່ຕັ້ງເປັນຂອງທ່ານແລ້ວ.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Steigėjų rinkinys jūsų.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Dibinātāja komplekts ir jūsu.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Основачкиот сет е ваш.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Үүсгэн байгуулагчийн багц таных боллоо.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Set pengasas kini milik anda.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Is-Sett tal-fundatur huwa tiegħek.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "De Oprichtersset is van jou.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Grunnleggersettet er ditt.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "L'Ensemble de fondators es vòstre.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Zestaw założyciela jest Twój.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "O Conjunto fundador é seu.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "O Conjunto de fundador é seu.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Setul fondator este al tău.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Набор основателя теперь ваш.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Төрүттээччи набора — эйиэнэ.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Ásaheaddji searvi lea du.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Zakladateľská súprava je vaša.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Ustanoviteljski set je vaš.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Aasaasaha dhigay waa kaaga.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Seti themelues është yti.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Оснивачки сет је ваш.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Grundaruppsättningen är din.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Zestow założycieli je twōj.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "நிறுவனர் தொகுப்பு இப்போது உங்களுடையது.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "ชุดผู้ก่อตั้งเป็นของคุณแล้ว",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Kurucu seti artık senin.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Нигез салучы җыелмасы — сезнеке.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Набір засновника тепер ваш.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "بانی سیٹ اب آپ کا ہے۔",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Ta'sischilar to'plami endi sizniki.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "El Set fondador el xe tuo.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Bộ sáng lập giờ là của bạn.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "דער גרינדער שטעלן איז דײַנער.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Oludasile ṣeto jẹ́ tìrẹ.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "创始者套装已归你所有。",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+3 -1
View File
@@ -1141,5 +1141,7 @@
"Sign in with `horizon-launcher account sign-in`.": "Sign in with `horizon-launcher account sign-in`.",
"The Founder Set is yours.": "Umsunguli usethiwe ungowakho.",
"{file} unpacks to more than {limit}: it isn't imported.": "{file} unpacks to more than {limit}: it isn't imported.",
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back."
"Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.": "Horizon's Vulkan renderer crashed while starting on this graphics card, so the game now uses {api}. Press Play to start it again. Video Settings > Graphics API switches back.",
"This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.": "This Nightly's title ({title}) doesn't name its date and commit as Horizon signs them, so it can't be checked: it was not installed.",
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it.": "{tag} is older than {newest}, which is installed: installing it as a rollback. The selection only moves to it when you pick it."
}
+80 -8
View File
@@ -1215,13 +1215,27 @@ pub fn install(release: &Release, progress: impl Fn(f32)) -> Result<(), String>
.to_string()
})?;
let sha256 = match &release.nightly {
// Signed for the Nightly channel, served under its own GitHub tag.
Some(published) => crate::signed::nightly_digest(
published,
asset,
&horizon_release_sign::trusted_keys(),
fetch_small,
)?,
// Signed for its own version (SHA256SUMS.v2.sig), which its title names and it installs as;
// served under its own GitHub tag. A title that doesn't parse strictly is refused: nothing
// signs GitHub's publication time.
Some(github_tag) => {
let version = horizon_release_sign::nightly_title_version(&release.name)
.filter(|v| *v == release.tag)
.ok_or_else(|| {
crate::i18n::trf(
"This Nightly's title ({title}) doesn't name its date and commit as Horizon \
signs them, so it can't be checked: it was not installed.",
&[("title", &format!("{:?}", release.name))],
)
})?;
crate::signed::nightly_digest(
github_tag,
&version,
asset,
&horizon_release_sign::trusted_keys(),
fetch_small,
)?
}
None if is_game_tag(tag) => signed_digest(tag, asset)?,
None => return Err(format!("{tag} is not a Horizon release.")),
};
@@ -3247,9 +3261,16 @@ pub fn install_tag(tag: &str, as_update: bool, progress: impl Fn(f32)) -> Result
return Err(format!("{} has no build for this platform.", release.tag));
}
let before = installed();
let downgrade = nightly_downgrade(release, &before);
if let Some(warning) = &downgrade {
eprintln!("{warning}");
}
install(release, progress)?;
let mut settings = Settings::load();
if !as_update || select_after_update(settings.selected.as_deref(), &before) {
// An older Nightly is a deliberate rollback: installed, but an update never moves the selection back.
let select = !as_update
|| (downgrade.is_none() && select_after_update(settings.selected.as_deref(), &before));
if select {
settings.selected = Some(release.tag.clone());
settings.save()?;
}
@@ -3260,6 +3281,24 @@ pub fn install_tag(tag: &str, as_update: bool, progress: impl Fn(f32)) -> Result
Ok(release.tag.clone())
}
/// A warning when `release` is a Nightly older than a Nightly already installed: a rollback, which is
/// allowed, but never what an update should do silently (an older build served as the current one
/// shows its own date, since that date is signed). None otherwise.
pub fn nightly_downgrade(release: &Release, installed: &[String]) -> Option<String> {
release.nightly.as_ref()?;
let newest = installed
.iter()
.filter(|v| crate::nightly::date_of(v).is_some())
.max_by(|a, b| compare_versions(a, b))?;
compare_versions(&release.tag, newest).is_lt().then(|| {
crate::i18n::trf(
"{tag} is older than {newest}, which is installed: installing it as a rollback. The selection \
only moves to it when you pick it.",
&[("tag", &release.tag), ("newest", newest)],
)
})
}
/// The launcher's own path, read once at start: after a self-update the running file is gone.
pub fn exe_path() -> &'static Path {
static EXE: std::sync::OnceLock<PathBuf> = std::sync::OnceLock::new();
@@ -5432,6 +5471,39 @@ pub fn {f}("
);
}
#[test]
fn an_older_nightly_installs_as_a_rollback_with_a_warning() {
let nightly = |tag: &str| Release {
tag: tag.into(),
name: String::new(),
body: String::new(),
date: String::new(),
time: String::new(),
asset: Some(("u".into(), 1)),
prerelease: false,
nightly: Some("nightly".into()),
};
let installed = [
"v0.2.81".to_owned(),
"nightly-2026-10-28-0c02067".to_owned(),
];
let warning =
nightly_downgrade(&nightly("nightly-2026-10-21-aaaaaaa"), &installed).unwrap();
assert!(
warning.contains("older than nightly-2026-10-28-0c02067"),
"{warning}"
);
assert!(nightly_downgrade(&nightly("nightly-2026-10-29-bbbbbbb"), &installed).is_none());
assert!(nightly_downgrade(&nightly("nightly-2026-10-28-0c02067"), &installed).is_none());
// No Nightly installed, or a release: nothing to warn about.
assert!(
nightly_downgrade(&nightly("nightly-2026-10-21-aaaaaaa"), &installed[..1]).is_none()
);
let mut release = nightly("v0.2.80");
release.nightly = None;
assert!(nightly_downgrade(&release, &installed).is_none());
}
#[test]
fn a_launcher_knows_which_line_it_was_released_on() {
// launcher.yml gives the tag; before it did, a release had only its `launcher-v` version.
+51 -15
View File
@@ -5,7 +5,7 @@
//! with a message saying why.
use crate::backend::REPO;
use horizon_release_sign::{PublicKey, SIGNATURE, SUMS};
use horizon_release_sign::{PublicKey, SIGNATURE, SIGNATURE_V2, SUMS};
/// Where a release's attached file downloads from (GitHub's fixed address for it).
pub fn asset_url(tag: &str, name: &str) -> String {
@@ -31,18 +31,27 @@ pub fn digest(
}
/// The signed SHA-256 of `asset` in the Nightly published under `tag` (`nightly`, or a dated
/// `nightly-<date>`): its checksums must be signed for the nightly channel
/// (`horizon_release_sign::nightly_digest`), whatever tag serves them.
/// `nightly-<date>`) that installs as `version` (`nightly-<date>-<commit>`, parsed strictly from its
/// title by `horizon_release_sign::nightly_title_version`): its SHA256SUMS.v2.sig must sign the
/// checksums for exactly that version, so an older Nightly can't be served as a newer one. The
/// channel's SHA256SUMS.sig is for launchers from before and is not read.
pub fn nightly_digest(
tag: &str,
version: &str,
asset: &str,
keys: &[PublicKey],
fetch: impl Fn(&str) -> Result<Option<Vec<u8>>, String>,
) -> Result<String, String> {
let sums = fetch(&asset_url(tag, SUMS))?;
let signature = fetch(&asset_url(tag, SIGNATURE))?
let signature = fetch(&asset_url(tag, SIGNATURE_V2))?
.map(|bytes| String::from_utf8_lossy(&bytes).into_owned());
horizon_release_sign::nightly_digest(asset, sums.as_deref(), signature.as_deref(), keys)
horizon_release_sign::nightly_digest(
version,
asset,
sums.as_deref(),
signature.as_deref(),
keys,
)
}
#[cfg(test)]
@@ -109,20 +118,28 @@ mod tests {
assert!(digest("v2099.01.01", "horizon.zip", &keys, offline).is_err());
}
/// The release channel never installs what was signed for the nightly channel, whatever tag it
/// is served under, and the nightly channel never installs a release's signed list.
/// The release channel never installs what was signed for a Nightly, whatever tag it is served
/// under; a Nightly installs only with its own version's signature (SHA256SUMS.v2.sig), never the
/// channel's, another Nightly's or a release's.
#[test]
fn the_release_channel_refuses_nightly_signatures() {
const VERSION: &str = "nightly-2026-10-28-0c02067";
let (key, _) = SigningKey::generate().unwrap();
let keys = [key.public()];
let sums = sums_file(&[("horizon.zip".into(), sha256_hex(b"game"))]);
let serving = |signed_for: &'static str| {
let signature = key.sign(signed_for, sums.as_bytes());
// Serves SHA256SUMS, SHA256SUMS.sig signed for `channel` and SHA256SUMS.v2.sig for `v2`.
let serving = |channel: &'static str, v2: &'static str| {
let (one, two) = (
key.sign(channel, sums.as_bytes()),
key.sign(v2, sums.as_bytes()),
);
let sums = sums.clone();
move |url: &str| -> Result<Option<Vec<u8>>, String> {
Ok(Some(
if url.ends_with(".sig") {
signature.clone()
if url.ends_with(SIGNATURE_V2) {
two.clone()
} else if url.ends_with(SIGNATURE) {
one.clone()
} else {
sums.clone()
}
@@ -130,19 +147,38 @@ mod tests {
))
}
};
let nightly = serving(horizon_release_sign::NIGHTLY);
let nightly = serving(horizon_release_sign::NIGHTLY, VERSION);
assert_eq!(
nightly_digest("nightly", "horizon.zip", &keys, &nightly),
nightly_digest("nightly", VERSION, "horizon.zip", &keys, &nightly),
Ok(sha256_hex(b"game"))
);
// Another version than the one signed (an older Nightly served as tonight's, or the reverse).
assert!(nightly_digest(
"nightly",
"nightly-2026-10-29-1111111",
"horizon.zip",
&keys,
&nightly
)
.is_err());
for tag in ["v0.2.81", "nightly", "nightly-2026-10-27"] {
assert!(
digest(tag, "horizon.zip", &keys, &nightly).is_err(),
"{tag}"
);
}
let release = serving("v0.2.81");
// Only the channel's signature (a Nightly from before v2): refused by a current launcher.
let old = |url: &str| -> Result<Option<Vec<u8>>, String> {
if url.ends_with(SIGNATURE_V2) {
Ok(None)
} else {
nightly(url)
}
};
let refused = nightly_digest("nightly", VERSION, "horizon.zip", &keys, old).unwrap_err();
assert!(refused.contains("SHA256SUMS.v2.sig"), "{refused}");
let release = serving("v0.2.81", "v0.2.81");
assert!(digest("v0.2.81", "horizon.zip", &keys, &release).is_ok());
assert!(nightly_digest("nightly", "horizon.zip", &keys, &release).is_err());
assert!(nightly_digest("nightly", VERSION, "horizon.zip", &keys, &release).is_err());
}
}
+15 -8
View File
@@ -74,11 +74,14 @@ else
[ -n "$TAG" ] || die "could not read the release's tag"
RAWTAG=$TAG
# A Nightly installs under its date and commit, as `horizon-server update` names it:
# "Nightly 2026-10-28 · 0c02067" is nightly-2026-10-28-0c02067.
# "Nightly 2026-10-28 · 0c02067" is nightly-2026-10-28-0c02067. Its signature is checked for exactly that
# version, so the title must name it (as horizon_release_sign::nightly_title_version reads it, strictly).
NAME=
case "$TAG" in
nightly|nightly-*)
NAME=$(printf '%s\n' "$JSON" | sed -n 's/^ "name": "Nightly \([0-9-]\{10\}\) · \([0-9a-f]\{1,40\}\)".*/nightly-\1-\2/p' | head -n 1)
[ -z "$NAME" ] || TAG=$NAME ;;
NAME=$(printf '%s\n' "$JSON" | sed -n 's/^ "name": "Nightly \([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\) · \([0-9a-f]\{7,40\}\)"[,}]*$/nightly-\1-\2/p' | head -n 1)
[ -n "$NAME" ] || die "this Nightly's title doesn't name its date and commit as Horizon signs them, so it can't be checked: not installed"
TAG=$NAME ;;
esac
# A release asset's download address, from its block in the release's JSON.
asset_url() {
@@ -100,23 +103,27 @@ else
[ -n "$URL" ] || die "release $TAG has none of $ASSETS"
# The signature (docs/release-flow.md, "Signed checksums"): SHA256SUMS.sig holds one base64 Ed25519 signature per
# line over "horizon release <tag>\n" + SHA256SUMS, a Nightly's for the channel "nightly" instead of its tag.
# line over "horizon release <tag>\n" + SHA256SUMS. A Nightly is checked against SHA256SUMS.v2.sig instead, signed
# for its own version (nightly-<date>-<commit>, from its title), never the channel's SHA256SUMS.sig: an older
# Nightly can't be passed off as the current one (docs/security.md, "Nightly signatures").
# It needs OpenSSL 3 (LibreSSL, which macOS ships, and OpenSSL 1.x cannot verify Ed25519 this way); without it
# the install says so and keeps the GitHub SHA-256 check below.
EXPECT=$DIGEST
case "$RAWTAG" in nightly|nightly-*) SIGTAG=nightly ;; *) SIGTAG=$RAWTAG ;; esac
if [ -n "$NAME" ]; then SIGTAG=$NAME; SIGFILE=SHA256SUMS.v2.sig; else SIGTAG=$RAWTAG; SIGFILE=SHA256SUMS.sig; fi
if ! command -v openssl >/dev/null; then
echo "Note: OpenSSL isn't installed, so the release signature was not checked; checking GitHub's SHA-256 only."
elif ! openssl version | grep -Eq '^OpenSSL ([3-9]|[1-9][0-9])\.'; then
echo "Note: $(openssl version | cut -d' ' -f1-2) can't check Ed25519 signatures (OpenSSL 3 is needed), so the release signature was not checked; checking GitHub's SHA-256 only."
else
SUMS_URL=$(asset_url SHA256SUMS)
SIG_URL=$(asset_url SHA256SUMS.sig)
if [ -z "$SUMS_URL" ] || [ -z "$SIG_URL" ]; then
SIG_URL=$(asset_url "$SIGFILE")
if [ -n "$NAME" ] && { [ -z "$SUMS_URL" ] || [ -z "$SIG_URL" ]; }; then
die "$TAG has no $SIGFILE (its signature for this exact build): it was published before Nightlies were signed for their own version, so it can't be checked. Install the current Nightly (--version latest) instead."
elif [ -z "$SUMS_URL" ] || [ -z "$SIG_URL" ]; then
echo "Note: release $TAG has no signed checksums (it was published before signing began), so the signature was not checked; checking GitHub's SHA-256 only."
else
curl -fsSL -o "$TMP/SHA256SUMS" "$SUMS_URL" || die "could not download SHA256SUMS"
curl -fsSL -o "$TMP/SHA256SUMS.sig" "$SIG_URL" || die "could not download SHA256SUMS.sig"
curl -fsSL -o "$TMP/SHA256SUMS.sig" "$SIG_URL" || die "could not download $SIGFILE"
{ printf 'horizon release %s\n' "$SIGTAG"; cat "$TMP/SHA256SUMS"; } > "$TMP/message"
SIGNED=
for KEY in $RELEASE_KEYS; do
+35 -13
View File
@@ -21,22 +21,29 @@ check() { # name, expected exit (0 or 1), output grep (may be empty), then the
else echo "FAIL $name (exit $rc, wanted $want, pattern '$pat')"; sed 's/^/ /' "$out"; fails=$((fails+1)); fi
}
# A fake release: an archive holding horizon-server, signed for TAG with a throwaway key.
make_release() { # dir tag
local d=$1 tag=$2
# A fake release: an archive holding horizon-server, signed for TAG with a throwaway key. A Nightly (TAG nightly)
# is also signed for its own version ALSO (nightly-<date>-<commit>) in SHA256SUMS.v2.sig, titled as
# nightly-build.yml titles it.
make_release() { # dir tag [also]
local d=$1 tag=$2 also=${3:-}
mkdir -p "$d/src/horizon-server-x" "$d/files"
printf '#!/bin/sh\necho fake\n' > "$d/src/horizon-server-x/horizon-server"; chmod +x "$d/src/horizon-server-x/horizon-server"
tar -czf "$d/files/horizon-server-linux-x86_64.tar.gz" -C "$d/src" horizon-server-x
EPHEMERAL=yes bash "$root/tools/ci/sign_release.sh" "$tag" "$d/files/horizon-server-linux-x86_64.tar.gz" > /dev/null
json "$d" "$tag" yes
ALSO_FOR=$also EPHEMERAL=yes bash "$root/tools/ci/sign_release.sh" "$tag" "$d/files/horizon-server-linux-x86_64.tar.gz" > /dev/null
json "$d" "$tag" yes "$(title "$tag" "$also")"
}
json() { # dir tag with-sums: GitHub's release JSON, as install.sh reads it
local d=$1 tag=$2 sums=$3 sha
title() { # tag also: the release's GitHub title
if [ -n "$2" ]; then printf 'Nightly %s · %s' "$(printf '%s' "$2" | cut -c9-18)" "$(printf '%s' "$2" | cut -c20-)"
else printf '%s' "$1"; fi
}
json() { # dir tag with-sums [title]: GitHub's release JSON, as install.sh reads it
local d=$1 tag=$2 sums=$3 name=${4:-$2} sha
sha=$(sha256sum "$d/files/horizon-server-linux-x86_64.tar.gz" | cut -d' ' -f1)
{
printf '{\n "tag_name": "%s",\n "name": "%s",\n "assets": [\n' "$tag" "$tag"
printf '{\n "tag_name": "%s",\n "name": "%s",\n "assets": [\n' "$tag" "$name"
printf ' {\n "name": "horizon-server-linux-x86_64.tar.gz",\n "digest": "sha256:%s",\n "browser_download_url": "https://dl.test/horizon-server-linux-x86_64.tar.gz"\n }' "$sha"
if [ "$sums" = yes ]; then for f in SHA256SUMS SHA256SUMS.sig; do
if [ "$sums" = yes ]; then for f in SHA256SUMS SHA256SUMS.sig SHA256SUMS.v2.sig; do
[ -f "$d/files/$f" ] || continue
printf ',\n {\n "name": "%s",\n "browser_download_url": "https://dl.test/%s"\n }' "$f" "$f"; done; fi
printf '\n ]\n}\n'
} > "$d/release.json"
@@ -81,11 +88,26 @@ edit() { # sed-expression file
mkdir -p "$W/home"
P=/usr/bin:/bin
# 1. Good signature, a Nightly (signed for the channel "nightly" under the tag nightly-2026-11-03).
d=$W/good; make_release "$d" nightly; with_key "$d"
edit 's/"tag_name": "nightly"/"tag_name": "nightly-2026-11-03"/' "$d/release.json"
run "$d" "$P"; verdict "good signature installs (nightly channel)" 0 "Release signature OK" "$d"
# 1. Good signature, a Nightly: SHA256SUMS.v2.sig signed for the version its title names.
NIGHTLY=nightly-2026-11-03-0c02067
d=$W/good; make_release "$d" nightly "$NIGHTLY"; with_key "$d"
run "$d" "$P"; verdict "good signature installs (Nightly, signed for its own version)" 0 "Release signature OK" "$d"
[ -x "$d/inst/current/horizon-server" ] || { echo "FAIL nothing installed"; fails=$((fails+1)); }
grep -q "Downloading Horizon $NIGHTLY " "$d/out" || { echo "FAIL not installed as $NIGHTLY"; fails=$((fails+1)); }
# 1b. A Nightly with only the channel's signature (published before v2): refused, never the channel's signature.
d=$W/channel; make_release "$d" nightly; with_key "$d"; json "$d" nightly yes "$(title nightly "$NIGHTLY")"
run "$d" "$P"; verdict "Nightly without SHA256SUMS.v2.sig refused" 1 "has no SHA256SUMS.v2.sig" "$d"
[ ! -e "$d/inst/current" ] || { echo "FAIL a Nightly without v2 was installed"; fails=$((fails+1)); }
# 1c. An older Nightly's files and signature retitled as a newer one: its v2 signature names the old version.
d=$W/rollback; make_release "$d" nightly nightly-2026-11-01-1111111; with_key "$d"
json "$d" nightly yes "$(title nightly "$NIGHTLY")"
run "$d" "$P"; verdict "older Nightly passed off as a newer one refused" 1 "signature doesn't match" "$d"
# 1d. A Nightly whose title doesn't name its date and commit: refused, not dated some other way.
d=$W/title; make_release "$d" nightly "$NIGHTLY"; with_key "$d"; json "$d" nightly yes "Nightly"
run "$d" "$P"; verdict "Nightly with an unreadable title refused" 1 "title doesn't name its date and commit" "$d"
# 2. Good signature, a normal tag.
d=$W/tag; make_release "$d" v1.2.3; with_key "$d"
+8 -3
View File
@@ -41,8 +41,11 @@ class OptionalReleaseAssetsTests(unittest.TestCase):
script_dir = root / "tools/ci"
script_dir.mkdir(parents=True)
shutil.copy(ROOT / "tools/ci/sign_release.sh", script_dir)
env = dict(os.environ, EPHEMERAL="yes", SHA="0123456789abcdef", DATE="2026-11-04",
SOURCE_TAG="nightly-test", RELEASE_SIGNING_KEY="", RELEASE_SIGNING_KEY_NEXT="")
# The steps' own env from nightly-build.yml: SHORT is the commit the title and
# SHA256SUMS.v2.sig name (ALSO_FOR, nightly-<date>-<short>).
env = dict(os.environ, EPHEMERAL="yes", SHA="0123456789abcdef", SHORT="0123456", DATE="2026-11-04",
ALSO_FOR="nightly-2026-11-04-0123456", SOURCE_TAG="nightly-test",
RELEASE_SIGNING_KEY="", RELEASE_SIGNING_KEY_NEXT="")
signed = subprocess.run(["bash", "-e", "-c", run_step("sign_release.sh nightly")],
cwd=root, env=env, text=True, capture_output=True)
self.assertEqual(signed.returncode, 0, signed.stderr)
@@ -50,6 +53,7 @@ class OptionalReleaseAssetsTests(unittest.TestCase):
(line.split() for line in (dist / "SHA256SUMS").read_text().splitlines())}
self.assertEqual(sums, {name: hashlib.sha256(name.encode()).hexdigest() for name in present})
self.assertTrue((dist / "SHA256SUMS.sig").stat().st_size)
self.assertTrue((dist / "SHA256SUMS.v2.sig").stat().st_size)
(dist / "smoke-test.json").write_text("{}")
(dist / "nightly-notes.md").write_text("test")
# Isolate GitHub and tag rotation; validate the exact attachment arguments
@@ -70,7 +74,8 @@ gh() {
cwd=root, env=env, text=True, capture_output=True)
self.assertEqual(published.returncode, 0, published.stderr)
files = {Path(name).name for name in (root / "published").read_text().splitlines()}
self.assertEqual(files, present | {"SHA256SUMS", "SHA256SUMS.sig", "smoke-test.json", "nightly-notes.md"})
self.assertEqual(files, present | {"SHA256SUMS", "SHA256SUMS.sig", "SHA256SUMS.v2.sig", "smoke-test.json",
"nightly-notes.md"})
for name in set(OPTIONAL) - present:
self.assertIn(f"::warning::{name} is missing", signed.stdout)
self.assertIn(f"::warning::{name} is missing", published.stdout)
+26 -7
View File
@@ -6,7 +6,11 @@
# but this file, which calls only the runner's sha256sum and OpenSSL; the publish job then checks the result
# with horizon-release-sign, as launchers do.
# EPHEMERAL=yes (dry runs) signs with a throwaway key instead and writes its public key to ephemeral.pub.
# ALSO_FOR=<tag> (Nightlies) signs the same SHA256SUMS a second time, for "horizon release <ALSO_FOR>\n", into
# SHA256SUMS.v2.sig, with the same key(s): the Nightly's own version (nightly-<date>-<commit>), which current
# launchers require, while SHA256SUMS.sig stays signed for the channel for launchers from before (docs/security.md).
# tools/ci/sign_release.sh v2026.10.19 dist/horizon-linux-x86_64.tar.gz dist/horizon-windows-x64.zip ...
# ALSO_FOR=nightly-2026-10-28-0c02067 tools/ci/sign_release.sh nightly dist/...
set -euo pipefail
tag=$1; shift
dir=$(dirname "$1")
@@ -21,16 +25,31 @@ for file in "$@"; do
[[ "$(dirname "$file")" == "$dir" ]] || { echo "$file: every file must be in $dir" >&2; exit 1; }
names+=("$(basename "$file")")
done
also=${ALSO_FOR:-}
if [[ -n "$also" && ! "$also" =~ ^nightly-[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9a-f]{7,40}$ ]]; then
echo "ALSO_FOR=$also: not a Nightly's nightly-<date>-<commit>" >&2; exit 1
fi
(cd "$dir" && "${sha[@]}" -- "${names[@]}") > "$dir/SHA256SUMS"
{ printf 'horizon release %s\n' "$tag"; cat "$dir/SHA256SUMS"; } > "$work/message"
rm -f "$dir/SHA256SUMS.sig" "$dir/ephemeral.pub"
if [[ -n "$also" ]]; then
{ printf 'horizon release %s\n' "$also"; cat "$dir/SHA256SUMS"; } > "$work/message.v2"
fi
rm -f "$dir/SHA256SUMS.sig" "$dir/SHA256SUMS.v2.sig" "$dir/ephemeral.pub"
sign_with() { # the key file in $1
"$openssl" pkeyutl -sign -rawin -inkey "$1" -keyform DER -in "$work/message" -out "$work/signature"
sign_one() { # key file, message file, signature file to append to
"$openssl" pkeyutl -sign -rawin -inkey "$1" -keyform DER -in "$2" -out "$work/signature"
# base64 of the 64 bytes on one line (GNU base64 wraps at 76 characters).
base64 < "$work/signature" | tr -d '\n' >> "$dir/SHA256SUMS.sig"
echo >> "$dir/SHA256SUMS.sig"
rm -f "$1" "$work/signature"
base64 < "$work/signature" | tr -d '\n' >> "$3"
echo >> "$3"
rm -f "$work/signature"
}
sign_with() { # the key file in $1: both messages, then the key goes
sign_one "$1" "$work/message" "$dir/SHA256SUMS.sig"
if [[ -n "$also" ]]; then
sign_one "$1" "$work/message.v2" "$dir/SHA256SUMS.v2.sig"
fi
rm -f "$1"
}
if [[ -n "${EPHEMERAL:-}" ]]; then
@@ -46,4 +65,4 @@ else
fi
done
fi
echo "$tag: SHA256SUMS lists ${#names[@]} files; $( [[ -f "$dir/SHA256SUMS.sig" ]] && echo "signed with $(wc -l < "$dir/SHA256SUMS.sig" | tr -d ' ') key(s)" || echo "no signing key, so unsigned")"
echo "$tag: SHA256SUMS lists ${#names[@]} files; $( [[ -f "$dir/SHA256SUMS.sig" ]] && echo "signed with $(wc -l < "$dir/SHA256SUMS.sig" | tr -d ' ') key(s)" || echo "no signing key, so unsigned")$( [[ -f "$dir/SHA256SUMS.v2.sig" ]] && echo ", and for $also in SHA256SUMS.v2.sig")"