diff --git a/auth.php b/auth.php index 1f5ad8a..0ef6fbf 100644 --- a/auth.php +++ b/auth.php @@ -40,7 +40,9 @@ if ( !$accepted ) { http_response_code(403); - print "Access from IP address ".htmlspecialchars($ip)." is not allowed"; + // (api.php doesn't load the locale) + $text = function_exists('__') ? __('Access from IP address %s is not allowed') : 'Access from IP address %s is not allowed'; + print "" . sprintf($text, htmlspecialchars($ip)) . ""; exit; } } diff --git a/functions.php b/functions.php index bf19c2d..b3f6ced 100644 --- a/functions.php +++ b/functions.php @@ -51,6 +51,17 @@ function __( $label, $alt_word = null ) return h($w2_word_set[$label]); } +/** + * Get translated word as a JavaScript string literal (with quotes), for inline scripts + * + * String $label Key for locale word + * return String + */ +function __js( $label ) +{ + return json_encode(html_entity_decode(__($label), ENT_QUOTES | ENT_HTML5, W2_CHARSET), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_UNESCAPED_UNICODE); +} + function descLengthSort($val_1, $val_2) { $firstVal = strlen($val_1); diff --git a/index.php b/index.php index 4d0ac5e..6b7a174 100644 --- a/index.php +++ b/index.php @@ -68,26 +68,26 @@ function printDrawer() "###### ".__('Header')." 6
". "
". "*".__('Emphasize')."* - ".__('Emphasize')."
". - "_".__('Emphasize')."* - ".__('Emphasize')."
". + "_".__('Emphasize')."_ - ".__('Emphasize')."
". "**".__('Bold')."** - ".__('Bold')."
". "__".__('Bold')."__ - ".__('Bold')."
". "
". - "[[Link to page]]
". + "[[".__('Link to page')."]]
". "<http://example.com/>
". - "[link text](http://url)

". - "![Alt text](/images/image.jpg)
". - "![Alt text](/images/image.jpg \"Optional title\")
". + "[".__('link text')."](http://url)

". + "![".__('Alt text')."](/images/image.jpg)
". + "![".__('Alt text')."](/images/image.jpg \"".__('Optional title')."\")
". "
". - "- Unordered list
". - "+ Unordered list
". - "* Unordered list
". - "1. Ordered list
". + "- ".__('Unordered list')."
". + "+ ".__('Unordered list')."
". + "* ".__('Unordered list')."
". + "1. ".__('Ordered list')."
". "
". - "> Blockquote
".//
Blockquotes
\n". - "```Code```
". //
Code
\n\n". - "`inline-code`

". - "*** Horizontal rule
". - "--- Horizontal rule
\n". + "> ".__('Blockquote')."
". + "```".__('Code')."```
". + "`".__('Inline code')."`

". + "*** ".__('Horizontal rule')."
". + "--- ".__('Horizontal rule')."
\n". " \n". " \n". " \n". @@ -128,7 +128,7 @@ function printDrawer() } if ( (!defined('W2_PASSWORD_HASH') || W2_PASSWORD_HASH === '') && defined('W2_PASSWORD') && W2_PASSWORD === 'secret' ) { - print "

Login is disabled while the default password is configured; please set W2_PASSWORD_HASH (or W2_PASSWORD) in config.php.

\n"; + print "

" . __('Login is disabled while the default password is configured; please set W2_PASSWORD_HASH (or W2_PASSWORD) in config.php.') . "

\n"; } print "
\n"; print " ".__('Password') . ": \n"; @@ -174,7 +174,7 @@ function checkedExecute(&$msg, $cmd) { // details (command, output) may reveal server internals, so only log them error_log("W2: error executing command $cmd (return value: $returnValue): ".implode(" ", $output)); - $msg .= "
Error executing git command (return value: ".$returnValue."); see the web server's error log for details."; + $msg .= "
".sprintf(__("Error executing git command (return value: %s); see the web server's error log for details."), h($returnValue)); } return ($returnValue == 0); } @@ -221,7 +221,7 @@ function destroy_session() ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isValidCSRFToken($_POST['csrf_token'] ?? null))) { http_response_code(403); - die('Invalid request: missing or wrong security token. Please go back, reload the page and try again.'); + die(__('Invalid request: missing or wrong security token. Please go back, reload the page and try again.')); } if ($action === 'logout' && !isValidCSRFToken($_GET['csrf_token'] ?? null)) { @@ -269,7 +269,7 @@ function destroy_session() { $basePage = basename($p); if ($basePage == $page) { - redirectWithMessage($p, "Page ".h($page)." does not exist, redirected instead to first page in a subfolder with matching filename (".h($p).")"); + redirectWithMessage($p, sprintf(__("Page %s does not exist, redirected instead to first page in a subfolder with matching filename (%s)"), h($page), h($p))); } } $newPage = $page; @@ -291,8 +291,8 @@ function destroy_session() if ($isNew && (file_exists($filename) || !isValidPageName($page))) { $msg .= file_exists($filename) - ? "Error creating page '".h($page)."' - it already exists! Please choose a different name, or
edit the existing page (this discards current text!)!\n" - : "Error creating page '".h($page)."' - invalid page name! Page names must not start with '".UPLOAD_FOLDER."/', or contain empty or hidden ('.'-prefixed) folder names.\n"; + ? sprintf(__("Error creating page '%s' - it already exists! Please choose a different name, or %s the existing page (this discards current text!)!"), h($page), "".__('edit')."")."\n" + : sprintf(__("Error creating page '%s' - invalid page name! Page names must not start with '%s/', or contain empty or hidden ('.'-prefixed) folder names."), h($page), h(UPLOAD_FOLDER))."\n"; $action = 'new'; $text = $newText; $newPage = $page; @@ -311,7 +311,7 @@ function destroy_session() $success = file_put_contents($filename, $newText); if ( $success === FALSE) { - $msg .= "Error saving changes! Make sure your web server has write access to the pages folder.\n"; + $msg .= __('Error saving changes! Make sure your web server has write access to the pages folder.')."\n"; error_log("W2: error saving $filename"); $action = ($isNew ? 'new' : 'edit'); $text = $newText; @@ -361,7 +361,7 @@ function destroy_session() { if (levenshtein(strtoupper($newPage), strtoupper($pageName)) < sqrt(min(strlen($newPage), strlen($pageName))) ) { - $html .= "
Note: Found similar page ".pageLink($pageName, h($pageName)).". Maybe you meant to edit this instead?"; + $html .= "
".__('Note').": ".sprintf(__('Found similar page %s. Maybe you meant to edit this instead?'), pageLink($pageName, h($pageName))); } } $html .= "\n"; @@ -373,7 +373,7 @@ function destroy_session() $html .= "

\n"; if (GIT_COMMIT_ENABLED) { - $html .= "

Message:

\n"; + $html .= "

".__('Message').":

\n"; } $html .= "

\n"; @@ -417,14 +417,14 @@ function destroy_session() 'function processForm(e) {'."\n". ' e.preventDefault();'."\n". ' var fileInput = document.getElementById("file");'."\n". - ' if (fileInput.files.length == 0) { alert("No file selected!"); return; }'."\n". + ' if (fileInput.files.length == 0) { alert('.__js('No file selected!').'); return; }'."\n". ' var filename = fileInput.files[0].name;'."\n". ' fetch("'.BASE_URI.'/api.php?task=checkupload&filename="+encodeURIComponent(filename))'."\n". ' .then((response) => {'."\n". ' response.json().then((data) => {'."\n". ' upload = true;'."\n". ' if (data) {'."\n". - ' upload = window.confirm("File "+filename+" already exists. Overwrite?");'."\n". + ' upload = window.confirm('.__js('File %s already exists. Overwrite?').'.replace("%s", () => filename));'."\n". ' }'."\n". ' if (upload) {'."\n". ' document.getElementById("overwrite").value = data ? "true" : "";'."\n". @@ -490,10 +490,10 @@ function destroy_session() $html .= ""; $html .= "". - "". + "". "". - "". - "". + "". + "". ""; if (SHOW_PAGES_WHERE_FILE_USED) { @@ -541,7 +541,7 @@ function destroy_session() { if ( DISABLE_UPLOADS ) { - die('Invalid access. Uploads are disabled in the configuration.'); + die(__('Invalid access. Uploads are disabled in the configuration.')); } $uploadError = $_FILES['userfile']['error'] ?? UPLOAD_ERR_NO_FILE; if ( $uploadError === UPLOAD_ERR_INI_SIZE || $uploadError === UPLOAD_ERR_FORM_SIZE ) @@ -586,12 +586,12 @@ function destroy_session() } if ( file_exists($finalPath) && ($_POST['overwrite'] ?? '') !== 'true' ) { - $msg .= __('Upload error').": ".h(basename($finalPath))." already exists!"; + $msg .= __('Upload error').": ".sprintf(__('%s already exists!'), h(basename($finalPath))); } else if ( ($svgData !== null) ? (file_put_contents($path, $svgData) !== false) : (move_uploaded_file($tmpName, $path) === true) ) { $commitMsg = "File '$dstName' uploaded!"; - $msg .= h($commitMsg)." "; + $msg .= sprintf(__("File '%s' uploaded!"), h($dstName))." "; $processFailed = false; if ($doProcess) { @@ -614,11 +614,11 @@ function destroy_session() try { $img->resizeImage($newSize[0], $newSize[1], imagick::FILTER_LANCZOS, 1); - $msg .= "Original size was $size[0]x$size[1], resized to $newSize[0]x$newSize[1]. "; + $msg .= sprintf(__('Original size was %s, resized to %s.'), "$size[0]x$size[1]", "$newSize[0]x$newSize[1]")." "; } catch (ImagickException $e) { - $msg .= "Resizing file failed! "; + $msg .= __('Resizing file failed!')." "; } } $ori = $img->getImageOrientation(); @@ -627,15 +627,15 @@ function destroy_session() switch($ori) { case imagick::ORIENTATION_RIGHTTOP: - $msg .= "Image rotated by +90°. "; + $msg .= sprintf(__('Image rotated by %s°.'), '+90')." "; $img->rotateImage('#000',90); break; case imagick::ORIENTATION_BOTTOMRIGHT: - $msg .= "Image rotated by 180°. "; + $msg .= sprintf(__('Image rotated by %s°.'), '180')." "; $img->rotateImage('#000',180); break; case imagick:: ORIENTATION_LEFTBOTTOM: - $msg .= "Image rotated by -90°. "; + $msg .= sprintf(__('Image rotated by %s°.'), '-90')." "; $img->rotateImage('#000',-90); break; // default: @@ -648,7 +648,7 @@ function destroy_session() { $dstName = substr($dstName, 0, strlen($dstName)-strlen($fileExt)).CONVERT_FORMAT; $img->setImageFormat(CONVERT_FORMAT); - $msg .= "Converted to format ".CONVERT_FORMAT.". "; + $msg .= sprintf(__('Converted to format %s.'), h(CONVERT_FORMAT))." "; } $img->writeImage($finalPath); unlink($path); @@ -663,14 +663,14 @@ function destroy_session() unlink($path); } $processFailed = true; - $msg = __('Upload error').": ".h($dstName)." could not be processed (is it a valid image?)"; + $msg = __('Upload error').": ".sprintf(__('%s could not be processed (is it a valid image?)'), h($dstName)); } } if (!$processFailed) { gitChangeHandler($commitMsg, $msg); - $msg .= "Use
".h(imageLinkText($dstName))."
to refer to it!"; + $msg .= sprintf(__('Use %s to refer to it!'), "
".h(imageLinkText($dstName))."
"); } } else @@ -680,15 +680,15 @@ function destroy_session() { // Likely a permissions issue error_log("W2: can't write upload to $path"); - $msg .= __('Upload error') .": Can't write to the uploads folder

\n". - "Check that your permissions are set correctly."; + $msg .= __('Upload error') .": ".__("Can't write to the uploads folder")."

\n". + __('Check that your permissions are set correctly.'); } else { // Give generic error message $msg .= __('Upload error').", error #".$error_code."

\n". - "Please see here for more information.

\n". - "If you see this message, please file a bug to improve w2wiki"; + sprintf(__('Please see %s for more information.'), "".__('here')."")."

\n". + sprintf(__('If you see this message, please %s'), "".__('file a bug to improve w2wiki').""); } } } @@ -715,7 +715,7 @@ function destroy_session() : "?") . "

"; $html .= "

"; - $html .= "\n"; + $html .= "\n"; $html .= ""; $html .= ""; if ($action === 'imgDelete' || $action === 'imgRename') @@ -889,7 +889,7 @@ function destroy_session() $html .= "

".__('Total').": ".count($pageNames)." ".__("pages")."

"; $html .= "
".(($sortBy!='name')?("Name"):"Name")."".(($sortBy!='name')?("".__('Name').""):"".__('Name')."")."".__("Usage")."".(($sortBy!='recent')?("Modified"):"Modified")."".(($sortBy!='size')?("Size"):"Size")."".(($sortBy!='recent')?("".__('Modified').""):"".__('Modified')."")."".(($sortBy!='size')?("".__('Size').""):"".__('Size')."")."".__("Action")."
"; $html .= "". - "". + "". "". "". "". @@ -911,7 +911,7 @@ function destroy_session() { $matches = 0; $q = $_REQUEST['q']; - $html .= "

Search: ".h($q)."

\n"; + $html .= "

".__('Search').": ".h($q)."

\n"; if ( trim($q) != "" ) { diff --git a/locales/de.php b/locales/de.php index a5b601b..7a4d74f 100644 --- a/locales/de.php +++ b/locales/de.php @@ -19,8 +19,6 @@ 'Created' => 'Angelegt', 'Upload' => 'Hochladen', 'All' => 'Alle', - 'Recent' => 'Zuletzt', - 'Exit' => 'Ausloggen', 'Search' => 'Suchen', 'Formatting help' => 'Formatierungshilfe', 'Bold' => 'Fett', @@ -30,9 +28,10 @@ 'Cancel' => 'Abbrechen', 'Saved' => 'Gespeichert', 'Log In' => 'Einloggen', - 'Log Out' => 'Ausloggen', + 'Log out' => 'Ausloggen', 'Password' => 'Passwort', 'Wrong password' => 'Falsches Passwort', + 'Invalid page name' => 'Ungültiger Seitenname', 'Title' => 'Titel', 'Image Description' => 'Bildbeschreibung', 'Name' => 'Name', @@ -63,13 +62,52 @@ 'Error renaming file' => 'Fehler beim Umbenennen der Datei', 'Sidebar file could not be found' => 'Seitenleisten-Datei nicht gefunden', 'Name of new page (restrictions in tip)' => 'Seitenname (Einschränkungen im Tip)', - "Character restrictions: '#' and '|' have a special meaning in page links, they will therefore be removed; also, characters '~', '/', '\\', ':', '|', '&' might cause trouble in filenames and are therefore replaced by '-'." => "Buchstaben-Beschränkungen: '#' und '|' haben eine spezielle Bedeutung in Links, sie werden deshalb entfernt. Weiters können die Zeichen '~', '/', '\\', ':', '|', '&' Probleme in Dateinamen verursachen, und werden deshalb durch einen Bindestrich '-' ersetzt.", + "Character restrictions: '#' and '|' have a special meaning in page links, they will therefore be removed; also, characters '~', '..', '\\', ':', '|', '&' might cause trouble in filenames and are therefore replaced by '-'." => "Buchstaben-Beschränkungen: '#' und '|' haben eine spezielle Bedeutung in Links, sie werden deshalb entfernt. Weiters können die Zeichen '~', '..', '\\', ':', '|', '&' Probleme in Dateinamen verursachen, und werden deshalb durch einen Bindestrich '-' ersetzt.", 'Image deleted' => 'Bild gelöscht', 'Image renamed' => 'Bild umbenannt', - 'Error deleting image' => 'Fehler beim Löschen des Bildes', + 'Error deleting image: ' => 'Fehler beim Löschen des Bildes: ', 'Restored unsaved draft from %s.' => 'Ungespeicherter Entwurf vom %s wiederhergestellt.', 'Warning: the page was changed since this draft was started.' => 'Achtung: Die Seite wurde geändert, seit dieser Entwurf begonnen wurde.', 'Discard draft' => 'Entwurf verwerfen', + 'Message' => 'Nachricht', + 'edit' => 'bearbeite', + 'No file selected!' => 'Keine Datei ausgewählt!', + 'File %s already exists. Overwrite?' => 'Die Datei %s existiert bereits. Überschreiben?', + "Error creating page '%s' - it already exists! Please choose a different name, or %s the existing page (this discards current text!)!" => "Fehler beim Anlegen der Seite '%s' - sie existiert bereits! Bitte wähle einen anderen Namen oder %s die bestehende Seite (der aktuelle Text geht dabei verloren!)!", + "Error creating page '%s' - invalid page name! Page names must not start with '%s/', or contain empty or hidden ('.'-prefixed) folder names." => "Fehler beim Anlegen der Seite '%s' - ungültiger Seitenname! Seitennamen dürfen nicht mit '%s/' beginnen und keine leeren oder versteckten (mit '.' beginnenden) Ordnernamen enthalten.", + 'Error saving changes! Make sure your web server has write access to the pages folder.' => 'Fehler beim Speichern der Änderungen! Stelle sicher, dass der Webserver Schreibzugriff auf den Seitenordner hat.', + 'Note' => 'Hinweis', + 'Found similar page %s. Maybe you meant to edit this instead?' => 'Ähnliche Seite gefunden: %s. Vielleicht wolltest du stattdessen diese bearbeiten?', + "Page %s does not exist, redirected instead to first page in a subfolder with matching filename (%s)" => "Die Seite %s existiert nicht, stattdessen wurde auf die erste Seite in einem Unterordner mit passendem Dateinamen weitergeleitet (%s)", + 'Login is disabled while the default password is configured; please set W2_PASSWORD_HASH (or W2_PASSWORD) in config.php.' => 'Das Einloggen ist gesperrt, solange das Standardpasswort eingestellt ist; bitte setze W2_PASSWORD_HASH (oder W2_PASSWORD) in config.php.', + 'Invalid request: missing or wrong security token. Please go back, reload the page and try again.' => 'Ungültige Anfrage: Das Sicherheitstoken fehlt oder ist falsch. Bitte gehe zurück, lade die Seite neu und versuche es erneut.', + 'Invalid access. Uploads are disabled in the configuration.' => 'Ungültiger Zugriff. Hochladen ist in der Konfiguration deaktiviert.', + "Error executing git command (return value: %s); see the web server's error log for details." => "Fehler beim Ausführen des git-Befehls (Rückgabewert: %s); Details stehen im Fehlerprotokoll des Webservers.", + 'Access from IP address %s is not allowed' => 'Zugriff von der IP-Adresse %s ist nicht erlaubt', + '%s already exists!' => '%s existiert bereits!', + "File '%s' uploaded!" => "Datei '%s' hochgeladen!", + 'Original size was %s, resized to %s.' => 'Ursprüngliche Größe war %s, verkleinert auf %s.', + 'Resizing file failed!' => 'Verkleinern der Datei fehlgeschlagen!', + 'Image rotated by %s°.' => 'Bild um %s° gedreht.', + 'Converted to format %s.' => 'In das Format %s umgewandelt.', + '%s could not be processed (is it a valid image?)' => '%s konnte nicht verarbeitet werden (ist es ein gültiges Bild?)', + 'Use %s to refer to it!' => 'Verwende %s, um darauf zu verweisen!', + "Can't write to the uploads folder" => 'Der Upload-Ordner ist nicht beschreibbar', + 'Check that your permissions are set correctly.' => 'Prüfe, ob die Berechtigungen richtig gesetzt sind.', + 'Please see %s for more information.' => 'Weitere Informationen stehen %s.', + 'here' => 'hier', + 'If you see this message, please %s' => 'Wenn du diese Meldung siehst, bitte %s', + 'file a bug to improve w2wiki' => 'melde einen Fehler, um w2wiki zu verbessern', + 'Link to page' => 'Link auf Seite', + 'link text' => 'Linktext', + 'Alt text' => 'Alternativtext', + 'Optional title' => 'Optionaler Titel', + 'Unordered list' => 'Aufzählung', + 'Ordered list' => 'Nummerierte Liste', + 'Blockquote' => 'Zitat', + 'Code' => 'Code', + 'Inline code' => 'Code im Text', + 'Horizontal rule' => 'Horizontale Linie', // Override TITLE_DATE and TITLE_DATE_NO_TIME if set. 'date_format' => 'd.m.Y H:i', 'date_format_no_time' => 'd.m.Y', diff --git a/locales/en.php b/locales/en.php index 46de617..7b51124 100644 --- a/locales/en.php +++ b/locales/en.php @@ -6,34 +6,16 @@ * Do not change variable name $w2_word_set. * Rewrite values in your locale and rename this file to locale code. * Set "LOCALE" to your locale in config.php. + * + * The English texts are the keys themselves: __() shows the key of a text which has no entry + * here, so this file only has the entries which are not the same as their key. To translate, + * add an entry for every text used with __() in the code (see the other files in this folder, + * and tests/Unit/LocaleFilesTest.php for the list of missing translations). */ $w2_word_set = array( - // Buttons / Labels - 'Home' => 'Home', - 'New' => 'New', - 'Edit' => 'Edit', - 'Upload' => 'Upload', + // Titles of the actions (the key is the name of the action) 'imgDelete' => 'Delete image', 'imgRename' => 'Rename image', - 'All' => 'All', - 'Recent' => 'Recent', - 'Exit' => 'Exit', - 'Search' => 'Search', - 'Save' => 'Save', - 'Cancel' => 'Cancel', - 'Saved' => 'Saved', - 'Log In' => 'Log In', - 'Title' => 'Title', - // Messages - 'Upload error' => 'Upload error', - 'Upload error: invalid file type' => 'Upload error: invalid file type', - 'The upload is too large: the server accepts requests of up to %s (post_max_size).' => 'The upload is too large: the server accepts requests of up to %s (post_max_size).', - 'Nothing was uploaded or saved. Please go back and try again with a smaller file.' => 'Nothing was uploaded or saved. Please go back and try again with a smaller file.', - 'Upload error: the file is larger than the allowed %s (upload_max_filesize).' => 'Upload error: the file is larger than the allowed %s (upload_max_filesize).', - 'Image uploading has been disabled on this installation.' => 'Image uploading has been disabled on this installation.', - 'Restored unsaved draft from %s.' => 'Restored unsaved draft from %s.', - 'Warning: the page was changed since this draft was started.' => 'Warning: the page was changed since this draft was started.', - 'Discard draft' => 'Discard draft', // Override TITLE_DATE and TITLE_DATE_NO_TIME if set. 'date_format' => 'Y-m-d H:i:s', 'date_format_no_time' => 'Y-m-d', diff --git a/locales/ja.php b/locales/ja.php index 26ca03a..c528a0c 100644 --- a/locales/ja.php +++ b/locales/ja.php @@ -14,8 +14,7 @@ 'Edit' => '編集', 'Upload' => 'アップロード', 'All' => '全て', - 'Recent' => '最近', - 'Exit' => 'ログアウト', + 'Log out' => 'ログアウト', 'Search' => '検索', 'Save' => '保存', 'Cancel' => 'キャンセル', diff --git a/locales/oc.php b/locales/oc.php index 449a762..ff79cf7 100644 --- a/locales/oc.php +++ b/locales/oc.php @@ -18,8 +18,6 @@ 'Created' => 'Creacion', 'Upload' => 'Enviar', 'All' => 'Tot', - 'Recent' => 'Recents', - 'Exit' => 'Sortir', 'Search' => 'Recercar', 'Formatting help' => 'Ajuda al formatatge', 'Bold' => 'Gras', @@ -29,7 +27,7 @@ 'Cancel' => 'Anullar', 'Saved' => 'Salvat', 'Log In' => 'Connexion', - 'Log Out' => 'Desconnexion', + 'Log out' => 'Desconnexion', 'Password' => 'Senhal', 'Title' => 'Títol', 'Image Description' => 'Descripcion de l’imatge', @@ -57,9 +55,9 @@ 'Error renaming file' => 'Error en renomenant lo fichièr', 'Sidebar file could not be found' => 'Impossible de trobar la barra laterala', 'Name of new page (restrictions in tip)' => 'Nom de la pagina novèla (restriccion dins las astúcias)', - "Character restrictions: '#' and '|' have a special meaning in page links, they will therefore be removed; also, characters '~', '/', '\\', ':', '|', '&' might cause trouble in filenames and are therefore replaced by '-'." => "Restriccions dels caractèrs : '#' e '|' an una significacion especiala dins los ligams de pagina, seràn doncas tirats ; tanben, los caractèrs '~', '/', '\\', ':', '|', '&' que pòdon causar de problèmas dins los noms de fichièrs seràn remplaçat per '-'.", + "Character restrictions: '#' and '|' have a special meaning in page links, they will therefore be removed; also, characters '~', '..', '\\', ':', '|', '&' might cause trouble in filenames and are therefore replaced by '-'." => "Restriccions dels caractèrs : '#' e '|' an una significacion especiala dins los ligams de pagina, seràn doncas tirats ; tanben, los caractèrs '~', '..', '\\', ':', '|', '&' que pòdon causar de problèmas dins los noms de fichièrs seràn remplaçat per '-'.", 'Image deleted' => 'Imatge suprimit', - 'Error deleting image' => 'Error de supression de l’imatge', + 'Error deleting image: ' => 'Error de supression de l’imatge : ', // Override TITLE_DATE and TITLE_DATE_NO_TIME if set. 'date_format' => 'd/m/Y H:i:s', 'date_format_no_time' => 'd/m/Y', diff --git a/locales/sample.php b/locales/sample.php index c609d05..76ac32a 100644 --- a/locales/sample.php +++ b/locales/sample.php @@ -14,8 +14,6 @@ 'Edit' => 'Edit', 'Upload' => 'Upload', 'All' => 'All', - 'Recent' => 'Recent', - 'Exit' => 'Exit', 'Search' => 'Search', 'Save' => 'Save', 'Cancel' => 'Cancel', diff --git a/tests/Integration/LocaleEscapingTest.php b/tests/Integration/LocaleEscapingTest.php new file mode 100644 index 0000000..90d49e9 --- /dev/null +++ b/tests/Integration/LocaleEscapingTest.php @@ -0,0 +1,61 @@ +\'&'; + + protected function configOverrides(): array + { + return ['W2_LOCALE' => 'generated']; + } + + protected function setUp(): void + { + parent::setUp(); + $texts = []; + foreach (['All', 'New', 'Upload', 'Search', 'Home', 'Edit', 'Save', 'Cancel', 'Title', 'Close', 'Formatting help', 'Header', 'Bold', 'Emphasize'] as $key) { + $texts[$key] = self::PAYLOAD . $key; + } + file_put_contents($this->server->rootDir() . '/locales/generated.php', "server->rootDir() . '/locales/generated.php'); + parent::tearDown(); + } + + public function testTextsWithMarkupAndQuotesAreEscaped(): void + { + foreach (['/index.php', '/index.php?action=all', '/index.php?action=new', '/index.php?action=edit&page=Home'] as $url) { + $response = $this->http->get($url); + $this->assertSame(200, $response->status, $url); + $this->assertStringNotContainsString('
".(($sortBy!='name')?("Name"):"".__('Name')."")."".(($sortBy!='name')?("".__('Name').""):"".__('Name')."")."".(($sortBy!='recent')?("".__('Modified').""):"".__('Modified')."")."".(($sortBy!='size')?("".__('Size').""):"".__('Size')."")."".__('Action')."