From f577ecb81149d0d09dc846204f17b2153a244b5a Mon Sep 17 00:00:00 2001 From: Igor Nadj Date: Thu, 5 Nov 2015 16:09:16 +1300 Subject: [PATCH 1/9] FIX: prevent use cache on browser back button --- control/HTTP.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control/HTTP.php b/control/HTTP.php index 895c126e9..8a65c1be0 100644 --- a/control/HTTP.php +++ b/control/HTTP.php @@ -384,7 +384,7 @@ class HTTP { // prefer the caching information indicated through the "Cache-Control" header. $responseHeaders["Pragma"] = ""; } else { - $responseHeaders["Cache-Control"] = "no-cache, max-age=0, must-revalidate, no-transform"; + $responseHeaders["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate, no-transform"; } } From e68eb7e45de7803a5f1a67cfc30324921be847aa Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Wed, 11 Nov 2015 17:06:45 +1300 Subject: [PATCH 2/9] Update translations --- admin/javascript/lang/de.js | 2 +- admin/javascript/lang/eo.js | 14 ++-- admin/javascript/lang/ro.js | 4 +- admin/javascript/lang/src/de.js | 2 +- admin/javascript/lang/src/eo.js | 14 ++-- admin/javascript/lang/src/ro.js | 4 +- admin/javascript/lang/src/zh.js | 8 +-- admin/javascript/lang/zh.js | 8 +-- lang/cs.yml | 4 -- lang/de.yml | 8 +++ lang/eo.yml | 9 +++ lang/es.yml | 10 +++ lang/fa_IR.yml | 117 +++++++++++++++++++++++++++++++- lang/fr.yml | 4 +- lang/it.yml | 3 + lang/lt.yml | 2 +- lang/sk.yml | 4 -- lang/tr.yml | 6 ++ lang/zh.yml | 34 ++++++++++ 19 files changed, 217 insertions(+), 40 deletions(-) diff --git a/admin/javascript/lang/de.js b/admin/javascript/lang/de.js index d43b2335a..65eb96fb2 100644 --- a/admin/javascript/lang/de.js +++ b/admin/javascript/lang/de.js @@ -9,7 +9,7 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { "CMSMAIN.BATCH_PUBLISH_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich veröffentlichen?", "CMSMAIN.BATCH_DELETE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich löschen?", "CMSMAIN.BATCH_ARCHIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich archivieren?\n\nDiese Seiten und alle Unterseiten davon werden von der veröffentlichen Seite gelöscht und in das Archiv verschoben.", - "CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.", + "CMSMAIN.BATCH_RESTORE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\\n\\nWollen Sie diese wirklich wiederherstellen?\\n\\nUnterseiten von archivierten Seiten werden auf der Root-Ebene wiederhergestellt, es sei denn, diese Seiten werden ebenfalls wiederhergestellt.", "CMSMAIN.BATCH_DELETELIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich von der veröfffentlichten Seite löschen?", "LeftAndMain.CONFIRMUNSAVED": "Sind Sie sicher, dass Sie die Seite verlassen möchten?\n\nWARNUNG: Ihre Änderungen werden nicht gespeichert.\n\nDrücken Sie \"OK\" um fortzufahren, oder \"Abbrechen\" um auf dieser Seite zu bleiben.", "LeftAndMain.CONFIRMUNSAVEDSHORT": "WARNUNG: Ihre Änderungen wurden nicht gespeichert.", diff --git a/admin/javascript/lang/eo.js b/admin/javascript/lang/eo.js index 81eb6d2ea..f46611198 100644 --- a/admin/javascript/lang/eo.js +++ b/admin/javascript/lang/eo.js @@ -4,13 +4,13 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); } else { ss.i18n.addDictionary('eo', { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", - "CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", - "CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", - "CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.", - "CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.", - "CMSMAIN.BATCH_DELETELIVE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?", + "CMSMAIN.SELECTONEPAGE": "Bonvole elektu almenaŭ 1 paĝon.", + "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas malpublikigi?", + "CMSMAIN.BATCH_PUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas publikigi?", + "CMSMAIN.BATCH_DELETE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas forigi?", + "CMSMAIN.BATCH_ARCHIVE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈu vi vere volas enarĥivigi tiujn paĝojn?\n\nTiuj paĝoj kaj ĉiuj idaj paĝoj estos malpublikigitaj kaj senditaj al la arĥivo.", + "CMSMAIN.BATCH_RESTORE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈu vi vere volas restaŭri al stadio?\n\nIdoj de enarĥivigitaj paĝoj estos restaŭritaj al la radika nivelo, escepte se tiuj paĝoj ankaŭ estos restaŭritaj.", + "CMSMAIN.BATCH_DELETELIVE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas forigi tiujn paĝojn el la publika stadio?", "LeftAndMain.CONFIRMUNSAVED": "Ĉu vi vere volas navigi for de ĉi tiu paĝo?\n\nAVERTO: Viaj ŝanĝoj ne estas konservitaj.\n\nPremu je Akcepti por daŭrigi, aŭ Nuligi por resti ĉe la aktuala paĝo.", "LeftAndMain.CONFIRMUNSAVEDSHORT": "AVERTO: Viaj ŝanĝoj ne estas konservitaj.", "SecurityAdmin.BATCHACTIONSDELETECONFIRM": "Ĉu vi vere volas forigi %s grupojn?", diff --git a/admin/javascript/lang/ro.js b/admin/javascript/lang/ro.js index c5895f4ab..733561e71 100644 --- a/admin/javascript/lang/ro.js +++ b/admin/javascript/lang/ro.js @@ -4,8 +4,8 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); } else { ss.i18n.addDictionary('ro', { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", + "CMSMAIN.SELECTONEPAGE": "Vă rugăm să selectaţi cel puțin o pagină.", + "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "Aveti {num} pagina(i) selectate.\n\nDoriti sa le nenublicati", "CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", "CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", "CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.", diff --git a/admin/javascript/lang/src/de.js b/admin/javascript/lang/src/de.js index 9f10852dd..5599a84af 100644 --- a/admin/javascript/lang/src/de.js +++ b/admin/javascript/lang/src/de.js @@ -4,7 +4,7 @@ "CMSMAIN.BATCH_PUBLISH_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich veröffentlichen?", "CMSMAIN.BATCH_DELETE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich löschen?", "CMSMAIN.BATCH_ARCHIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich archivieren?\n\nDiese Seiten und alle Unterseiten davon werden von der veröffentlichen Seite gelöscht und in das Archiv verschoben.", - "CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.", + "CMSMAIN.BATCH_RESTORE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\\n\\nWollen Sie diese wirklich wiederherstellen?\\n\\nUnterseiten von archivierten Seiten werden auf der Root-Ebene wiederhergestellt, es sei denn, diese Seiten werden ebenfalls wiederhergestellt.", "CMSMAIN.BATCH_DELETELIVE_PROMPT": "Sie haben {num} Seite(n) ausgewählt.\n\nWollen Sie diese wirklich von der veröfffentlichten Seite löschen?", "LeftAndMain.CONFIRMUNSAVED": "Sind Sie sicher, dass Sie die Seite verlassen möchten?\n\nWARNUNG: Ihre Änderungen werden nicht gespeichert.\n\nDrücken Sie \"OK\" um fortzufahren, oder \"Abbrechen\" um auf dieser Seite zu bleiben.", "LeftAndMain.CONFIRMUNSAVEDSHORT": "WARNUNG: Ihre Änderungen wurden nicht gespeichert.", diff --git a/admin/javascript/lang/src/eo.js b/admin/javascript/lang/src/eo.js index bcea526f6..1a69993f4 100644 --- a/admin/javascript/lang/src/eo.js +++ b/admin/javascript/lang/src/eo.js @@ -1,11 +1,11 @@ { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", - "CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", - "CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", - "CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.", - "CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.", - "CMSMAIN.BATCH_DELETELIVE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?", + "CMSMAIN.SELECTONEPAGE": "Bonvole elektu almenaŭ 1 paĝon.", + "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas malpublikigi?", + "CMSMAIN.BATCH_PUBLISH_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas publikigi?", + "CMSMAIN.BATCH_DELETE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas forigi?", + "CMSMAIN.BATCH_ARCHIVE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈu vi vere volas enarĥivigi tiujn paĝojn?\n\nTiuj paĝoj kaj ĉiuj idaj paĝoj estos malpublikigitaj kaj senditaj al la arĥivo.", + "CMSMAIN.BATCH_RESTORE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈu vi vere volas restaŭri al stadio?\n\nIdoj de enarĥivigitaj paĝoj estos restaŭritaj al la radika nivelo, escepte se tiuj paĝoj ankaŭ estos restaŭritaj.", + "CMSMAIN.BATCH_DELETELIVE_PROMPT": "Vi elektis {num} paĝo(j)n.\n\nĈi vi vere volas forigi tiujn paĝojn el la publika stadio?", "LeftAndMain.CONFIRMUNSAVED": "Ĉu vi vere volas navigi for de ĉi tiu paĝo?\n\nAVERTO: Viaj ŝanĝoj ne estas konservitaj.\n\nPremu je Akcepti por daŭrigi, aŭ Nuligi por resti ĉe la aktuala paĝo.", "LeftAndMain.CONFIRMUNSAVEDSHORT": "AVERTO: Viaj ŝanĝoj ne estas konservitaj.", "SecurityAdmin.BATCHACTIONSDELETECONFIRM": "Ĉu vi vere volas forigi %s grupojn?", diff --git a/admin/javascript/lang/src/ro.js b/admin/javascript/lang/src/ro.js index 43d6cba2c..2488400ea 100644 --- a/admin/javascript/lang/src/ro.js +++ b/admin/javascript/lang/src/ro.js @@ -1,6 +1,6 @@ { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", + "CMSMAIN.SELECTONEPAGE": "Vă rugăm să selectaţi cel puțin o pagină.", + "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "Aveti {num} pagina(i) selectate.\n\nDoriti sa le nenublicati", "CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", "CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", "CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.", diff --git a/admin/javascript/lang/src/zh.js b/admin/javascript/lang/src/zh.js index 686b667d3..c61a5628e 100644 --- a/admin/javascript/lang/src/zh.js +++ b/admin/javascript/lang/src/zh.js @@ -1,8 +1,8 @@ { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", - "CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", - "CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", + "CMSMAIN.SELECTONEPAGE": "请至少选择一个页面", + "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要取消发布", + "CMSMAIN.BATCH_PUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要发布?", + "CMSMAIN.BATCH_DELETE_PROMPT": "您已选了{num}个页面。\n\n是否确定要删除?", "CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.", "CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.", "CMSMAIN.BATCH_DELETELIVE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?", diff --git a/admin/javascript/lang/zh.js b/admin/javascript/lang/zh.js index f55fd2a3e..bea2e3a73 100644 --- a/admin/javascript/lang/zh.js +++ b/admin/javascript/lang/zh.js @@ -4,10 +4,10 @@ if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') { if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined'); } else { ss.i18n.addDictionary('zh', { - "CMSMAIN.SELECTONEPAGE": "Please select at least one page", - "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to unpublish", - "CMSMAIN.BATCH_PUBLISH_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to publish?", - "CMSMAIN.BATCH_DELETE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete?", + "CMSMAIN.SELECTONEPAGE": "请至少选择一个页面", + "CMSMAIN.BATCH_UNPUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要取消发布", + "CMSMAIN.BATCH_PUBLISH_PROMPT": "您已选了{num}个页面。\n\n是否确定要发布?", + "CMSMAIN.BATCH_DELETE_PROMPT": "您已选了{num}个页面。\n\n是否确定要删除?", "CMSMAIN.BATCH_ARCHIVE_PROMPT": "You have {num} page(s) selected.\n\nAre you sure you want to archive these pages?\n\nThese pages and all of their children pages will be unpublished and sent to the archive.", "CMSMAIN.BATCH_RESTORE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to restore to stage?\n\nChildren of archived pages will be restored to the root level, unless those pages are also being restored.", "CMSMAIN.BATCH_DELETELIVE_PROMPT": "You have {num} page(s) selected.\n\nDo you really want to delete these pages from live?", diff --git a/lang/cs.yml b/lang/cs.yml index 710dff459..a96f65879 100644 --- a/lang/cs.yml +++ b/lang/cs.yml @@ -292,8 +292,6 @@ cs: FROMWEB: 'Z webu' FindInFolder: 'Hledat ve složce' IMAGEALT: 'Alternativní text (alt)' - IMAGEALTTEXT: 'Alternativní text (alt) - ukáže se, když obrázek nemúže být zobrazen' - IMAGEALTTEXTDESC: 'Zobrazeno na obrazovce, anebo když obrázek nemůže být zobrazen' IMAGEDIMENSIONS: Rozměry IMAGEHEIGHTPX: Výška IMAGETITLE: 'Titul text (tooltip) - další informace o obrázku' @@ -328,11 +326,9 @@ cs: DELETED: Smazáno. DropdownBatchActionsDefault: Akcie HELP: Nápověda - PAGETYPE: 'Typ stránky:' PERMAGAIN: 'Byli jste odhlášeni z CMS. Pokud se chcete znovu přihlásit, zadejte níže své uživatelské jméno a heslo.' PERMALREADY: 'Omlouvám se, ale nemůžete vstoupit do této části CMS. Pokud se chcete přihlásit jako někdo jiný, udělejte tak níže.' PERMDEFAULT: 'Musíte být přihlášen/a k přístup do oblasti administrace, zadejte vaše přihlošovací údaje dole, prosím.' - PLEASESAVE: 'Uložte stránku, prosím. Tato stránka nemůže být aktualizována, protože ještě nebyla uložena.' PreviewButton: Náhled REORGANISATIONSUCCESSFUL: 'Strom webu reorganizován úspěšně.' SAVEDUP: Uloženo. diff --git a/lang/de.yml b/lang/de.yml index 15f637333..037954c17 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -260,6 +260,7 @@ de: many_many_Members: Mitglieder GroupImportForm: Help1: '

Eine oder mehrere Gruppen im CSV-Format (kommaseparierte Werte) importieren. Erweiterte Nutzung

' + Help2: '

Erweiterte Benutzung

  • Gültige Spalten: %s
  • Bereits existierende Gruppen werden anhand ihres eindeutigen Code identifiziert und um neue Einträge aus der Importdatei erweitert.
  • Gruppenhierarchien können mittels der Spalte ParentCode erstellt werden.
  • Berechtigungen können in der Spalte PermissionCode hinzugefügt werden. Schon zugewiesene Berechtigungen werden nicht entfernt.
' ResultCreated: '{count} Gruppe(n) wurden erstellt' ResultDeleted: '%d Gruppe(n) gelöscht' ResultUpdated: '%d Gruppe(n) aktualisiert' @@ -291,6 +292,8 @@ de: FROMWEB: 'Aus dem Web' FindInFolder: 'In Ordner suchen' IMAGEALT: 'Alternativtext (alt)' + IMAGEALTTEXT: 'Alternativtext (alt) - erscheint, falls das Bild nicht angezeigt werden kann.' + IMAGEALTTEXTDESC: 'Wird von Screenreadern vorgelesen oder angezeigt, falls das Bild nicht angezeigt werden kann.' IMAGEDIMENSIONS: Dimensionen IMAGEHEIGHTPX: Höhe (px) IMAGETITLE: 'Titeltext (Tooltip) - für zusätzliche Informationen über das Bild' @@ -325,7 +328,11 @@ de: DELETED: Gelöscht. DropdownBatchActionsDefault: Aktionen HELP: Hilfe + PAGETYPE: 'Seitentyp' PERMAGAIN: 'Sie wurden aus dem System ausgeloggt. Falls Sie sich wieder einloggen möchten, geben Sie bitte Benutzernamen und Passwort im untenstehenden Formular an.' + PERMALREADY: 'Leider dürfen Sie diesen Teil des CMS nicht aufrufen. Wenn Sie sich als jemand anderes einloggen wollen, benutzen Sie bitte das nachstehende Formular.' + PERMDEFAULT: 'Sie müssen angemeldet sein, um auf diesen Bereich zugreifen zu können. Bitte geben Sie Ihre Zugangsdaten ein.' + PLEASESAVE: 'Diese Seite konnte nicht aktualisiert werden weil sie noch nicht gespeichert wurde - bitte speichern.' PreviewButton: Vorschau REORGANISATIONSUCCESSFUL: 'Der Seitenbaum wurde erfolgreich sortiert.' SAVEDUP: Gespeichert. @@ -413,6 +420,7 @@ de: Toggle: 'Hilfe zur Formatierung anzeigen' MemberImportForm: Help1: '

Mitglieder im CSV-Format (kommaseparierte Werte) importieren. Erweiterte Nutzung

' + Help2: '

Erweiterte Benutzung

  • Gültige Spalten: %s
  • Bereits existierende Benutzer werden anhand ihres eindeutigen Code identifiziert und um neue Einträge aus der Importdatei erweitert.
  • Gruppen können in der Spalte Gruppen hinzugefügt werden. Gruppen werden anhand ihres Code erkannt. Mehrere Gruppen werden Komma-separiert eingetragen. Schon zugewiesene Gruppen werden nicht entfernt.
' ResultCreated: '{count} Mitglied(er) wurde(n) erstellt' ResultDeleted: '%d Mitglied(er) gelöscht' ResultNone: 'Keine Änderungen' diff --git a/lang/eo.yml b/lang/eo.yml index 14ca046e4..fbe1f4ba2 100644 --- a/lang/eo.yml +++ b/lang/eo.yml @@ -260,6 +260,7 @@ eo: many_many_Members: Membroj GroupImportForm: Help1: '

Importi unu aŭ pliaj grupojn en formato CSV (perkome disigitaj valoroj values). Vidigi spertulan uzadon

' + Help2: '

Speciala uzado

  • Eblaj kolumnoj: %s
  • Ekzistantaj grupoj kongruiĝas laŭ la valoro de ilia unika Kodo, kaj ĝisdatiĝas per eventualaj valoroj el la importita dosiero
  • Eblas krei grupajn hierarĥiojn per la kolumno ParentCode.
  • Eblas agordi permeskodojn per la kolumno PermissionCode. Ekzistantaj permeskodoj ne vakiĝas.
' ResultCreated: 'Kreiĝis {count} grupoj' ResultDeleted: 'Forigis %d grupojn' ResultUpdated: 'Aktualigis %d grupojn' @@ -326,15 +327,20 @@ eo: DropdownBatchActionsDefault: Agoj HELP: Helpo PERMAGAIN: 'Vin adiaŭis la CMS. Se vi volas denove saluti, enigu salutnomon kaj pasvorton malsupre.' + PERMALREADY: 'Bedaŭrinde vi ne povas aliri tiun parton de la CMS. Se vi volas ensaluti kiel aliulo, faru tion sube.' + PERMDEFAULT: 'Necesas ensaluti por aliri la administran zonon; bonvolu enigi viajn akreditaĵoj sube.' PreviewButton: Antaŭvido REORGANISATIONSUCCESSFUL: 'Sukcese reorganizis la retejan arbon.' SAVEDUP: Konservita. ShowAsList: 'vidigi kiel liston' TooManyPages: 'Tro da paĝoj' ValidationError: 'Validiga eraro' + VersionUnknown: nekonata LeftAndMain_Menu_ss: Hello: Saluton LOGOUT: 'Elsaluti' + ListboxField: + SOURCE_VALIDATION: 'Bonvolu elekti valoron el la listo donita. %s ne estas valida agordo' LoginAttempt: Email: 'Retadreso' IP: 'IP-Adreso' @@ -410,6 +416,7 @@ eo: Toggle: 'Vidigi aranĝa helpo' MemberImportForm: Help1: '

Importi membrojn en CSV-formato (diskomaj valoroj ). Vidigi spertulan uzadon

' + Help2: '

Speciala uzado

  • Eblaj kolumnoj: %s
  • Ekzistantaj uzantoj kongruiĝas laŭ la valoro de sia unika atributo Code, kaj ĝisdatiĝas per eventualaj novaj valoroj el la importita dosiero.
  • Eblas agordi grupojn per la kolumno Groups. Grupoj estas identigeblaj per sia atributo Code, plurobla grupo estu apartigitaj per komo. Ekzistantaj grupaj membrecoj ne vakiĝas.
' ResultCreated: 'Krei {count} membrojn' ResultDeleted: 'Forigis %d membrojn' ResultNone: 'Neniu ŝanĝo' @@ -539,6 +546,8 @@ eo: Print: Presi TableListField_PageControls_ss: OF: de + TextField: + VALIDATEMAXLENGTH: 'La longo de la valoro por {name} devas ne superi {maxLength} signojn' TimeField: VALIDATEFORMAT: 'Bonvole enigu validan horan formaton ({format})' ToggleField: diff --git a/lang/es.yml b/lang/es.yml index 427098d8f..b56ec237f 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -82,6 +82,7 @@ es: CMSSecurity: INVALIDUSER: '

Usuario inválido. Por favor, vuelva a autenticar aquí para continuar.

' LoginMessage: '

Si Ud tiene cualquier trabajo sin guardar puede volver donde lo dejó, iniciando sesión más abajo.

' + SUCCESS: Exito SUCCESSCONTENT: '

Inicio de sesión exitoso. Si Ud no es automáticamente redireccionado, haga clic aquí

' TimedOutTitleAnonymous: 'Expiró su sesión.' TimedOutTitleMember: 'Eh {name}!
Tu sesión expiró.' @@ -259,6 +260,7 @@ es: many_many_Members: Miembros GroupImportForm: Help1: '

Importar uno o más grupos en formato CSV (valores separados por coma). Mostrar uso avanzado

' + Help2: '

Uso avanzado

  • Columnas permitidas: %s
  • Grupos existentes son relacionados con su Código único y actualizados con cualquier nuevo valor desde el archivo importado
  • Jerarquías de grupo pueden ser creadas utilizando la columna ParentCode.
  • Códigos de permiso pueden ser asignados por la columna PermissionCode. Códigos de permisos existentes no son eliminados.
' ResultCreated: 'Creados {count} grupos' ResultDeleted: 'Se eliminaron %d grupos' ResultUpdated: 'Actualizados grupos %d' @@ -290,6 +292,8 @@ es: FROMWEB: 'Desde la web' FindInFolder: 'Buscar en carpeta' IMAGEALT: 'Texto alternativo (alt)' + IMAGEALTTEXT: 'Texto alternativo (alt) - es mostrado si la imagen no puede ser visualizada' + IMAGEALTTEXTDESC: 'Mostrado a los lectores de pantalla o si la imagen no se puede visualizar' IMAGEDIMENSIONS: Dimensiones IMAGEHEIGHTPX: Alto IMAGETITLE: 'Texto del título (tooltip) - para obtener más información acerca de la imagen' @@ -324,7 +328,11 @@ es: DELETED: Borrado DropdownBatchActionsDefault: Acciones HELP: Ayuda + PAGETYPE: 'Tipo de página' PERMAGAIN: 'Ha sido desconectado del CMS. Si quiere volver a entrar, introduzca su nombre de usuario y contraseña a continuación.' + PERMALREADY: 'Lamentablemente no puede acceder a esta parte del CMS. Si quiere entrar como alguien distinto, hágalo a continuación' + PERMDEFAULT: 'Debes estar conectado para acceder al área de administración; por favor ingresa tus datos a continuación' + PLEASESAVE: 'Por favor Guarde la Página: Esta página no se ha podido actualizar porque aún no ha sido salvada' PreviewButton: Vista previa REORGANISATIONSUCCESSFUL: 'Reorganizado el árbol del sitio con éxito.' SAVEDUP: Guardado @@ -412,6 +420,7 @@ es: Toggle: 'Cambiar' MemberImportForm: Help1: '

Importar usuarios en formato CSV (valores separados por coma). Mostrar uso avanzado

' + Help2: '

Uso avanzado

  • Columnas permitidas: %s
  • Usuarios existentes son relacionados con su Código único, y actualizados con cualquier nuevo valor desde el archivo importado.
  • Grupos pueden ser asignados por la columna Groups. Grupos son identificados por su propiedad Code, multiples grupos pueden ser separados por una coma. La pertenencia a grupos existentes no se borra.
' ResultCreated: 'Creados {count} miembros' ResultDeleted: 'Se eliminaron %d miembros' ResultNone: 'No hay cambios' @@ -475,6 +484,7 @@ es: SINGULARNAME: Regla Title: Título PermissionRoleCode: + PLURALNAME: 'Códigos de permiso' PermsError: 'No se puede asignar permisos privilegiados al código "% s" (requiere acceso de administrador)' SINGULARNAME: 'Códigos de las regla de permisos' Permissions: diff --git a/lang/fa_IR.yml b/lang/fa_IR.yml index 41a900443..08e128d9c 100644 --- a/lang/fa_IR.yml +++ b/lang/fa_IR.yml @@ -4,12 +4,18 @@ fa_IR: AssetTableField: DIM: ابعاد FILENAME: نام فايل + FOLDER: پوشه LASTEDIT: 'آخرین تغییرات' OWNER: دارنده SIZE: 'حجم' TITLE: عنوان TYPE: 'نوع' URL: نشانی + AssetUploadField: + EDITALL: 'ویرایش همه' + EDITINFO: 'ویرایش فایل‌ها' + FILES: فایل‌ها + TOTAL: مجموع BBCodeParser: ALIGNEMENT: جاگذاری ALIGNEMENTEXAMPLE: 'به راست' @@ -26,13 +32,29 @@ fa_IR: UNDERLINEEXAMPLE: زیرخط Boolean: ANY: هر + NOANSWER: 'خیر' + YESANSWER: 'بله' + CMSLoadingScreen_ss: + LOADING: بارگذاری... CMSMain: SAVE: نگاهداری + CMSMemberLoginForm: + BUTTONFORGOTPASSWORD: 'رمز عبور را فراموش کرده‌اید؟' + BUTTONLOGOUT: 'خروج' + CMSPageHistoryController_versions_ss: + PREVIEW: 'پیش‌نمایش وب‌سایت' + CMSProfileController: + MENUTITLE: 'پروفایل من' + CMSSecurity: + SUCCESS: موفقیت ChangePasswordEmail_ss: CHANGEPASSWORDTEXT1: 'شما گذرواژه تان را دگرگون کردید برای' EMAIL: ايميل HELLO: درود PASSWORD: كلمه عبور + CheckboxField: + NOANSWER: 'خیر' + YESANSWER: 'بله' ConfirmedPasswordField: SHOWONCLICKTITLE: 'تغيير كلمه عبور' CreditCardField: @@ -40,36 +62,76 @@ fa_IR: FOURTH: چهارم SECOND: دوم THIRD: سوم + CurrencyField: + CURRENCYSYMBOL: ﷼ DataObject: PLURALNAME: 'داده های اشیاء' SINGULARNAME: 'داده اشیاء' + Date: + DAY: روز + DAYS: روز + HOUR: ساعت + HOURS: ساعت + LessThanMinuteAgo: 'کمتر از یک دقیقه' + MIN: دقیقه + MINS: دقیقه + MONTH: ماه + MONTHS: ماه + SEC: ثانیه + SECS: ثانیه + TIMEDIFFAGO: '{difference} پیش' + TIMEDIFFIN: 'در {difference}' + YEAR: سال + YEARS: سال DateField: TODAY: امروز DropdownField: CHOOSE: (گزینش) + Enum: + ANY: هر File: + AviType: 'فایل ویدیو AVI' Content: محتوا + CssType: 'فایل CSS' Filename: نام پرونده + HtlType: 'فایل HTML' + HtmlType: 'فایل HTML' Name: نام PLURALNAME: فايل ها SINGULARNAME: فايل Title: عنوان + Folder: + PLURALNAME: پوشه‌ها + SINGULARNAME: پوشه ForgotPasswordEmail_ss: HELLO: درود TEXT3: برای Form: + SubmitBtnLabel: برو VALIDATIONPASSWORDSDONTMATCH: 'گذرواژه‌ها همانند هم نیستند' VALIDATIONPASSWORDSNOTEMPTY: 'گذرواژه نباید تهی باشد' FormField: NONE: هیچ کدام + GridAction: + DELETE_DESCRIPTION: حذف + Delete: حذف + GridField: + Find: بگرد + ResetFilter: از نو + GridFieldEditButton_ss: + EDIT: ویرایش + GridFieldItemEditView: + Go_back: 'بازگشت' Group: Code: 'كد گروه' DefaultGroupTitleAdministrators: مدیران کل DefaultGroupTitleContentAuthors: 'نویسندگان مطالب' Description: توضحیات Locked: 'بسته شده است؟' + PLURALNAME: گروه‌ها Parent: 'گروه مادر' RolesAddEditLink: 'اضافه/ویرایش وظیفه' + SINGULARNAME: گروه Sort: 'تربیت چیدن' has_many_Permissions: مجوز‌ها many_many_Members: اعضاء @@ -77,8 +139,11 @@ fa_IR: ResultDeleted: 'گروه %d حذف شد' ResultUpdated: 'گروه %d بروز شد' HtmlEditorField: + ADDURL: 'افزودن URL' + BUTTONINSERT: وارد کردن BUTTONINSERTLINK: 'گذاشتن پیوند' BUTTONREMOVELINK: 'برداشتن پیوند' + BUTTONUpdate: به روزرسانی CSSCLASS: 'جاگیری / الگو' EMAIL: 'پست الکترونیک' FILE: پرونده @@ -94,11 +159,25 @@ fa_IR: LINKTO: 'پیوند به' PAGE: برگ URL: نشانی + Image: + PLURALNAME: فایل‌ها + SINGULARNAME: فايل + Image_Cached: + PLURALNAME: فایل‌ها + SINGULARNAME: فايل LeftAndMain: + DELETED: حذف شده HELP: کمک PERMAGAIN: 'شما از سیستم مدیریت محتوا خارج شده اید.اگر میخواهید دوباره وارد شوید نام کاربری و رمز عبور خود را در قسمت زیر وارد کنید' + PreviewButton: پیش‌نمایش + SAVEDUP: ذخیره شده + LeftAndMain_Menu_ss: + Hello: درود + LOGOUT: 'خروج' LoginAttempt: - Email: 'آدرس های ایمیل' + Email: 'نشانی ای‌میل' + IP: 'نشانی IP' + Status: وضعیت Member: BUTTONCHANGEPASSWORD: 'تغییر رمز عبور' BUTTONLOGIN: 'ورود' @@ -116,20 +195,41 @@ fa_IR: SUBJECTPASSWORDCHANGED: 'گذرواژه شما دگرگون شد' SUBJECTPASSWORDRESET: 'پیوند ازنوسازی گذرواژه شما' SURNAME: نام خانوادگی + TIMEFORMAT: 'قالب زمان' YOUROLDPASSWORD: 'رمز عبور قدیمی' belongs_many_many_Groups: گروه‌ها db_LockedOutUntil: 'بسته شده تا ' + db_Password: رمز عبور db_PasswordExpiry: 'تاریخ از میان رفتن گذرواژه' + MemberDatetimeOptionsetField: + Preview: پیش‌نمایش MemberImportForm: ResultDeleted: 'کاربر %d حذف شد' ResultNone: 'تغییری ایجاد نشد' ModelAdmin: DELETE: حذف + ModelAdmin_Tools_ss: + FILTER: پالایش + IMPORT: وارد کردن + ModelSidebar_ss: + IMPORT_TAB_HEADER: وارد کردن + SEARCHLISTINGS: جستجو + MoneyField: + FIELDLABELAMOUNT: مقدار + FIELDLABELCURRENCY: واحد پول NullableField: IsNullLabel: 'خالی است' + Pagination: + Page: صفحه + View: نمایش Permission: AdminGroup: مدیر کل + CMS_ACCESS_CATEGORY: 'دسترسی CMS' FULLADMINRIGHTS: 'توانایی‌های کامل مدیریتی:' + PermissionRole: + PLURALNAME: وظایف + SINGULARNAME: وظیفه + Title: عنوان Permissions: PERMISSIONS_CATEGORY: 'مجوز دسترسی ها و وظایف' PhoneNumberField: @@ -142,14 +242,29 @@ fa_IR: SecurityAdmin: APPLY_ROLES: 'اعمال وظایف به گروه' MEMBERS: کاربران + MENUTITLE: امنیت NEWGROUP: 'گروه تازه' ROLES: وظایف TABROLES: وظایف + Users: کاربران SecurityAdmin_MemberImportForm: BtnImport: 'وارد کردن' + SilverStripeNavigator: + Edit: ویرایش + Mobile: موبایل + Tablet: تبلت + Width: پهنا SiteTree: TABMAIN: اصلی + TableListField: + Print: چاپ ToggleField: MORE: بیشتر + UploadField: + DOEDIT: ذخیره + Dimensions: ابعاد + EDIT: ویرایش + REMOVE: حذف + Saved: ذخیره شده Versioned: has_many_Versions: نسخه ها diff --git a/lang/fr.yml b/lang/fr.yml index 745b53d73..952d44c99 100644 --- a/lang/fr.yml +++ b/lang/fr.yml @@ -251,9 +251,9 @@ fr: CAPTIONTEXT: 'Légende' CSSCLASS: 'Alignement / Style' CSSCLASSCENTER: 'Centré' - CSSCLASSLEFT: 'A gauche, avec texte à la ligne.' + CSSCLASSLEFT: 'À gauche, avec texte autour.' CSSCLASSLEFTALONE: 'Sur la gauche seulement' - CSSCLASSRIGHT: 'a droite, avec texte à la ligne.' + CSSCLASSRIGHT: 'À droite, avec texte autour.' DETAILS: Détails EMAIL: 'Adresse email' FILE: Fichier diff --git a/lang/it.yml b/lang/it.yml index 17627d5cb..f79e319b9 100644 --- a/lang/it.yml +++ b/lang/it.yml @@ -325,7 +325,10 @@ it: DELETED: Eliminato. DropdownBatchActionsDefault: Azioni HELP: Aiuto + PAGETYPE: 'Tipo di pagina' PERMAGAIN: 'Sei stato disconnesso dal CMS. Se desideri autenticarti nuovamente, inserisci qui sotto nome utente e password.' + PERMALREADY: 'Siamo spiacenti, ma non puoi accedere a questa sezione del CMS. Se desideri autenticarti come qualcun altro, fallo qui sotto.' + PERMDEFAULT: 'Devi essere autenticato per accedere all''area amministrativa; Per favore inserisci le tue credenziali qui sotto' PreviewButton: Anteprima REORGANISATIONSUCCESSFUL: 'Albero del sito riorganizzato con successo.' SAVEDUP: Salvato. diff --git a/lang/lt.yml b/lang/lt.yml index 1725617f3..9da6bb6c9 100644 --- a/lang/lt.yml +++ b/lang/lt.yml @@ -328,7 +328,7 @@ lt: DELETED: Ištrinta. DropdownBatchActionsDefault: Veiksmai HELP: Pagalba - PAGETYPE: 'Puslapio tipas:' + PAGETYPE: 'Puslapio tipas' PERMAGAIN: 'Jūs atsijungėte. Norėdami vėl prisijungti, įveskite savo duomenis į žemiau esančius laukelius.' PERMALREADY: 'Deja, bet Jūs negalite patekti į šią TVS dalį. Jeigu norite prisijungti kitu vartotoju, tai atlikite žemiau.' PERMDEFAULT: 'Jūs turite būti prisijungę, norėdami pasiekti administravimo zoną; prašome suvesti prisijungimo duomenis į žemiau esančius laukelius.' diff --git a/lang/sk.yml b/lang/sk.yml index f46181354..91f68461c 100644 --- a/lang/sk.yml +++ b/lang/sk.yml @@ -292,8 +292,6 @@ sk: FROMWEB: 'Z webu' FindInFolder: 'Vyhľadať v priečinku' IMAGEALT: 'Atlernatívny text (alt)' - IMAGEALTTEXT: 'Atlernatívny text (alt) - zobrazí sa ak obrázok nemože byť zobrazený ' - IMAGEALTTEXTDESC: 'Zobrazí sa na obrazovke, ak obrázok nemôže byť zobrazený' IMAGEDIMENSIONS: Rozmery IMAGEHEIGHTPX: Výška IMAGETITLE: 'Text titulky (tooltip) - pre doplňujúce informácie o obrázku' @@ -328,11 +326,9 @@ sk: DELETED: Zmazané. DropdownBatchActionsDefault: Akcie HELP: Pomoc - PAGETYPE: 'Typ stránky:' PERMAGAIN: 'Boli ste odhlásený' PERMALREADY: 'Je mi ľúto, ale nemáte prístup k tejto časti CMS. Ak sa chcete prihlásiť ako niekto iný, urobte tak nižšie' PERMDEFAULT: 'Musíte byť prihlásený/á k prístupu do oblasti administrácie, zadajte vaše prihlasovacie údaje dole, prosím.' - PLEASESAVE: 'Uložte stránku, prosím. Táto stránka nemôže byť aktualizovaná, pretože eště nebola uložená.' PreviewButton: Náhľad REORGANISATIONSUCCESSFUL: 'Strom webu bol reorganizovaný úspešne.' SAVEDUP: Uložené. diff --git a/lang/tr.yml b/lang/tr.yml index 39acb814b..7a564d58a 100644 --- a/lang/tr.yml +++ b/lang/tr.yml @@ -47,6 +47,8 @@ tr: ERRORNOTREC: 'Kullanıcı adı / şifre hatalı' Boolean: ANY: Herhangi + NOANSWER: 'Hayır' + YESANSWER: 'Evet' CMSMain: ACCESSALLINTERFACES: 'Tüm İYS arayüzlerine erişim' SAVE: Kaydet @@ -56,6 +58,9 @@ tr: EMAIL: E-Posta HELLO: Merhaba PASSWORD: Parola + CheckboxField: + NOANSWER: 'Hayır' + YESANSWER: 'Evet' ConfirmedPasswordField: SHOWONCLICKTITLE: 'Parola Değiştir' CreditCardField: @@ -87,6 +92,7 @@ tr: TEXT2: 'şifre sıfırlama linki' TEXT3: için Form: + SubmitBtnLabel: Başla VALIDATIONNOTUNIQUE: 'Girilen değer benzersiz olmalıdır' VALIDATIONPASSWORDSDONTMATCH: 'Şifre tekrarı hatalı' VALIDATIONPASSWORDSNOTEMPTY: 'Şifreler boş geçilemez' diff --git a/lang/zh.yml b/lang/zh.yml index 37ac3a870..7ef8121f2 100644 --- a/lang/zh.yml +++ b/lang/zh.yml @@ -60,6 +60,8 @@ zh: ERRORNOTREC: '那个用户名 / 密码无法被辨认' Boolean: ANY: 任何 + NOANSWER: '不是' + YESANSWER: '是' CMSLoadingScreen_ss: LOADING: 正在载入…… REQUIREJS: 'CMS 要求您启用 JavaScript。' @@ -68,16 +70,35 @@ zh: ACCESSALLINTERFACES: '对所有 CMS 部分的访问' ACCESSALLINTERFACESHELP: '支配更多的特殊访问设置' SAVE: 保存 + CMSMemberLoginForm: + BUTTONFORGOTPASSWORD: '忘记密码?' + BUTTONLOGIN: '重新登录' + BUTTONLOGOUT: '登出' + PASSWORDEXPIRED: '

您的密码已过期。 请选择一个新的。' CMSPageHistoryController_versions_ss: PREVIEW: '网站预览' CMSProfileController: MENUTITLE: '我的个人资料' + CMSSecurity: + INVALIDUSER: '

用户已无效。 请在此继续重新进行身份验证' + LoginMessage: '

如果您有任何未保存的工作,你可以重新登录以回到你未保存的地方。

' + SUCCESS: 成功 + SUCCESSCONTENT: '

登录成功。如果您没有自动重定向点击此处

' + TimedOutTitleAnonymous: '你的登陆超时已过期。' + TimedOutTitleMember: '你好{name}!
你的登陆超时已过期。' ChangePasswordEmail_ss: CHANGEPASSWORDTEXT1: '您的密码已更改为:' CHANGEPASSWORDTEXT2: '现在,您可以使用下列证书来登录了:' EMAIL: 电子邮件 HELLO: 您好 PASSWORD: 密码 + CheckboxField: + NOANSWER: '不是' + YESANSWER: '是' + CheckboxFieldSetField: + SOURCE_VALIDATION: '请选择列表内提供的选项。{value}不是一个有效的选项' + CheckboxSetField: + SOURCE_VALIDATION: '请选择列表内提供的选项。''{value}''不是一个有效的选项' ConfirmedPasswordField: ATLEAST: '密码长度必须至少 {min} 个字符。' BETWEEN: '密码长度必须含 {min} 到 {max} 个字符。' @@ -124,6 +145,7 @@ zh: DropdownField: CHOOSE: (选择) CHOOSESEARCH: '(选择或搜索)' + SOURCE_VALIDATION: '请选择列表内提供的选项。{value}不是一个有效的选项' EmailField: VALIDATION: '请输入一个电子邮件地址' Enum: @@ -171,6 +193,7 @@ zh: TEXT2: '密码重设链接' TEXT3: 为 Form: + CSRF_FAILED_MESSAGE: '似乎是一个技术问题。请点击返回按钮,刷新浏览器,然后再试一次。' FIELDISREQUIRED: '{name} 为必填' SubmitBtnLabel: 前往 VALIDATIONCREDITNUMBER: '请确保您输入了正确的 {number} 信用卡号码' @@ -244,6 +267,8 @@ zh: HtmlEditorField: ADDURL: '添加网址' ADJUSTDETAILSDIMENSIONS: '详情 &amp; 体积' + ANCHORSCANNOTACCESSPAGE: '您不允许访问该页面的内容。' + ANCHORSPAGENOTFOUND: '无法找到该页面。' ANCHORVALUE: 固定 BUTTONADDURL: '添加网址' BUTTONINSERT: 插入 @@ -282,6 +307,7 @@ zh: LINKOPENNEWWIN: '在新窗口中打开链接?' LINKTO: '链接到' PAGE: 页面 + SUBJECT: '电子邮件标题' URL: 网址 URLNOTANOEMBEDRESOURCE: '''{url}'' 该网址无法转换成媒体来源。' UpdateMEDIA: '更新媒体' @@ -299,15 +325,19 @@ zh: DropdownBatchActionsDefault: 动作 HELP: 帮助 PERMAGAIN: '您已经退出 CMS。如果您想再次登录,请在下面输入用户名和密码。' + PERMALREADY: '抱歉,您不能访问这一部分的后台管理。如果您想以不同的身份登录,请在下面进行操作。' PreviewButton: 预览 REORGANISATIONSUCCESSFUL: '重新组织网站地图已成功' SAVEDUP: 已保存。 ShowAsList: '以列表方式展示' TooManyPages: '页面数目过多' ValidationError: '验证错误' + VersionUnknown: 未知 LeftAndMain_Menu_ss: Hello: 您好 LOGOUT: '退出' + ListboxField: + SOURCE_VALIDATION: '请选择列表内提供的选项。%s不是一个有效的选项' LoginAttempt: Email: '电子邮件地址' IP: 'IP 地址' @@ -340,6 +370,7 @@ zh: NEWPASSWORD: '新密码' NoPassword: '该成员无密码' PASSWORD: 密码 + PASSWORDEXPIRED: '您的密码已过期。 请选择一个新的。' PLURALNAME: 成员 REMEMBERME: '下次记住我?' SINGULARNAME: 成员 @@ -445,6 +476,7 @@ zh: SINGULARNAME: 角色 Title: 标题 PermissionRoleCode: + PLURALNAME: '权限角色代码' PermsError: '无法为代码 "%s"分配特权权限(要求具备 ADMIN 访问)' SINGULARNAME: '权限角色代码' Permissions: @@ -510,6 +542,8 @@ zh: Print: 打印 TableListField_PageControls_ss: OF: 的 + TextField: + VALIDATEMAXLENGTH: '{name} 的长度必须至多{maxLength} 个字符。' TimeField: VALIDATEFORMAT: '请输入有效的时间格式 ({format})' ToggleField: From 97f21fddb3c565052f19ee3b35366f48e1e9a36f Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Thu, 29 Oct 2015 11:53:44 +1300 Subject: [PATCH 3/9] [ss-2015-021] Fix rewrite hash links XSS --- tests/view/SSViewerTest.php | 37 ++++++++++++++++++++++++++++------- view/SSTemplateParser.php | 10 +++++++--- view/SSTemplateParser.php.inc | 10 +++++++--- view/SSViewer.php | 6 +++--- 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/tests/view/SSViewerTest.php b/tests/view/SSViewerTest.php index 56882db0f..4c539cad2 100644 --- a/tests/view/SSViewerTest.php +++ b/tests/view/SSViewerTest.php @@ -1,11 +1,30 @@ update('SSViewer', 'source_file_comments', false); + Config::inst()->update('SSViewer_FromString', 'cache_template', false); + $this->oldServer = $_SERVER; } - + + public function tearDown() { + $_SERVER = $this->oldServer; + parent::tearDown(); + } + /** * Tests for {@link Config::inst()->get('SSViewer', 'theme')} for different behaviour * of user defined themes via {@link SiteConfig} and default theme @@ -1160,10 +1179,13 @@ after') $orig = Config::inst()->get('SSViewer', 'rewrite_hash_links'); Config::inst()->update('SSViewer', 'rewrite_hash_links', true); - $_SERVER['REQUEST_URI'] = 'http://path/to/file?foo"onclick="alert(\'xss\')""'; + $_SERVER['HTTP_HOST'] = 'www.mysite.com'; + $_SERVER['REQUEST_URI'] = '//file.com?foo"onclick="alert(\'xss\')""'; // Emulate SSViewer::process() - $base = Convert::raw2att($_SERVER['REQUEST_URI']); + // Note that leading double slashes have been rewritten to prevent these being mis-interepreted + // as protocol-less absolute urls + $base = Convert::raw2att('/file.com?foo"onclick="alert(\'xss\')""'); $tmplFile = TEMP_FOLDER . '/SSViewerTest_testRewriteHashlinks_' . sha1(rand()) . '.ss'; @@ -1231,10 +1253,11 @@ after') $obj = new ViewableData(); $obj->InsertedLink = 'InsertedLink'; $result = $tmpl->process($obj); - $this->assertContains( - '#anchor">InsertedLink +EOC; + $this->assertContains($code, $result); // TODO Fix inline links in PHP mode // $this->assertContains( // ']+href *= *)"#/i', - '\\1"\' . (Config::inst()->get(\'SSViewer\', \'rewrite_hash_links\') ?' . - ' Convert::raw2att( $_SERVER[\'REQUEST_URI\'] ) : "") . - \'#', + '\\1"\' . ' . addcslashes($code, '\\') . ' . \'#', $text ); diff --git a/view/SSTemplateParser.php.inc b/view/SSTemplateParser.php.inc index 6bb7c550d..77333e3d1 100644 --- a/view/SSTemplateParser.php.inc +++ b/view/SSTemplateParser.php.inc @@ -1135,11 +1135,15 @@ class SSTemplateParser extends Parser implements TemplateParser { // TODO: This is pretty ugly & gets applied on all files not just html. I wonder if we can make this // non-dynamically calculated + $code = <<<'EOC' +(\Config::inst()->get('SSViewer', 'rewrite_hash_links') + ? \Convert::raw2att( preg_replace("/^(\\/)+/", "/", $_SERVER['REQUEST_URI'] ) ) + : "") +EOC; + // Because preg_replace replacement requires escaped slashes, addcslashes here $text = preg_replace( '/(]+href *= *)"#/i', - '\\1"\' . (Config::inst()->get(\'SSViewer\', \'rewrite_hash_links\') ?' . - ' Convert::raw2att( $_SERVER[\'REQUEST_URI\'] ) : "") . - \'#', + '\\1"\' . ' . addcslashes($code, '\\') . ' . \'#', $text ); diff --git a/view/SSViewer.php b/view/SSViewer.php index 712a2e302..c9a18885d 100644 --- a/view/SSViewer.php +++ b/view/SSViewer.php @@ -1110,10 +1110,10 @@ class SSViewer implements Flushable { $rewrite = Config::inst()->get('SSViewer', 'rewrite_hash_links'); if($this->rewriteHashlinks && $rewrite) { if(strpos($output, '"; } else { - $thisURLRelativeToBase = Convert::raw2att($_SERVER['REQUEST_URI']); + $thisURLRelativeToBase = Convert::raw2att(preg_replace("/^(\\/)+/", "/", $_SERVER['REQUEST_URI'])); } $output = preg_replace('/(]+href *= *)"#/i', '\\1"' . $thisURLRelativeToBase . '#', $output); From ac4342d81d19201bd8d3814f168240db1ac565fe Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 2 Nov 2015 11:33:04 +1300 Subject: [PATCH 4/9] [ss-2015-022]: XML escape RSSFeed $link parameter --- api/RSSFeed.php | 1 + tests/api/RSSFeedTest.php | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/api/RSSFeed.php b/api/RSSFeed.php index acc81fb02..6c6c569ce 100644 --- a/api/RSSFeed.php +++ b/api/RSSFeed.php @@ -16,6 +16,7 @@ class RSSFeed extends ViewableData { private static $casting = array( "Title" => "Varchar", "Description" => "Varchar", + "Link" => "Varchar", ); /** diff --git a/tests/api/RSSFeedTest.php b/tests/api/RSSFeedTest.php index 0402bd30a..9bbf25927 100644 --- a/tests/api/RSSFeedTest.php +++ b/tests/api/RSSFeedTest.php @@ -43,6 +43,13 @@ class RSSFeedTest extends SapphireTest { $this->assertContains('ItemC AltContent', $content); } + public function testLinkEncoding() { + $list = new ArrayList(); + $rssFeed = new RSSFeed($list, "http://www.example.com/?param1=true¶m2=true", "Test RSS Feed"); + $content = $rssFeed->outputToBrowser(); + $this->assertContains('http://www.example.com/?param1=true&param2=true', $content); + } + public function testRSSFeedWithShortcode() { $list = new ArrayList(); $list->push(new RSSFeedTest_ItemD()); From 53b3bc707bcccb8f5e5060f85ab1398a0975bba2 Mon Sep 17 00:00:00 2001 From: Hamish Friedlander Date: Tue, 10 Nov 2015 11:27:49 +1300 Subject: [PATCH 5/9] [ss-2015-025]: FIX Dont expose class on error --- control/RequestHandler.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/control/RequestHandler.php b/control/RequestHandler.php index 06604c914..e8fe96164 100644 --- a/control/RequestHandler.php +++ b/control/RequestHandler.php @@ -188,14 +188,14 @@ class RequestHandler extends ViewableData { user_error("Non-string method name: " . var_export($action, true), E_USER_ERROR); } - $className = get_class($this); + $classMessage = Director::isLive() ? 'on this handler' : 'on class '.get_class($this); try { if(!$this->hasAction($action)) { - return $this->httpError(404, "Action '$action' isn't available on class $className."); + return $this->httpError(404, "Action '$action' isn't available $classMessage."); } if(!$this->checkAccessAction($action) || in_array(strtolower($action), array('run', 'init'))) { - return $this->httpError(403, "Action '$action' isn't allowed on class $className."); + return $this->httpError(403, "Action '$action' isn't allowed $classMessage."); } $result = $this->handleAction($request, $action); } @@ -232,7 +232,7 @@ class RequestHandler extends ViewableData { // But if we have more content on the URL and we don't know what to do with it, return an error. } else { - return $this->httpError(404, "I can't handle sub-URLs of a $this->class object."); + return $this->httpError(404, "I can't handle sub-URLs $classMessage."); } return $this; @@ -276,10 +276,10 @@ class RequestHandler extends ViewableData { * @return SS_HTTPResponse */ protected function handleAction($request, $action) { - $className = get_class($this); + $classMessage = Director::isLive() ? 'on this handler' : 'on class '.get_class($this); if(!$this->hasMethod($action)) { - return new SS_HTTPResponse("Action '$action' isn't available on class $className.", 404); + return new SS_HTTPResponse("Action '$action' isn't available $classMessage.", 404); } $res = $this->extend('beforeCallActionHandler', $request, $action); From 245e0aae2f5f3eb0acba1d198ad8e196bb224462 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Wed, 11 Nov 2015 15:18:26 +1300 Subject: [PATCH 6/9] [ss-2015-026]: BUG Fix FormField error messages not being encoded safely --- docs/en/04_Changelogs/3.1.16.md | 25 +++++++++++++++++++++++++ forms/Form.php | 12 ++++++++++++ tests/forms/FormTest.php | 16 ++++++++++++++-- 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 docs/en/04_Changelogs/3.1.16.md diff --git a/docs/en/04_Changelogs/3.1.16.md b/docs/en/04_Changelogs/3.1.16.md new file mode 100644 index 000000000..14ce134c9 --- /dev/null +++ b/docs/en/04_Changelogs/3.1.16.md @@ -0,0 +1,25 @@ +# 3.1.16 + +## Upgrading + +FormField validation messages generated by the `Validator` class will now be automatically XML +encoded before being rendered alongside an invalid field. + +If a validation message in a custom `Validator` instance should be rendered as literal HTML, +then the $message parameter for `Validator::validationError` should be passed as an instance +of `HTMLText` + +For example: + + + :::php + class MyCustomValidator extends Validator { + public function php($data) { + $this->validationError( + 'EmailAddress', + DBField::create_field('HTMLText', "Invalid email. Please sign up at this page") + ); + } + } + + diff --git a/forms/Form.php b/forms/Form.php index 3b0f3957b..769e6ece6 100644 --- a/forms/Form.php +++ b/forms/Form.php @@ -1211,6 +1211,18 @@ class Form extends RequestHandler { if($errors){ // Load errors into session and post back $data = $this->getData(); + // Encode validation messages as XML before saving into session state + // As per Form::addErrorMessage() + $errors = array_map(function($error) { + // Encode message as XML by default + if($error['message'] instanceof DBField) { + $error['message'] = $error['message']->forTemplate();; + } else { + $error['message'] = Convert::raw2xml($error['message']); + } + return $error; + }, $errors); + Session::set("FormInfo.{$this->FormName()}.errors", $errors); Session::set("FormInfo.{$this->FormName()}.data", $data); return false; diff --git a/tests/forms/FormTest.php b/tests/forms/FormTest.php index 7773c6725..c893979cf 100644 --- a/tests/forms/FormTest.php +++ b/tests/forms/FormTest.php @@ -226,6 +226,7 @@ class FormTest extends FunctionalTest { 'FormTest_Controller/Form', array( 'Email' => 'invalid', + 'Number' => 'link' // XSS attempt // leaving out "Required" field ) ); @@ -243,7 +244,17 @@ class FormTest extends FunctionalTest { ), 'Required fields show a notification on field when left blank' ); - + + $this->assertContains( + ''<a href="http://mysite.com">link</a>' is not a number, only numbers can be accepted for this field', + $response->getBody(), + "Validation messages are safely XML encoded" + ); + $this->assertNotContains( + 'link', + $response->getBody(), + "Unsafe content is not emitted directly inside the response body" + ); } public function testSessionSuccessMessage() { @@ -630,7 +641,8 @@ class FormTest_Controller extends Controller implements TestOnly { new FieldList( new EmailField('Email'), new TextField('SomeRequiredField'), - new CheckboxSetField('Boxes', null, array('1'=>'one','2'=>'two')) + new CheckboxSetField('Boxes', null, array('1'=>'one','2'=>'two')), + new NumericField('Number') ), new FieldList( new FormAction('doSubmit') From 8eb583cda06f31a8c8c2bc999244a324ee722096 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Mon, 16 Nov 2015 15:08:39 +1300 Subject: [PATCH 7/9] Update translations --- lang/de.yml | 3 +-- lang/es.yml | 4 ---- lang/it.yml | 1 - lang/lt.yml | 2 +- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/lang/de.yml b/lang/de.yml index 037954c17..de6f1f233 100644 --- a/lang/de.yml +++ b/lang/de.yml @@ -293,7 +293,6 @@ de: FindInFolder: 'In Ordner suchen' IMAGEALT: 'Alternativtext (alt)' IMAGEALTTEXT: 'Alternativtext (alt) - erscheint, falls das Bild nicht angezeigt werden kann.' - IMAGEALTTEXTDESC: 'Wird von Screenreadern vorgelesen oder angezeigt, falls das Bild nicht angezeigt werden kann.' IMAGEDIMENSIONS: Dimensionen IMAGEHEIGHTPX: Höhe (px) IMAGETITLE: 'Titeltext (Tooltip) - für zusätzliche Informationen über das Bild' @@ -328,7 +327,7 @@ de: DELETED: Gelöscht. DropdownBatchActionsDefault: Aktionen HELP: Hilfe - PAGETYPE: 'Seitentyp' + PAGETYPE: 'Seitentyp:' PERMAGAIN: 'Sie wurden aus dem System ausgeloggt. Falls Sie sich wieder einloggen möchten, geben Sie bitte Benutzernamen und Passwort im untenstehenden Formular an.' PERMALREADY: 'Leider dürfen Sie diesen Teil des CMS nicht aufrufen. Wenn Sie sich als jemand anderes einloggen wollen, benutzen Sie bitte das nachstehende Formular.' PERMDEFAULT: 'Sie müssen angemeldet sein, um auf diesen Bereich zugreifen zu können. Bitte geben Sie Ihre Zugangsdaten ein.' diff --git a/lang/es.yml b/lang/es.yml index b56ec237f..e2a3c3768 100644 --- a/lang/es.yml +++ b/lang/es.yml @@ -292,8 +292,6 @@ es: FROMWEB: 'Desde la web' FindInFolder: 'Buscar en carpeta' IMAGEALT: 'Texto alternativo (alt)' - IMAGEALTTEXT: 'Texto alternativo (alt) - es mostrado si la imagen no puede ser visualizada' - IMAGEALTTEXTDESC: 'Mostrado a los lectores de pantalla o si la imagen no se puede visualizar' IMAGEDIMENSIONS: Dimensiones IMAGEHEIGHTPX: Alto IMAGETITLE: 'Texto del título (tooltip) - para obtener más información acerca de la imagen' @@ -328,11 +326,9 @@ es: DELETED: Borrado DropdownBatchActionsDefault: Acciones HELP: Ayuda - PAGETYPE: 'Tipo de página' PERMAGAIN: 'Ha sido desconectado del CMS. Si quiere volver a entrar, introduzca su nombre de usuario y contraseña a continuación.' PERMALREADY: 'Lamentablemente no puede acceder a esta parte del CMS. Si quiere entrar como alguien distinto, hágalo a continuación' PERMDEFAULT: 'Debes estar conectado para acceder al área de administración; por favor ingresa tus datos a continuación' - PLEASESAVE: 'Por favor Guarde la Página: Esta página no se ha podido actualizar porque aún no ha sido salvada' PreviewButton: Vista previa REORGANISATIONSUCCESSFUL: 'Reorganizado el árbol del sitio con éxito.' SAVEDUP: Guardado diff --git a/lang/it.yml b/lang/it.yml index f79e319b9..acef00d87 100644 --- a/lang/it.yml +++ b/lang/it.yml @@ -325,7 +325,6 @@ it: DELETED: Eliminato. DropdownBatchActionsDefault: Azioni HELP: Aiuto - PAGETYPE: 'Tipo di pagina' PERMAGAIN: 'Sei stato disconnesso dal CMS. Se desideri autenticarti nuovamente, inserisci qui sotto nome utente e password.' PERMALREADY: 'Siamo spiacenti, ma non puoi accedere a questa sezione del CMS. Se desideri autenticarti come qualcun altro, fallo qui sotto.' PERMDEFAULT: 'Devi essere autenticato per accedere all''area amministrativa; Per favore inserisci le tue credenziali qui sotto' diff --git a/lang/lt.yml b/lang/lt.yml index 9da6bb6c9..1725617f3 100644 --- a/lang/lt.yml +++ b/lang/lt.yml @@ -328,7 +328,7 @@ lt: DELETED: Ištrinta. DropdownBatchActionsDefault: Veiksmai HELP: Pagalba - PAGETYPE: 'Puslapio tipas' + PAGETYPE: 'Puslapio tipas:' PERMAGAIN: 'Jūs atsijungėte. Norėdami vėl prisijungti, įveskite savo duomenis į žemiau esančius laukelius.' PERMALREADY: 'Deja, bet Jūs negalite patekti į šią TVS dalį. Jeigu norite prisijungti kitu vartotoju, tai atlikite žemiau.' PERMDEFAULT: 'Jūs turite būti prisijungę, norėdami pasiekti administravimo zoną; prašome suvesti prisijungimo duomenis į žemiau esančius laukelius.' From 615b2d5563b137e36a32fe005f447a3fa6fb2ff0 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Mon, 16 Nov 2015 15:16:49 +1300 Subject: [PATCH 8/9] Added 3.1.16 changelog --- docs/en/04_Changelogs/3.1.16.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/en/04_Changelogs/3.1.16.md b/docs/en/04_Changelogs/3.1.16.md index 14ce134c9..05981d464 100644 --- a/docs/en/04_Changelogs/3.1.16.md +++ b/docs/en/04_Changelogs/3.1.16.md @@ -23,3 +23,18 @@ For example: } + + +## Change Log + +### Security + + * 2015-11-11 [245e0aa](https://github.com/silverstripe/silverstripe-framework/commit/245e0aae2f5f3eb0acba1d198ad8e196bb224462) Fix FormField error messages not being encoded safely (Damian Mooyman) - See [ss-2015-026](http://www.silverstripe.org/download/security-releases/ss-2015-026) + * 2015-11-09 [53b3bc7](https://github.com/silverstripe/silverstripe-framework/commit/53b3bc707bcccb8f5e5060f85ab1398a0975bba2) Dont expose class on error (Hamish Friedlander) - See [ss-2015-025](http://www.silverstripe.org/download/security-releases/ss-2015-025) + * 2015-11-01 [ac4342d](https://github.com/silverstripe/silverstripe-framework/commit/ac4342d81d19201bd8d3814f168240db1ac565fe) XML escape RSSFeed $link parameter (Ingo Schommer) - See [ss-2015-022](http://www.silverstripe.org/download/security-releases/ss-2015-022) + * 2015-10-28 [97f21fd](https://github.com/silverstripe/silverstripe-framework/commit/97f21fddb3c565052f19ee3b35366f48e1e9a36f) Fix rewrite hash links XSS (Damian Mooyman) - See [ss-2015-021](http://www.silverstripe.org/download/security-releases/ss-2015-021) + +### Bugfixes + + * 2015-10-20 [b857bdf](https://github.com/silverstripe/silverstripe-framework/commit/b857bdf209d79fc623724e68f6a660354cbd5f93) Fix duplicate files being included in case of flush (Damian Mooyman) + * 2015-10-08 [ff6c0a3](https://github.com/silverstripe/silverstripe-cms/commit/ff6c0a3160c5eb3ca624efea6585efb44399dc1c) (v3.1) for #1294 to workaround ErrorPage fatal errors (and undefined var) when publishing. (Patrick Nelson) From 2e6469956fa76513c6c9c70587c806f095ddb6d7 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Mon, 16 Nov 2015 15:20:30 +1300 Subject: [PATCH 9/9] Add 3.1.16-rc1 changelog --- docs/en/04_Changelogs/rc/3.1.16-rc1.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 docs/en/04_Changelogs/rc/3.1.16-rc1.md diff --git a/docs/en/04_Changelogs/rc/3.1.16-rc1.md b/docs/en/04_Changelogs/rc/3.1.16-rc1.md new file mode 100644 index 000000000..c9fde7c24 --- /dev/null +++ b/docs/en/04_Changelogs/rc/3.1.16-rc1.md @@ -0,0 +1,19 @@ +# 3.1.16-rc1 + +See [3.1.16](/changelogs/3.1.16) changelog for more information on what is new in 3.1.16 + + + +## Change Log + +### Security + + * 2015-11-11 [245e0aa](https://github.com/silverstripe/silverstripe-framework/commit/245e0aae2f5f3eb0acba1d198ad8e196bb224462) Fix FormField error messages not being encoded safely (Damian Mooyman) - See [ss-2015-026](http://www.silverstripe.org/download/security-releases/ss-2015-026) + * 2015-11-09 [53b3bc7](https://github.com/silverstripe/silverstripe-framework/commit/53b3bc707bcccb8f5e5060f85ab1398a0975bba2) Dont expose class on error (Hamish Friedlander) - See [ss-2015-025](http://www.silverstripe.org/download/security-releases/ss-2015-025) + * 2015-11-01 [ac4342d](https://github.com/silverstripe/silverstripe-framework/commit/ac4342d81d19201bd8d3814f168240db1ac565fe) XML escape RSSFeed $link parameter (Ingo Schommer) - See [ss-2015-022](http://www.silverstripe.org/download/security-releases/ss-2015-022) + * 2015-10-28 [97f21fd](https://github.com/silverstripe/silverstripe-framework/commit/97f21fddb3c565052f19ee3b35366f48e1e9a36f) Fix rewrite hash links XSS (Damian Mooyman) - See [ss-2015-021](http://www.silverstripe.org/download/security-releases/ss-2015-021) + +### Bugfixes + + * 2015-10-20 [b857bdf](https://github.com/silverstripe/silverstripe-framework/commit/b857bdf209d79fc623724e68f6a660354cbd5f93) Fix duplicate files being included in case of flush (Damian Mooyman) + * 2015-10-08 [ff6c0a3](https://github.com/silverstripe/silverstripe-cms/commit/ff6c0a3160c5eb3ca624efea6585efb44399dc1c) (v3.1) for #1294 to workaround ErrorPage fatal errors (and undefined var) when publishing. (Patrick Nelson)