".
- "| ".(($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")." | ";
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 .= "";
$html .= "".
- "| ".(($sortBy!='name')?("Name"):"".__('Name')."")." | ".
+ "".(($sortBy!='name')?("".__('Name').""):"".__('Name')."")." | ".
"".(($sortBy!='recent')?("".__('Modified').""):"".__('Modified')."")." | ".
"".(($sortBy!='size')?("".__('Size').""):"".__('Size')."")." | ".
"".__('Action')." | ".
@@ -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('