mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-12 13:33:19 +00:00
Merge pull request #6802 from dotCooCoo/fix/plugin-manifest-commands-errors
Plug-ins: a wrongly shaped `commands` value gets an error every catalog translates
This commit is contained in:
@@ -736,10 +736,41 @@ fn input_names<'de, D: serde::Deserializer<'de>>(d: D) -> std::result::Result<Ve
|
||||
/// Reads the `commands` list one entry at a time from the manifest itself, so each command's
|
||||
/// `params` keep their declaration order and a repeated parameter is refused. A malformed entry
|
||||
/// is an error that names it (its id when the id comes before the fault, otherwise its place in
|
||||
/// the list), and a list is refused at its first entry past [`MAX_COMMANDS`].
|
||||
/// the list), and a list is refused at its first entry past [`MAX_COMMANDS`]. A `commands` value,
|
||||
/// an entry, an `id` or a `label` of the wrong type gets a fixed message of this function's own.
|
||||
fn ordered_commands<'de, D: serde::Deserializer<'de>>(d: D) -> std::result::Result<Vec<Command>, D::Error> {
|
||||
use serde::de::{Error as _, IgnoredAny, MapAccess, SeqAccess, Visitor};
|
||||
|
||||
/// A visitor's methods for a boolean, a number and a string: each is the error its type's
|
||||
/// `wrong()` gives.
|
||||
macro_rules! refuse_scalars {
|
||||
() => {
|
||||
fn visit_bool<E: serde::de::Error>(self, _: bool) -> std::result::Result<Self::Value, E> {
|
||||
Err(E::custom(self.wrong()))
|
||||
}
|
||||
fn visit_i64<E: serde::de::Error>(self, _: i64) -> std::result::Result<Self::Value, E> {
|
||||
Err(E::custom(self.wrong()))
|
||||
}
|
||||
fn visit_u64<E: serde::de::Error>(self, _: u64) -> std::result::Result<Self::Value, E> {
|
||||
Err(E::custom(self.wrong()))
|
||||
}
|
||||
fn visit_f64<E: serde::de::Error>(self, _: f64) -> std::result::Result<Self::Value, E> {
|
||||
Err(E::custom(self.wrong()))
|
||||
}
|
||||
fn visit_str<E: serde::de::Error>(self, _: &str) -> std::result::Result<Self::Value, E> {
|
||||
Err(E::custom(self.wrong()))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A string field of an entry: anything else is the error "`{key}` must be a string".
|
||||
fn string_field<'de, A: MapAccess<'de>>(map: &mut A, key: &str) -> std::result::Result<std::result::Result<String, String>, A::Error> {
|
||||
Ok(match map.next_value::<Value>()? {
|
||||
Value::String(s) => Ok(s),
|
||||
_ => Err(format!("`{key}` must be a string")),
|
||||
})
|
||||
}
|
||||
|
||||
/// A command's `params`, read in declaration order.
|
||||
struct Params(Vec<(String, Param)>);
|
||||
impl<'de> Deserialize<'de> for Params {
|
||||
@@ -750,6 +781,11 @@ fn ordered_commands<'de, D: serde::Deserializer<'de>>(d: D) -> std::result::Resu
|
||||
|
||||
/// The entry at place `.0` in the list.
|
||||
struct Entry(usize);
|
||||
impl Entry {
|
||||
fn wrong(&self) -> String {
|
||||
format!("command {} must be an object with an `id` and a `label`", command_name(self.0, ""))
|
||||
}
|
||||
}
|
||||
impl<'de> serde::de::DeserializeSeed<'de> for Entry {
|
||||
type Value = Command;
|
||||
fn deserialize<D: serde::Deserializer<'de>>(self, d: D) -> std::result::Result<Command, D::Error> {
|
||||
@@ -759,21 +795,29 @@ fn ordered_commands<'de, D: serde::Deserializer<'de>>(d: D) -> std::result::Resu
|
||||
impl<'de> Visitor<'de> for Entry {
|
||||
type Value = Command;
|
||||
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "command [{}] as {{id, label, params?}}", self.0)
|
||||
f.write_str(&self.wrong())
|
||||
}
|
||||
refuse_scalars!();
|
||||
fn visit_unit<E: serde::de::Error>(self) -> std::result::Result<Command, E> {
|
||||
Err(E::custom(self.wrong()))
|
||||
}
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, _: A) -> std::result::Result<Command, A::Error> {
|
||||
Err(A::Error::custom(self.wrong()))
|
||||
}
|
||||
fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> std::result::Result<Command, A::Error> {
|
||||
let (mut id, mut label, mut params) = (None::<String>, None::<String>, None::<Params>);
|
||||
let named = |id: &Option<String>, e: &dyn std::fmt::Display| {
|
||||
A::Error::custom(format!("command {}: {e}", command_name(self.0, id.as_deref().unwrap_or_default())))
|
||||
};
|
||||
while let Some(key) = map.next_key::<String>().map_err(|e| named(&id, &e))? {
|
||||
// A key and an ignored value can only fail as JSON syntax, which keeps serde's own error.
|
||||
while let Some(key) = map.next_key::<String>()? {
|
||||
let repeated = match key.as_str() {
|
||||
"id" if id.is_none() => {
|
||||
id = Some(map.next_value().map_err(|e| named(&id, &e))?);
|
||||
id = Some(string_field(&mut map, "id")?.map_err(|e| named(&id, &e))?);
|
||||
false
|
||||
}
|
||||
"label" if label.is_none() => {
|
||||
label = Some(map.next_value().map_err(|e| named(&id, &e))?);
|
||||
label = Some(string_field(&mut map, "label")?.map_err(|e| named(&id, &e))?);
|
||||
false
|
||||
}
|
||||
"params" if params.is_none() => {
|
||||
@@ -782,7 +826,7 @@ fn ordered_commands<'de, D: serde::Deserializer<'de>>(d: D) -> std::result::Resu
|
||||
}
|
||||
"id" | "label" | "params" => true,
|
||||
_ => {
|
||||
map.next_value::<IgnoredAny>().map_err(|e| named(&id, &e))?;
|
||||
map.next_value::<IgnoredAny>()?;
|
||||
false
|
||||
}
|
||||
};
|
||||
@@ -801,16 +845,22 @@ fn ordered_commands<'de, D: serde::Deserializer<'de>>(d: D) -> std::result::Resu
|
||||
}
|
||||
|
||||
struct List;
|
||||
impl List {
|
||||
fn wrong(&self) -> &'static str {
|
||||
"`commands` must be a list of commands, each with an `id` and a `label`"
|
||||
}
|
||||
}
|
||||
impl<'de> Visitor<'de> for List {
|
||||
type Value = Vec<Command>;
|
||||
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.write_str("`commands` as a list of {id, label, params?}")
|
||||
f.write_str(self.wrong())
|
||||
}
|
||||
refuse_scalars!();
|
||||
fn visit_unit<E: serde::de::Error>(self) -> std::result::Result<Self::Value, E> {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
fn visit_map<A: MapAccess<'de>>(self, _: A) -> std::result::Result<Self::Value, A::Error> {
|
||||
Err(A::Error::custom("`commands` must be a list of {id, label, params?}"))
|
||||
Err(A::Error::custom(self.wrong()))
|
||||
}
|
||||
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> std::result::Result<Self::Value, A::Error> {
|
||||
let mut out = Vec::new();
|
||||
@@ -1215,14 +1265,27 @@ mod tests {
|
||||
r#"{"id":"a","name":"x","kind":"filter","commands":[{"id":"x","label":"A","params":{"r":{"type":"bool"},"r":{"type":"int"}}}]}"#,
|
||||
"command `x`: parameter `r` is declared twice",
|
||||
),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","commands":[1]}"#, "command [0]"),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","commands":{"id":"x"}}"#, "must be a list"),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","commands":[1]}"#, "command [0] must be an object with an `id` and a `label`"),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","commands":[{"id":"x","label":"A"},null]}"#, "command [1] must be an object"),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","commands":[["x"]]}"#, "command [0] must be an object"),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","commands":[{"id":1,"label":"A"}]}"#, "command [0]: `id` must be a string"),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","commands":[{"id":"x","label":true}]}"#, "command `x`: `label` must be a string"),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","commands":[{"id":"x","id":"y","label":"A"}]}"#, "command `x`: duplicate field `id`"),
|
||||
(
|
||||
r#"{"id":"a","name":"x","kind":"filter","commands":{"id":"x"}}"#,
|
||||
"`commands` must be a list of commands, each with an `id` and a `label`",
|
||||
),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","commands":"x"}"#, "`commands` must be a list of commands"),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","commands":7}"#, "`commands` must be a list of commands"),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","commands":true}"#, "`commands` must be a list of commands"),
|
||||
(r#"{"id":"a","name":"x","kind":"exporter","extensions":["plt"],"commands":[{"id":"x","label":"A"}]}"#, "only a filter or a live effect"),
|
||||
(r#"{"id":"a","name":"x","kind":"filter","budget":"heavy","commands":[{"id":"x","label":"A"}]}"#, "heavy filter"),
|
||||
(too_many.as_str(), "at most 32 `commands`"),
|
||||
] {
|
||||
let e = Manifest::parse(bad.as_bytes()).unwrap_err().to_string();
|
||||
assert!(e.contains(says), "{bad}: {e}");
|
||||
// The message is the manifest reader's own, with serde's place in the manifest once.
|
||||
assert!(!e.contains("invalid type") && !e.contains("expected") && e.matches(" at line ").count() <= 1, "{bad}: {e}");
|
||||
}
|
||||
let long_id = format!(r#"{{"id":"a","name":"x","kind":"filter","commands":[{{"id":"{}","label":"A"}}]}}"#, "c".repeat(MAX_COMMAND_ID + 1));
|
||||
assert!(Manifest::parse(long_id.as_bytes()).is_err());
|
||||
|
||||
@@ -6188,6 +6188,12 @@ digits Malayalam Malaiàlam
|
||||
@msg command {name}: `label` must be 1-64 printable characters ordre {name}: `label` ha de tenir 1-64 caràcters imprimibles
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter ordre {name}: fes servir un id d’1-{MAX_COMMAND_ID} caràcters d’a-z 0-9 _ que comenci per una lletra
|
||||
@msg command {name}: {e} ordre {name}: {e}
|
||||
@msg manifest: {e} manifest: {e}
|
||||
@msg manifest: {e} at line {line} column {column} manifest: {e} (línia {line}, columna {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` ha de ser una llista d’ordres, cadascuna amb `id` i `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` l’ordre {name} ha de ser un objecte amb `id` i `label`
|
||||
@msg missing field `{key}` falta el camp `{key}`
|
||||
@msg duplicate field `{key}` el camp `{key}` està repetit
|
||||
@msg only a filter or a live effect declares `commands` només un filtre o un efecte dinàmic declara `commands`
|
||||
@msg “{name}” › {label}: {e} «{name}» › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed el mòdul no té el SHA-256 que indica `hash`: no s’ha instal·lat res
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6141,6 +6141,12 @@ axis Y Axis osa Y
|
||||
@msg command {name}: `label` must be 1-64 printable characters příkaz {name}: `label` musí mít 1-64 tisknutelných znaků
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter příkaz {name}: použijte id o 1-{MAX_COMMAND_ID} znacích z a-z 0-9 _, které začíná písmenem
|
||||
@msg command {name}: {e} příkaz {name}: {e}
|
||||
@msg manifest: {e} manifest: {e}
|
||||
@msg manifest: {e} at line {line} column {column} manifest: {e} (řádek {line}, sloupec {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` musí být seznam příkazů, každý s `id` a `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` příkaz {name} musí být objekt s `id` a `label`
|
||||
@msg missing field `{key}` chybí pole `{key}`
|
||||
@msg duplicate field `{key}` pole `{key}` je uvedeno dvakrát
|
||||
@msg only a filter or a live effect declares `commands` `commands` deklaruje jen filtr nebo živý efekt
|
||||
@msg “{name}” › {label}: {e} „{name}“ › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed modul nemá SHA-256 uvedený v `hash`: nic nebylo nainstalováno
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5732,6 +5732,12 @@ axis Y Axis Y-Achse
|
||||
@msg command {name}: `label` must be 1-64 printable characters Befehl {name}: `label` muss 1-64 druckbare Zeichen haben
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter Befehl {name}: Verwenden Sie eine ID aus 1-{MAX_COMMAND_ID} Zeichen aus a-z 0-9 _, die mit einem Buchstaben beginnt
|
||||
@msg command {name}: {e} Befehl {name}: {e}
|
||||
@msg manifest: {e} Manifest: {e}
|
||||
@msg manifest: {e} at line {line} column {column} Manifest: {e} (Zeile {line}, Spalte {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` muss eine Liste von Befehlen sein, jeder mit `id` und `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` der Befehl {name} muss ein Objekt mit `id` und `label` sein
|
||||
@msg missing field `{key}` fehlendes Feld `{key}`
|
||||
@msg duplicate field `{key}` doppeltes Feld `{key}`
|
||||
@msg only a filter or a live effect declares `commands` nur ein Filter oder ein Live-Effekt deklariert `commands`
|
||||
@msg “{name}” › {label}: {e} „{name}“ › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed das Modul hat nicht den SHA-256-Wert aus `hash`: Es wurde nichts installiert
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6092,6 +6092,12 @@ axis Y Axis Άξονας Y
|
||||
@msg command {name}: `label` must be 1-64 printable characters εντολή {name}: το `label` πρέπει να έχει 1-64 εκτυπώσιμους χαρακτήρες
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter εντολή {name}: χρησιμοποιήστε αναγνωριστικό 1-{MAX_COMMAND_ID} χαρακτήρων από a-z 0-9 _ που αρχίζει με γράμμα
|
||||
@msg command {name}: {e} εντολή {name}: {e}
|
||||
@msg manifest: {e} αρχείο δηλώσεων: {e}
|
||||
@msg manifest: {e} at line {line} column {column} αρχείο δηλώσεων: {e} (γραμμή {line}, στήλη {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` το `commands` πρέπει να είναι λίστα εντολών, καθεμία με `id` και `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` η εντολή {name} πρέπει να είναι αντικείμενο με `id` και `label`
|
||||
@msg missing field `{key}` λείπει το πεδίο `{key}`
|
||||
@msg duplicate field `{key}` το πεδίο `{key}` εμφανίζεται δύο φορές
|
||||
@msg only a filter or a live effect declares `commands` μόνο ένα φίλτρο ή ένα δυναμικό εφέ δηλώνει `commands`
|
||||
@msg “{name}” › {label}: {e} «{name}» › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed η λειτουργική μονάδα δεν έχει το SHA-256 που δίνει το `hash`: δεν εγκαταστάθηκε τίποτα
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -6083,6 +6083,12 @@ axis Y Axis Eje Y
|
||||
@msg command {name}: `label` must be 1-64 printable characters comando {name}: `label` debe tener 1-64 caracteres imprimibles
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter comando {name}: usa un id de 1-{MAX_COMMAND_ID} caracteres de a-z 0-9 _ que empiece por una letra
|
||||
@msg command {name}: {e} comando {name}: {e}
|
||||
@msg manifest: {e} manifiesto: {e}
|
||||
@msg manifest: {e} at line {line} column {column} manifiesto: {e} (línea {line}, columna {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` debe ser una lista de comandos, cada uno con `id` y `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` el comando {name} debe ser un objeto con `id` y `label`
|
||||
@msg missing field `{key}` falta el campo `{key}`
|
||||
@msg duplicate field `{key}` el campo `{key}` está repetido
|
||||
@msg only a filter or a live effect declares `commands` solo un filtro o un efecto interactivo declara `commands`
|
||||
@msg “{name}” › {label}: {e} “{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed el módulo no tiene el SHA-256 que indica `hash`: no se instaló nada
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6171,6 +6171,12 @@ axis Y Axis Y-akseli
|
||||
@msg command {name}: `label` must be 1-64 printable characters komento {name}: `label`-kentässä on oltava 1-64 tulostettavaa merkkiä
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter komento {name}: käytä 1-{MAX_COMMAND_ID} merkin tunnusta merkeistä a-z 0-9 _, joka alkaa kirjaimella
|
||||
@msg command {name}: {e} komento {name}: {e}
|
||||
@msg manifest: {e} manifesti: {e}
|
||||
@msg manifest: {e} at line {line} column {column} manifesti: {e} (rivi {line}, sarake {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands`-kohdan on oltava luettelo komennoista, joilla kullakin on `id` ja `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` komennon {name} on oltava objekti, jossa on `id` ja `label`
|
||||
@msg missing field `{key}` kenttä `{key}` puuttuu
|
||||
@msg duplicate field `{key}` kenttä `{key}` on kahdesti
|
||||
@msg only a filter or a live effect declares `commands` vain suodin tai live-tehoste määrittelee `commands`-kohdan
|
||||
@msg “{name}” › {label}: {e} ”{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed moduulilla ei ole `hash`-kentän SHA-256-arvoa: mitään ei asennettu
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6136,6 +6136,12 @@ axis Y Axis Axe Y
|
||||
@msg command {name}: `label` must be 1-64 printable characters commande {name} : `label` doit compter 1-64 caractères imprimables
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter commande {name} : utilisez un id de 1-{MAX_COMMAND_ID} caractères parmi a-z 0-9 _ commençant par une lettre
|
||||
@msg command {name}: {e} commande {name} : {e}
|
||||
@msg manifest: {e} manifeste : {e}
|
||||
@msg manifest: {e} at line {line} column {column} manifeste : {e} (ligne {line}, colonne {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` doit être une liste de commandes, chacune avec `id` et `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` la commande {name} doit être un objet avec `id` et `label`
|
||||
@msg missing field `{key}` champ `{key}` manquant
|
||||
@msg duplicate field `{key}` champ `{key}` en double
|
||||
@msg only a filter or a live effect declares `commands` seul un filtre ou un effet dynamique déclare `commands`
|
||||
@msg “{name}” › {label}: {e} « {name} » › {label} : {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed le module n’a pas le SHA-256 indiqué par `hash` : rien n’a été installé
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5437,6 +5437,11 @@ antiAlias Sharp शार्प
|
||||
@msg command {name}: `label` must be 1-64 printable characters कमांड {name}: `label` में 1-64 प्रिंट करने योग्य वर्ण होने चाहिए
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter कमांड {name}: a-z 0-9 _ के 1-{MAX_COMMAND_ID} वर्णों वाली ऐसी id इस्तेमाल करें जो अक्षर से शुरू हो
|
||||
@msg command {name}: {e} कमांड {name}: {e}
|
||||
@msg manifest: {e} at line {line} column {column} प्रकटन: {e} (लाइन {line}, कॉलम {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` कमांड की एक सूची होनी चाहिए, हर एक में `id` और `label` हो
|
||||
@msg command {name} must be an object with an `id` and a `label` कमांड {name} एक ऑब्जेक्ट होना चाहिए जिसमें `id` और `label` हों
|
||||
@msg missing field `{key}` फ़ील्ड `{key}` नहीं है
|
||||
@msg duplicate field `{key}` फ़ील्ड `{key}` दो बार है
|
||||
@msg only a filter or a live effect declares `commands` केवल फ़िल्टर या लाइव इफ़ेक्ट ही `commands` घोषित करता है
|
||||
@msg “{name}” › {label}: {e} “{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed मॉड्यूल का SHA-256 वह नहीं है जो `hash` बताता है: कुछ भी इंस्टॉल नहीं हुआ
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -6124,6 +6124,12 @@ axis Y Axis Y tengely
|
||||
@msg command {name}: `label` must be 1-64 printable characters {name} parancs: a `label` 1-64 nyomtatható karakter legyen
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter {name} parancs: használj 1-{MAX_COMMAND_ID} karakteres, a-z 0-9 _ karakterekből álló, betűvel kezdődő azonosítót
|
||||
@msg command {name}: {e} {name} parancs: {e}
|
||||
@msg manifest: {e} leíró: {e}
|
||||
@msg manifest: {e} at line {line} column {column} leíró: {e} ({line}. sor, {column}. oszlop)
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands`: parancsok listája kell, mindegyikben `id` és `label` értékkel
|
||||
@msg command {name} must be an object with an `id` and a `label` a(z) {name} parancs csak `id` és `label` mezőt tartalmazó objektum lehet
|
||||
@msg missing field `{key}` hiányzó mező: `{key}`
|
||||
@msg duplicate field `{key}` ismétlődő mező: `{key}`
|
||||
@msg only a filter or a live effect declares `commands` `commands` értéket csak szűrő vagy élő effektus deklarálhat
|
||||
@msg “{name}” › {label}: {e} „{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed a modul SHA-256 értéke nem az, amit a `hash` megad: semmi sem lett telepítve
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5766,6 +5766,12 @@ axis Y Axis Asse Y
|
||||
@msg command {name}: `label` must be 1-64 printable characters comando {name}: `label` deve avere 1-64 caratteri stampabili
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter comando {name}: usa un id di 1-{MAX_COMMAND_ID} caratteri tra a-z 0-9 _ che inizi con una lettera
|
||||
@msg command {name}: {e} comando {name}: {e}
|
||||
@msg manifest: {e} manifest: {e}
|
||||
@msg manifest: {e} at line {line} column {column} manifest: {e} (riga {line}, colonna {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` deve essere un elenco di comandi, ciascuno con `id` e `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` il comando {name} deve essere un oggetto con `id` e `label`
|
||||
@msg missing field `{key}` campo `{key}` mancante
|
||||
@msg duplicate field `{key}` campo `{key}` duplicato
|
||||
@msg only a filter or a live effect declares `commands` solo un filtro o un effetto dinamico dichiara `commands`
|
||||
@msg “{name}” › {label}: {e} “{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed il modulo non ha lo SHA-256 indicato da `hash`: non è stato installato nulla
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5831,6 +5831,12 @@ axis Y Axis Y 軸
|
||||
@msg command {name}: `label` must be 1-64 printable characters コマンド {name}: `label` は印刷可能な 1-64 文字にしてください
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter コマンド {name}: a-z 0-9 _ からなり英字で始まる 1-{MAX_COMMAND_ID} 文字の ID を使用してください
|
||||
@msg command {name}: {e} コマンド {name}: {e}
|
||||
@msg manifest: {e} マニフェスト: {e}
|
||||
@msg manifest: {e} at line {line} column {column} マニフェスト: {e} ({line} 行目、{column} 列目)
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` は、それぞれ `id` と `label` を持つコマンドのリストにしてください
|
||||
@msg command {name} must be an object with an `id` and a `label` コマンド {name} は `id` と `label` を持つオブジェクトにしてください
|
||||
@msg missing field `{key}` フィールド `{key}` がありません
|
||||
@msg duplicate field `{key}` フィールド `{key}` が重複しています
|
||||
@msg only a filter or a live effect declares `commands` `commands` を宣言できるのはフィルターかライブ効果だけです
|
||||
@msg “{name}” › {label}: {e} 「{name}」 › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed モジュールの SHA-256 が `hash` の値と一致しません。何もインストールされませんでした
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6092,6 +6092,12 @@ axis Y Axis Y ღერძი
|
||||
@msg command {name}: `label` must be 1-64 printable characters ბრძანება {name}: `label` უნდა შედგებოდეს 1-64 დასაბეჭდი სიმბოლოსგან
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter ბრძანება {name}: გამოიყენეთ 1-{MAX_COMMAND_ID} სიმბოლოიანი id a-z 0-9 _ სიმბოლოებიდან, რომელიც ასოთი იწყება
|
||||
@msg command {name}: {e} ბრძანება {name}: {e}
|
||||
@msg manifest: {e} მანიფესტი: {e}
|
||||
@msg manifest: {e} at line {line} column {column} მანიფესტი: {e} (სტრიქონი {line}, სვეტი {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` უნდა იყოს ბრძანებების სია, თითოეული `id`-ით და `label`-ით
|
||||
@msg command {name} must be an object with an `id` and a `label` ბრძანება {name} უნდა იყოს ობიექტი `id`-ით და `label`-ით
|
||||
@msg missing field `{key}` აკლია ველი `{key}`
|
||||
@msg duplicate field `{key}` ველი `{key}` ორჯერაა
|
||||
@msg only a filter or a live effect declares `commands` `commands`-ს მხოლოდ ფილტრი ან ცოცხალი ეფექტი აცხადებს
|
||||
@msg “{name}” › {label}: {e} „{name}“ › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed მოდულს არ აქვს `hash`-ში მითითებული SHA-256: არაფერი დაყენებულა
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -5727,6 +5727,12 @@ axis Y Axis Y축
|
||||
@msg command {name}: `label` must be 1-64 printable characters 명령 {name}: `label`은 인쇄 가능한 문자 1-64자여야 합니다
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter 명령 {name}: a-z 0-9 _로 이루어지고 문자로 시작하는 1-{MAX_COMMAND_ID}자 ID를 사용하세요
|
||||
@msg command {name}: {e} 명령 {name}: {e}
|
||||
@msg manifest: {e} 매니페스트: {e}
|
||||
@msg manifest: {e} at line {line} column {column} 매니페스트: {e} ({line}행 {column}열)
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands`는 각각 `id`와 `label`이 있는 명령 목록이어야 합니다
|
||||
@msg command {name} must be an object with an `id` and a `label` 명령 {name}은(는) `id`와 `label`이 있는 객체여야 합니다
|
||||
@msg missing field `{key}` `{key}` 필드가 없습니다
|
||||
@msg duplicate field `{key}` `{key}` 필드가 중복되었습니다
|
||||
@msg only a filter or a live effect declares `commands` 필터나 라이브 효과만 `commands`를 선언합니다
|
||||
@msg “{name}” › {label}: {e} “{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed 모듈의 SHA-256이 `hash`에 지정된 값과 다릅니다. 아무것도 설치되지 않았습니다
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5995,6 +5995,12 @@ axis Y Axis Oś Y
|
||||
@msg command {name}: `label` must be 1-64 printable characters polecenie {name}: `label` musi mieć 1-64 drukowalnych znaków
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter polecenie {name}: użyj id z 1-{MAX_COMMAND_ID} znaków spośród a-z 0-9 _, zaczynającego się od litery
|
||||
@msg command {name}: {e} polecenie {name}: {e}
|
||||
@msg manifest: {e} manifest: {e}
|
||||
@msg manifest: {e} at line {line} column {column} manifest: {e} (wiersz {line}, kolumna {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` musi być listą poleceń, każde z `id` i `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` polecenie {name} musi być obiektem z `id` i `label`
|
||||
@msg missing field `{key}` brak pola `{key}`
|
||||
@msg duplicate field `{key}` zduplikowane pole `{key}`
|
||||
@msg only a filter or a live effect declares `commands` `commands` deklaruje tylko filtr lub efekt na żywo
|
||||
@msg “{name}” › {label}: {e} „{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed moduł nie ma skrótu SHA-256 podanego w `hash`: nic nie zainstalowano
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -6056,6 +6056,12 @@ axis Y Axis Eixo Y
|
||||
@msg command {name}: `label` must be 1-64 printable characters comando {name}: `label` deve ter 1-64 caracteres imprimíveis
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter comando {name}: use um id de 1-{MAX_COMMAND_ID} caracteres de a-z 0-9 _ que comece com uma letra
|
||||
@msg command {name}: {e} comando {name}: {e}
|
||||
@msg manifest: {e} manifesto: {e}
|
||||
@msg manifest: {e} at line {line} column {column} manifesto: {e} (linha {line}, coluna {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` deve ser uma lista de comandos, cada um com `id` e `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` o comando {name} deve ser um objeto com `id` e `label`
|
||||
@msg missing field `{key}` falta o campo `{key}`
|
||||
@msg duplicate field `{key}` campo `{key}` duplicado
|
||||
@msg only a filter or a live effect declares `commands` só um filtro ou um efeito dinâmico declara `commands`
|
||||
@msg “{name}” › {label}: {e} “{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed o módulo não tem o SHA-256 indicado em `hash`: nada foi instalado
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -5752,6 +5752,12 @@ axis Y Axis Ось Y
|
||||
@msg command {name}: `label` must be 1-64 printable characters команда {name}: `label` должен содержать 1-64 печатаемых символа
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter команда {name}: используйте id из 1-{MAX_COMMAND_ID} символов a-z 0-9 _, начинающийся с буквы
|
||||
@msg command {name}: {e} команда {name}: {e}
|
||||
@msg manifest: {e} манифест: {e}
|
||||
@msg manifest: {e} at line {line} column {column} манифест: {e} (строка {line}, столбец {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` должно быть списком команд, у каждой из которых есть `id` и `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` команда {name} должна быть объектом с `id` и `label`
|
||||
@msg missing field `{key}` нет поля `{key}`
|
||||
@msg duplicate field `{key}` поле `{key}` указано дважды
|
||||
@msg only a filter or a live effect declares `commands` `commands` объявляет только фильтр или динамический эффект
|
||||
@msg “{name}” › {label}: {e} «{name}» › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed у модуля не тот SHA-256, что указан в `hash`: ничего не установлено
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -6159,6 +6159,11 @@ axis Y Axis Y-axel
|
||||
@msg command {name}: `label` must be 1-64 printable characters kommando {name}: `label` måste ha 1-64 utskrivbara tecken
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter kommando {name}: använd ett id med 1-{MAX_COMMAND_ID} tecken av a-z 0-9 _ som börjar med en bokstav
|
||||
@msg command {name}: {e} kommando {name}: {e}
|
||||
@msg manifest: {e} at line {line} column {column} manifest: {e} (rad {line}, kolumn {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` måste vara en lista med kommandon, vart och ett med `id` och `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` kommandot {name} måste vara ett objekt med `id` och `label`
|
||||
@msg missing field `{key}` fältet `{key}` saknas
|
||||
@msg duplicate field `{key}` fältet `{key}` förekommer två gånger
|
||||
@msg only a filter or a live effect declares `commands` bara ett filter eller en live-effekt deklarerar `commands`
|
||||
@msg “{name}” › {label}: {e} ”{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed modulen har inte den SHA-256 som `hash` anger: ingenting installerades
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -2027,6 +2027,38 @@ fn plugin_limit_errors_are_translated() {
|
||||
}
|
||||
}
|
||||
|
||||
/// A manifest whose `commands` value has the wrong shape is refused with an error that every
|
||||
/// language of [`COMPLETE_MESSAGES`] translates whole, the command's name and the place in the
|
||||
/// manifest included.
|
||||
#[test]
|
||||
fn wrongly_shaped_plugin_commands_errors_are_translated() {
|
||||
let many: Vec<String> = (0..=32).map(|i| format!(r#"{{"id":"c{i}","label":"C"}}"#)).collect();
|
||||
let commands = [
|
||||
r#"{"id":"x"}"#.to_string(),
|
||||
r#""x""#.to_string(),
|
||||
"[1]".to_string(),
|
||||
r#"[{"id":1,"label":"A"}]"#.to_string(),
|
||||
r#"[{"id":"x","label":true}]"#.to_string(),
|
||||
r#"[{"label":"B"}]"#.to_string(),
|
||||
r#"[{"id":"x"}]"#.to_string(),
|
||||
r#"[{"id":"x","id":"y","label":"A"}]"#.to_string(),
|
||||
format!("[{}]", many.join(",")),
|
||||
];
|
||||
let english = ["must", "list", "missing", "field", "duplicate", "object", "line", "column", "each", "with", "invalid", "expected"];
|
||||
for value in &commands {
|
||||
let manifest = format!(r#"{{"id":"a","name":"x","kind":"filter","commands":{value}}}"#);
|
||||
let e = vectorcraft_plugins::manifest::Manifest::parse(manifest.as_bytes()).unwrap_err().to_string();
|
||||
let numbers: Vec<&str> = e.split(|c: char| !c.is_ascii_digit()).filter(|n| !n.is_empty()).collect();
|
||||
for code in COMPLETE_MESSAGES {
|
||||
let shown = message(Lang::from_code(code).expect("registered"), &e);
|
||||
// Backticked names stay in English; the words around them are translated.
|
||||
let words: String = shown.split('`').step_by(2).collect();
|
||||
assert!(words.split(|c: char| !c.is_alphabetic()).all(|w| !english.contains(&w)), "{code}: {e} -> {shown}");
|
||||
assert!(numbers.iter().all(|n| shown.contains(n)), "{code}: {e} -> {shown}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The warnings of an Image Trace with keepColors, which the status bar shows and the scan above
|
||||
/// doesn't read, are translated in each language of [`COMPLETE_MESSAGES`], with the colors kept.
|
||||
#[test]
|
||||
|
||||
@@ -6097,6 +6097,12 @@ axis Y Axis Y ekseni
|
||||
@msg command {name}: `label` must be 1-64 printable characters {name} komutu: `label` 1-64 yazdırılabilir karakter olmalıdır
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter {name} komutu: a-z 0-9 _ karakterlerinden oluşan ve harfle başlayan 1-{MAX_COMMAND_ID} karakterlik bir kimlik kullanın
|
||||
@msg command {name}: {e} {name} komutu: {e}
|
||||
@msg manifest: {e} bildirim: {e}
|
||||
@msg manifest: {e} at line {line} column {column} bildirim: {e} (satır {line}, sütun {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands`, her biri `id` ve `label` içeren bir komut listesi olmalıdır
|
||||
@msg command {name} must be an object with an `id` and a `label` {name} komutu `id` ve `label` içeren bir nesne olmalıdır
|
||||
@msg missing field `{key}` `{key}` alanı eksik
|
||||
@msg duplicate field `{key}` `{key}` alanı yinelenmiş
|
||||
@msg only a filter or a live effect declares `commands` `commands` yalnızca bir filtre veya canlı efekt tarafından bildirilir
|
||||
@msg “{name}” › {label}: {e} “{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed modül `hash` içinde verilen SHA-256 değerine sahip değil: hiçbir şey yüklenmedi
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -5746,6 +5746,12 @@ axis Y Axis Вісь Y
|
||||
@msg command {name}: `label` must be 1-64 printable characters команда {name}: `label` має містити 1-64 друковані символи
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter команда {name}: використайте id з 1-{MAX_COMMAND_ID} символів a-z 0-9 _, що починається з літери
|
||||
@msg command {name}: {e} команда {name}: {e}
|
||||
@msg manifest: {e} маніфест: {e}
|
||||
@msg manifest: {e} at line {line} column {column} маніфест: {e} (рядок {line}, стовпець {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` має бути списком команд, кожна з `id` і `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` команда {name} має бути об'єктом з `id` і `label`
|
||||
@msg missing field `{key}` немає поля `{key}`
|
||||
@msg duplicate field `{key}` поле `{key}` вказано двічі
|
||||
@msg only a filter or a live effect declares `commands` `commands` оголошує лише фільтр або динамічний ефект
|
||||
@msg “{name}” › {label}: {e} «{name}» › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed модуль має не той SHA-256, що вказаний у `hash`: нічого не встановлено
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 182 and column 5.
|
@@ -5747,6 +5747,12 @@ axis Y Axis Trục Y
|
||||
@msg command {name}: `label` must be 1-64 printable characters lệnh {name}: `label` phải có 1-64 ký tự in được
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter lệnh {name}: hãy dùng id gồm 1-{MAX_COMMAND_ID} ký tự từ a-z 0-9 _ và bắt đầu bằng một chữ cái
|
||||
@msg command {name}: {e} lệnh {name}: {e}
|
||||
@msg manifest: {e} manifest: {e}
|
||||
@msg manifest: {e} at line {line} column {column} manifest: {e} (dòng {line}, cột {column})
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` phải là một danh sách lệnh, mỗi lệnh có `id` và `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` lệnh {name} phải là một đối tượng có `id` và `label`
|
||||
@msg missing field `{key}` thiếu trường `{key}`
|
||||
@msg duplicate field `{key}` trường `{key}` bị lặp
|
||||
@msg only a filter or a live effect declares `commands` chỉ bộ lọc hoặc hiệu ứng trực tiếp mới khai báo `commands`
|
||||
@msg “{name}” › {label}: {e} “{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed mô-đun không có SHA-256 mà `hash` cho biết: không có gì được cài đặt
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 204 and column 5.
|
@@ -5979,6 +5979,12 @@ axis Y Axis Y 轴
|
||||
@msg command {name}: `label` must be 1-64 printable characters 命令 {name}:`label` 必须是 1-64 个可打印字符
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter 命令 {name}:请使用由 a-z 0-9 _ 组成、以字母开头的 1-{MAX_COMMAND_ID} 个字符的 ID
|
||||
@msg command {name}: {e} 命令 {name}:{e}
|
||||
@msg manifest: {e} 清单:{e}
|
||||
@msg manifest: {e} at line {line} column {column} 清单:{e}(第 {line} 行,第 {column} 列)
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` 必须是命令列表,每个命令都有 `id` 和 `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` 命令 {name} 必须是包含 `id` 和 `label` 的对象
|
||||
@msg missing field `{key}` 缺少字段 `{key}`
|
||||
@msg duplicate field `{key}` 字段 `{key}` 重复
|
||||
@msg only a filter or a live effect declares `commands` 只有滤镜或实时效果才能声明 `commands`
|
||||
@msg “{name}” › {label}: {e} “{name}” › {label}:{e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed 模块的 SHA-256 与 `hash` 给出的不符:未安装任何内容
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5784,6 +5784,12 @@ axis Y Axis Y 軸
|
||||
@msg command {name}: `label` must be 1-64 printable characters 指令 {name}:`label` 必須是 1-64 個可列印字元
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter 指令 {name}:請使用由 a-z 0-9 _ 組成、以字母開頭的 1-{MAX_COMMAND_ID} 個字元的 ID
|
||||
@msg command {name}: {e} 指令 {name}:{e}
|
||||
@msg manifest: {e} 資訊清單:{e}
|
||||
@msg manifest: {e} at line {line} column {column} 資訊清單:{e}(第 {line} 行,第 {column} 欄)
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` 必須是指令清單,每個指令都有 `id` 和 `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` 指令 {name} 必須是包含 `id` 和 `label` 的物件
|
||||
@msg missing field `{key}` 找不到欄位 `{key}`
|
||||
@msg duplicate field `{key}` 欄位 `{key}` 重複
|
||||
@msg only a filter or a live effect declares `commands` 只有濾鏡或即時效果才能宣告 `commands`
|
||||
@msg “{name}” › {label}: {e} 「{name}」 › {label}:{e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed 模組的 SHA-256 與 `hash` 提供的不符:未安裝任何內容
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
Reference in New Issue
Block a user