diff options
-rw-r--r-- | example-config.dhall | 3 | ||||
-rw-r--r-- | site/examples/encrypted.json | bin | 641 -> 652 bytes | |||
-rw-r--r-- | site/examples/example.json | 2 | ||||
-rw-r--r-- | site/i18n.js | 67 | ||||
-rw-r--r-- | site/index.html | 31 | ||||
-rw-r--r-- | site/thanks.html | 2 | ||||
-rw-r--r-- | utils/src/main.rs | 13 |
7 files changed, 99 insertions, 19 deletions
diff --git a/example-config.dhall b/example-config.dhall index 0b5d5ae..ae12897 100644 --- a/example-config.dhall +++ b/example-config.dhall @@ -1,6 +1,7 @@ { title = "Test Survey" , description = "This is a test survey." -, pubkey = Some "age1te673wg4decpplhwrtw2x8atglrn59t87q0tllx7n7uhnr7qrg0ss6f36g" +, lang = Lang.en +, pubkey = Some "age1f380w6eaeuydey65mmu88h4kqv50dda96pxlgkal78sufpnngypqnetmuu" , questions = [ { question = "first question", name = "question1", space = Answers.YesOrNo } , { question = "second question" diff --git a/site/examples/encrypted.json b/site/examples/encrypted.json Binary files differindex 3eac1c5..2e24d13 100644 --- a/site/examples/encrypted.json +++ b/site/examples/encrypted.json diff --git a/site/examples/example.json b/site/examples/example.json index 2a6c2f9..fcd09d8 100644 --- a/site/examples/example.json +++ b/site/examples/example.json @@ -1 +1 @@ -{"title":"Test Survey","description":"This is a test survey.","questions":[{"question":"first question","name":"question1","space":"YesOrNo"},{"question":"second question","name":"question2","space":{"Freeform":"test"}},{"question":"third question","name":"question3","space":{"Multiple":["first possible answer","second possible answer","third possible answer"]}}],"pubkey":"age1f380w6eaeuydey65mmu88h4kqv50dda96pxlgkal78sufpnngypqnetmuu"} +{"title":"Test Survey","description":"This is a test survey.","questions":[{"question":"first question","name":"question1","space":"YesOrNo"},{"question":"second question","name":"question2","space":{"Freeform":"test"}},{"question":"third question","name":"question3","space":{"Multiple":["first possible answer","second possible answer","third possible answer"]}}],"pubkey":"age1f380w6eaeuydey65mmu88h4kqv50dda96pxlgkal78sufpnngypqnetmuu","lang":"en"}
\ No newline at end of file diff --git a/site/i18n.js b/site/i18n.js new file mode 100644 index 0000000..38ffe7b --- /dev/null +++ b/site/i18n.js @@ -0,0 +1,67 @@ + + + +let langs = { + en : { + // error message in case the survey url was obviously invalid (currently only the case if none was given) + "Error: nothing here": "There's nothing here. Maybe try appending something after the url?\n\nAlternatively, check to see if you copied the whole url.", + // error message in case the http request on the survey url returned a status code that wasn't 200 + "Error: survey doesn't exist": "Could not load this survey; are you sure that it exists?", + // error message in case the survey url was loaded, but had some obviously invalid format (i.e. neither json nor age encryption) + "Error: unknown format": "Could not load this survey; it appears to be in a wrong or unknown format.", + // text fragment in error messages, after which the survey url will be printed + "attempted path:": "Attempted path:", + // prompt for a passphrase + "please enter passphrase": "please enter a passphrase to access the survey:", + // error message in case decryption failed + "passphrase incorrect": "passphrase was incorrect!", + // document title for the decryption dialog + "Enter Passphrase": "Enter Passphrase", + // header of the decryption dialog + "Passphrase": "Passphrase", + // the text on the "decrypt" button + "decrypt": "decrypt", + // the text on the "submit" button + "submit": "submit", + // error message in case the given answers were invalid + "Error: answers invalid":"Cannot submit: not all required questions were filled in!", + // error message in case the post request failed entirely (i.e. printed if the .catch-clause of the fetch() function is reached) + "Error: could not post":"Error: The http POST request did not succeed.", + // error message in case the post request returned some other status code than 200; its status code and message will be appended in the next line after the text given here + "Error: post returned error":"Error: The http POST request returned an error code:" + }, + de : { + "Error: nothing here": "Hier ist nichts. Evtl. hilft es, etwas hinten an die url dranzuhängen?\n\nAnsonsten: bist du dir sicher, dass du den ganzen Link hierher kopiert hast?", + "Error: survey doesn't exist": "Diese Umfrage konnte nicht geladen werden. Bist du sicher, dass sie existiert?", + "Error: unknown format": "Diese Umfrage scheint ein unbekanntes Format zu haben und konnte nicht angezeigt werden", + "attempted path:": "Abgerufener Pfad:", + "please enter passphrase": "Bitte gebe eine Passphrase ein, um die Umfrage zu entschlüsseln", + "passphrase incorrect": "Passphrase war nicht korrekt!", + "Passphrase": "Passphrase", + "decrypt":"entschlüsseln", + "submit":"absenden", + "Enter Passphrase": "Passphrase eingeben", + "Error: answers invalid":"Einige verpflichtenden Antworten fehlen!", + "Error: could not post":"Fehler: Die http POST Anfrage schlug fehl.", + "Error: post returned error":"Fehler: Die http POST Anfragen schlug fehl und gab einen Fehlercode zurück:" + } +} + +// we use english by default until something else is set +let locale = "en"; + +// the main translation function. if no fitting translation +// is found, it returns the key as a fallback value +// (therefore, keys should themselves be understandable texts) +export function _(key) { + console.log("getting translation for ", locale, key); + return !(locale in langs) ? key + : !(key in langs[locale]) ? key + : langs[locale][key] +} + +export function setLang (loc) { + locale = loc; +} + +export default _; diff --git a/site/index.html b/site/index.html index 5771e94..bceb936 100644 --- a/site/index.html +++ b/site/index.html @@ -1,4 +1,4 @@ -<html> +<html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> @@ -10,6 +10,7 @@ <script type="module"> import init, { age_encrypt, age_decrypt } from "./rage_wasm.js"; + import _, { setLang } from "./i18n.js"; /// the basic idea here is to have functions which construct parts /// of the DOM that renders the survey to a user. These functions @@ -122,6 +123,8 @@ // makes a survey from a given json config object function mkSurvey (survey) { document.title = survey.title; + setLang(survey.lang); + document.getElementsByTagName("html")[0].lang = survey.lang; // make the header with general information let header = document.createElement("div"); appendChildren(header, [ @@ -146,7 +149,7 @@ }); let footer = mkElement("section"); - let submit = mkElement("button", "Submit"); + let submit = mkElement("button", _("submit")); let errormsg = mkElement("p", "", "error"); appendChildren(footer, [ mkElement("hr"), @@ -182,17 +185,17 @@ console.log(response.text()) window.location.href = "thanks.html"; } - errormsg.innerText = "POST request returned error code:\n" + errormsg.innerText = _("Error: post returned error") + "\n" + response.status + ": " + response.statusText; errormsg.hidden = false; }).catch(error => { console.log(error); - errormsg.innerText = "Error: The http POST request did not succeed."; + errormsg.innerText = _("Error: could not post"); errormsg.hidden = false; }); } else { - errormsg.innerText = "Cannot submit: not all required questions were filled in!"; + errormsg.innerText = _("Error: answers invalid"); errormsg.hidden = false; } } @@ -207,21 +210,21 @@ /// displays a passphrase prompt until the use enters a passphrase /// which age can use for successful decryption function askPassphrase (ciphertext, secondTry=false) { - document.title = "Enter Passphrase"; + document.title = _("Enter Passphrase"); let div = mkElement("div"); - let button = mkElement("button", "decrypt"); + let button = mkElement("button", _("decrypt")); let [passphrase,label] = mkOption( "password", - "please enter a passphrase to access the survey:" + _("please enter passphrase") ); passphrase.value = ""; appendChildren(div, [ - mkElement("h1", "Passphrase"), + mkElement("h1", _("Passphrase")), appendChildren(mkElement("p"),[label]), passphrase, button ].concat( - secondTry ? [mkElement("p","passphrase was incorrect!","error")] : [] + secondTry ? [mkElement("p",_("passphrase incorrect"),"error")] : [] )); root.appendChild(div); button.onclick = () => { @@ -247,7 +250,7 @@ mkElement("h1", "Error"), mkElement("p", msg, "error"), appendChildren( - mkElement("p","attempted path: ","error"), + mkElement("p",_("attempted path:"),"error"), [mkElement("tt", surveyUrl,"error")] ) ]); @@ -275,7 +278,7 @@ console.log ("survey appears to be encrypted"); askPassphrase(bytearray); } else { - mkReadError ("Could not load this survey; it appears to be in a wrong or unknown format."); + mkReadError (_("Error: unknown format")); } } /// if the survey was unencrypted, start it here. If it @@ -287,14 +290,14 @@ } // couldn't load survey json, show error message } else { - mkReadError ("Could not load this survey; are you sure that it exists?"); + mkReadError (_("Error: survey doesn't exist")); } } } } if (surveyUrl === "") { - mkReadError ("There's nothing here. Maybe try appending something after the url?\n\nAlternatively, check to see if you copied the whole url."); + mkReadError (_("Error: nothing here")); } else { main () } diff --git a/site/thanks.html b/site/thanks.html index 1f0a18b..e7b5ad4 100644 --- a/site/thanks.html +++ b/site/thanks.html @@ -1,4 +1,4 @@ -<html> +<html lang="en"> <head> <meta charset="UTF-8"> <title>Thanks for answering the survey!</title> diff --git a/utils/src/main.rs b/utils/src/main.rs index 3d6f885..4428ac3 100644 --- a/utils/src/main.rs +++ b/utils/src/main.rs @@ -12,11 +12,19 @@ use secrecy::ExposeSecret; use age::x25519::Recipient; #[derive(Deserialize, Serialize, StaticType, Debug)] +#[serde(rename_all="lowercase")] +enum Lang { + de, + en +} + +#[derive(Deserialize, Serialize, StaticType, Debug)] struct Survey { title: String, description: String, questions: Vec<Question>, - pubkey: Option<String> + pubkey: Option<String>, + lang: Lang } #[derive(Deserialize, Serialize, StaticType, Debug)] @@ -56,9 +64,10 @@ fn main () { // imported: just wrap our input code into a dhall "let"-statement. // Probably doesn't scale very vell, though ... let code = format!( - "let Question = {} \nlet Answers = {} \nin {}", + "let Question = {} \nlet Answers = {} \nlet Lang = {}\nin {}", Question::static_type(), AnswerSpace::static_type(), + Lang::static_type(), config_file ); match serde_dhall::from_str(&code) |