diff --git a/SafeExamBrowser.Client/CompositionRoot.cs b/SafeExamBrowser.Client/CompositionRoot.cs index e1e08638..56c05701 100644 --- a/SafeExamBrowser.Client/CompositionRoot.cs +++ b/SafeExamBrowser.Client/CompositionRoot.cs @@ -9,8 +9,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; -using System.Reflection; using SafeExamBrowser.Applications; using SafeExamBrowser.Browser; using SafeExamBrowser.Client.Communication; @@ -74,7 +72,6 @@ namespace SafeExamBrowser.Client private ITaskbar taskbar; private ITaskview taskview; private IText text; - private ITextResource textResource; private IUserInterfaceFactory uiFactory; internal IClientController ClientController { get; private set; } @@ -83,18 +80,16 @@ namespace SafeExamBrowser.Client { ValidateCommandLineArguments(); - logger = new Logger(); - nativeMethods = new NativeMethods(); - systemInfo = new SystemInfo(); - InitializeLogging(); InitializeText(); actionCenter = BuildActionCenter(); context = new ClientContext(); messageBox = BuildMessageBox(); + nativeMethods = new NativeMethods(); uiFactory = BuildUserInterfaceFactory(); runtimeProxy = new RuntimeProxy(runtimeHostUri, new ProxyObjectFactory(), ModuleLogger(nameof(RuntimeProxy)), Interlocutor.Client); + systemInfo = new SystemInfo(); taskbar = BuildTaskbar(); taskview = BuildTaskview(); @@ -109,7 +104,7 @@ namespace SafeExamBrowser.Client var operations = new Queue(); - operations.Enqueue(new I18nOperation(logger, text, textResource)); + operations.Enqueue(new I18nOperation(logger, text)); operations.Enqueue(new RuntimeConnectionOperation(context, logger, runtimeProxy, authenticationToken)); operations.Enqueue(new ConfigurationOperation(context, logger, runtimeProxy)); operations.Enqueue(new DelegateOperation(UpdateAppConfig)); @@ -187,17 +182,15 @@ namespace SafeExamBrowser.Client var logFileWriter = new LogFileWriter(new DefaultLogFormatter(), logFilePath); logFileWriter.Initialize(); + + logger = new Logger(); logger.LogLevel = logLevel; logger.Subscribe(logFileWriter); } private void InitializeText() { - var location = Assembly.GetAssembly(typeof(XmlTextResource)).Location; - var path = $@"{Path.GetDirectoryName(location)}\Text.xml"; - - text = new Text(logger); - textResource = new XmlTextResource(path); + text = new Text(ModuleLogger(nameof(Text))); } private IOperation BuildBrowserOperation() diff --git a/SafeExamBrowser.Core.UnitTests/Operations/I18nOperationTests.cs b/SafeExamBrowser.Core.UnitTests/Operations/I18nOperationTests.cs index 2ac31970..44b6a537 100644 --- a/SafeExamBrowser.Core.UnitTests/Operations/I18nOperationTests.cs +++ b/SafeExamBrowser.Core.UnitTests/Operations/I18nOperationTests.cs @@ -9,9 +9,9 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using SafeExamBrowser.Core.Contracts.OperationModel; +using SafeExamBrowser.Core.Operations; using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.Logging.Contracts; -using SafeExamBrowser.Core.Operations; namespace SafeExamBrowser.Core.UnitTests.Operations { @@ -20,7 +20,6 @@ namespace SafeExamBrowser.Core.UnitTests.Operations { private Mock logger; private Mock text; - private Mock textResource; private I18nOperation sut; @@ -29,9 +28,8 @@ namespace SafeExamBrowser.Core.UnitTests.Operations { logger = new Mock(); text = new Mock(); - textResource = new Mock(); - sut = new I18nOperation(logger.Object, text.Object, textResource.Object); + sut = new I18nOperation(logger.Object, text.Object); } [TestMethod] @@ -39,7 +37,7 @@ namespace SafeExamBrowser.Core.UnitTests.Operations { var result = sut.Perform(); - text.Verify(t => t.Initialize(It.Is(r => r == textResource.Object)), Times.Once); + text.Verify(t => t.Initialize(), Times.Once); Assert.AreEqual(OperationResult.Success, result); } @@ -48,7 +46,6 @@ namespace SafeExamBrowser.Core.UnitTests.Operations public void MustDoNothingOnRevert() { sut.Revert(); - text.VerifyNoOtherCalls(); } } diff --git a/SafeExamBrowser.Core/Operations/I18nOperation.cs b/SafeExamBrowser.Core/Operations/I18nOperation.cs index 120eeb84..9eb9cde2 100644 --- a/SafeExamBrowser.Core/Operations/I18nOperation.cs +++ b/SafeExamBrowser.Core/Operations/I18nOperation.cs @@ -6,7 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using System.Globalization; using SafeExamBrowser.Core.Contracts.OperationModel; using SafeExamBrowser.Core.Contracts.OperationModel.Events; using SafeExamBrowser.I18n.Contracts; @@ -15,29 +14,27 @@ using SafeExamBrowser.Logging.Contracts; namespace SafeExamBrowser.Core.Operations { /// - /// An operation to handle the initialization of an module with text data from the default directory. + /// An operation to handle the initialization of an module with text data. /// public class I18nOperation : IOperation { private ILogger logger; private IText text; - private ITextResource textResource; public event ActionRequiredEventHandler ActionRequired { add { } remove { } } public event StatusChangedEventHandler StatusChanged { add { } remove { } } - public I18nOperation(ILogger logger, IText text, ITextResource textResource) + public I18nOperation(ILogger logger, IText text) { this.logger = logger; this.text = text; - this.textResource = textResource; } public OperationResult Perform() { - logger.Info($"Loading default text data (the currently active culture is '{CultureInfo.CurrentCulture.Name}')..."); + logger.Info($"Loading text data..."); - text.Initialize(textResource); + text.Initialize(); return OperationResult.Success; } diff --git a/SafeExamBrowser.I18n.Contracts/IText.cs b/SafeExamBrowser.I18n.Contracts/IText.cs index 9f940e6a..5d001fae 100644 --- a/SafeExamBrowser.I18n.Contracts/IText.cs +++ b/SafeExamBrowser.I18n.Contracts/IText.cs @@ -14,13 +14,12 @@ namespace SafeExamBrowser.I18n.Contracts public interface IText { /// - /// Initializes the text module, e.g. loads text data from the specified text resource. + /// Initializes the text module, i.e. loads text data according to the currently active UI culture. /// - void Initialize(ITextResource resource); + void Initialize(); /// - /// Gets the text associated with the specified key. If the key was not found, a default text indicating - /// that the given key is not configured will be returned. + /// Gets the text associated with the specified key. If the key was not found, an error message indicating the missing key will be returned. /// string Get(TextKey key); } diff --git a/SafeExamBrowser.I18n.Contracts/TextKey.cs b/SafeExamBrowser.I18n.Contracts/TextKey.cs index 776d52d2..2e41005c 100644 --- a/SafeExamBrowser.I18n.Contracts/TextKey.cs +++ b/SafeExamBrowser.I18n.Contracts/TextKey.cs @@ -15,6 +15,7 @@ namespace SafeExamBrowser.I18n.Contracts public enum TextKey { AboutWindow_LicenseInfo, + AboutWindow_Title, Browser_BlockedContentMessage, Browser_BlockedPageButton, Browser_BlockedPageMessage, diff --git a/SafeExamBrowser.I18n.UnitTests/TextTests.cs b/SafeExamBrowser.I18n.UnitTests/TextTests.cs index e19b2769..1fac2d4f 100644 --- a/SafeExamBrowser.I18n.UnitTests/TextTests.cs +++ b/SafeExamBrowser.I18n.UnitTests/TextTests.cs @@ -6,13 +6,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -using System; -using System.Collections.Generic; +using System.Globalization; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.Logging.Contracts; -using SafeExamBrowser.I18n; namespace SafeExamBrowser.I18n.UnitTests { @@ -20,59 +18,29 @@ namespace SafeExamBrowser.I18n.UnitTests public class TextTests { private Mock loggerMock; + private Text sut; [TestInitialize] public void Initialize() { loggerMock = new Mock(); + sut = new Text(loggerMock.Object); } [TestMethod] public void MustNeverReturnNull() { - var sut = new Text(loggerMock.Object); var text = sut.Get((TextKey)(-1)); Assert.IsNotNull(text); } [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] - public void MustNotAllowNullResource() + public void MustNotFailToInitializeWhenDataNotFound() { - var sut = new Text(loggerMock.Object); + CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture; - sut.Initialize(null); - } - - [TestMethod] - public void MustNotFailWhenGettingNullFromResource() - { - var resource = new Mock(); - var sut = new Text(loggerMock.Object); - - resource.Setup(r => r.LoadText()).Returns>(null); - sut.Initialize(resource.Object); - - var text = sut.Get((TextKey)(-1)); - - Assert.IsNotNull(text); - } - - [TestMethod] - public void MustNotFailWhenResourceThrowsException() - { - var resource = new Mock(); - var sut = new Text(loggerMock.Object); - - resource.Setup(r => r.LoadText()).Throws(); - sut.Initialize(resource.Object); - - var text = sut.Get((TextKey)(-1)); - - loggerMock.Verify(l => l.Error(It.IsAny(), It.IsAny()), Times.AtLeastOnce); - - Assert.IsNotNull(text); + sut.Initialize(); } } } diff --git a/SafeExamBrowser.I18n.UnitTests/XmlTextResourceTests.cs b/SafeExamBrowser.I18n.UnitTests/XmlTextResourceTests.cs index 49c959ca..4b0a1ae4 100644 --- a/SafeExamBrowser.I18n.UnitTests/XmlTextResourceTests.cs +++ b/SafeExamBrowser.I18n.UnitTests/XmlTextResourceTests.cs @@ -23,7 +23,8 @@ namespace SafeExamBrowser.I18n.UnitTests { var location = Assembly.GetAssembly(typeof(XmlTextResourceTests)).Location; var path = $@"{Path.GetDirectoryName(location)}\Text_Valid.xml"; - var sut = new XmlTextResource(path); + var stream = new FileStream(path, FileMode.Open, FileAccess.Read); + var sut = new XmlTextResource(stream); var text = sut.LoadText(); @@ -39,7 +40,8 @@ namespace SafeExamBrowser.I18n.UnitTests { var location = Assembly.GetAssembly(typeof(XmlTextResourceTests)).Location; var path = $@"{Path.GetDirectoryName(location)}\Text_Invalid.txt"; - var sut = new XmlTextResource(path); + var stream = new FileStream(path, FileMode.Open, FileAccess.Read); + var sut = new XmlTextResource(stream); sut.LoadText(); } @@ -49,7 +51,8 @@ namespace SafeExamBrowser.I18n.UnitTests { var location = Assembly.GetAssembly(typeof(XmlTextResourceTests)).Location; var path = $@"{Path.GetDirectoryName(location)}\Text_Incompatible.xml"; - var sut = new XmlTextResource(path); + var stream = new FileStream(path, FileMode.Open, FileAccess.Read); + var sut = new XmlTextResource(stream); var text = sut.LoadText(); @@ -62,7 +65,8 @@ namespace SafeExamBrowser.I18n.UnitTests { var location = Assembly.GetAssembly(typeof(XmlTextResourceTests)).Location; var path = $@"{Path.GetDirectoryName(location)}\Text_Valid.xml"; - var sut = new XmlTextResource(path); + var stream = new FileStream(path, FileMode.Open, FileAccess.Read); + var sut = new XmlTextResource(stream); var text = sut.LoadText(); @@ -70,13 +74,6 @@ namespace SafeExamBrowser.I18n.UnitTests Assert.AreEqual(string.Empty, text[TextKey.Notification_LogTooltip]); } - [TestMethod] - [ExpectedException(typeof(ArgumentException))] - public void MustNotAcceptInvalidPath() - { - new XmlTextResource("This is not a valid path"); - } - [TestMethod] [ExpectedException(typeof(ArgumentNullException))] public void MustNotAcceptNullAsPath() @@ -89,7 +86,8 @@ namespace SafeExamBrowser.I18n.UnitTests { var location = Assembly.GetAssembly(typeof(XmlTextResourceTests)).Location; var path = $@"{Path.GetDirectoryName(location)}\Text_Valid.xml"; - var sut = new XmlTextResource(path); + var stream = new FileStream(path, FileMode.Open, FileAccess.Read); + var sut = new XmlTextResource(stream); var text = sut.LoadText(); diff --git a/SafeExamBrowser.I18n/Data/de.xml b/SafeExamBrowser.I18n/Data/de.xml new file mode 100644 index 00000000..7c02d2bd --- /dev/null +++ b/SafeExamBrowser.I18n/Data/de.xml @@ -0,0 +1,465 @@ + + + + Diese Applikation unterliegt den Auflagen der Mozilla Public License, Version 2.0. Safe Exam Browser benutzt die folgenden Frameworks und Drittanbieter-Bibliotheken: + + + Informationen zu Version & Lizenz + + + Inhalt blockiert + + + Zurück zur vorherigen Seite + + + Zugriff auf diese Seite ist nicht erlaubt gemäss der aktiven Konfiguration. + + + Seite blockiert + + + Browser + + + Browser Applikation + + + Entwickler-Konsole + + + Lade herunter... + + + Abgebrochen. + + + Heruntergeladen. + + + Seiten-Zoom + + + Build + + + Abbrechen + + + Fehler beim Laden der Daten! + + + Lade... + + + Bitte Datei zum Öffnen auswählen. + + + Bitte Ordner auswählen. + + + Die ausgewählte Datei existiert bereits! Wollen Sie diese wirklich überschreiben? + + + Überschreiben? + + + Speichern als: + + + Bitte wählen Sie einen Ort zum Speichern der Datei. + + + Bitte wählen Sie einen Ort zum Speichern des Ordners. + + + Auswählen + + + Dateisystem-Zugriff + + + Applikation "%%NAME%%" konnte nicht gefunden werden auf dem System! Bitte geben Sie an, wo die ausführbare Datei "%%EXECUTABLE%%" liegt. + + + Verbotene Applikationen temporär erlauben. Dies gilt nur für die momentan laufenden Instanzen der aktuellen Sitzung! + + + Die unten aufgelisteten, verbotenen Applikationen wurden gestartet und konnten nicht automatisch beendet werden! Bitte wählen Sie eine der verfügbaren Optionen aus und geben Sie das korrekte Passwort ein, um SEB zu entsperren. + + + Safe Exam Browser beenden. WARNUNG: Sie werden keine Möglichkeit haben, Daten zu speichern oder weitere Aktionen auszuführen, SEB wird sofort beendet! + + + SEB GESPERRT + + + Entsperren + + + Immer zuoberst + + + Inhalt automatisch scrollen + + + Applikations-Protokoll + + + Die unten aufgelisteten Applikationen müssen beendet werden bevor eine neue Sitzung gestartet werden kann. Sollen diese nun automatisch beendet werden? + + + Laufende Applikationen erkannt + + + WARNUNG: Ungespeicherte Applikationsdaten können möglicherweise verloren gehen! + + + Ein schwerwiegender Fehler ist aufgetreten! Bitte konsultieren Sie das Applikations-Protokoll für mehr Informationen. SEB wird sich nun beenden... + + + Applikations-Fehler + + + Applikation %%NAME%% konnte nicht initialisiert werden und wird darum nicht verfügbar sein in der neuen Sitzung! Bitte konsultieren Sie das Applikations-Protokoll für mehr Informationen. + + + Applikations-Initialisierung fehlgeschlagen + + + Applikation %%NAME%% konnte nicht gefunden werden auf dem System und wird darum nicht verfügbar sein in der neuen Sitzung! Bitte konsultieren Sie das Applikations-Protokoll für mehr Informationen. + + + Applikation nicht gefunden + + + Die unten aufgelisteten Applikationen konnten nicht beendet werden! Bitte beenden Sie diese manuell und probieren Sie es erneut... + + + Automatisches Beenden fehlgeschlagen + + + Zugriff auf "%%URL%%" is gemäss der aktiven Konfiguration nicht erlaubt. + + + Seite blockiert + + + Die Browser-Applikation hat eine Quit-URL erkannt! Möchten Sie SEB nun beenden? + + + Quit-URL erkannt + + + Abbrechen + + + Die Einrichtung der lokalen Konfiguration ist gescheitert! Bitte konsultieren Sie das Applikations-Protokoll für mehr Informationen. SEB wird sich nun beenden... + + + Konfiguration gescheitert + + + Die lokale Konfiguration wurde gespeichert und wird benutzt wenn Sie SEB das nächste Mal starten. Möchten Sie nun beenden? + + + Konfiguration erfolgreich + + + Konnte neue Konfiguration nicht herunterladen. Bitte versuchen Sie es erneut oder kontaktieren Sie technischen Support. + + + Fehler beim Herunterladen + + + Die Konfigurations-Ressource "%%URI%%" enthält ungültige Daten! + + + Konfigurations-Fehler + + + Sie haben 5 mal das falsche Passwort eingegeben. SEB wird sich nun beenden... + + + Ungültiges Passwort + + + SEB kann nur durch Eingabe des korrekten Passworts beendet werden. + + + Ungültiges Quit-Passwort + + + SEB kann nur durch Eingabe des korrekten Passworts entsperrt werden. + + + Ungültiges Entsperrungs-Passwort + + + Nein + + + Die Konfigurations-Ressource "%%URI%%" wird nicht unterstützt! + + + Konfigurations-Fehler + + + OK + + + Möchten Sie SEB beenden? + + + Beenden? + + + Der Client konnte die Anfrage zum Beenden nicht an die Runtime senden! + + + Fehler beim Beenden + + + Es ist Ihnen nicht erlaubt, SEB zu rekonfigurieren. + + + Rekonfiguration abgelehnt + + + Der Client konnte die Anfrage zur Rekonfiguration nicht an die Runtime senden! + + + Fehler bei der Rekonfiguration + + + Möchten Sie die aktuelle Seite neu laden? + + + Neu laden? + + + Fehler beim Initialisieren des SEB-Service! SEB wird sich nun beenden da der Service als obligatorisch konfiguriert ist. + + + Service nicht verfügbar + + + Fehler beim Initialisieren des SEB-Service! SEB wird mit der Initialisierung fortfahren da der Service als optional konfiguriert ist. + + + Service nicht verfügbar + + + SEB konnte keine neue Sitzung starten! Bitte konsultieren Sie das Applikations-Protokoll für mehr Informationen. + + + Fehler beim Starten der Sitzung + + + Beim Beenden ist ein unerwarteter Fehler aufgetreten! Bitte konsultieren Sie das Applikations-Protokoll für mehr Informationen. + + + Fehler beim Beenden + + + Beim Starten ist ein unerwarteter Fehler aufgetreten! Bitte konsultieren Sie das Applikations-Protokoll für mehr Informationen. + + + Fehler beim Starten + + + Beim Laden der Konfigurations-Ressource "%%URI%%" ist ein unerwarteter Fehler aufgetreten! Bitte konsultieren Sie das Applikations-Protokoll für mehr Informationen. + + + Konfigurations-Fehler + + + Dieser Computer scheint eine virtuelle Maschine zu sein. Die ausgewählte Konfiguration erlaubt es nicht, SEB in einer virtuellen Maschine auszuführen. + + + Virtuelle Maschine erkannt + + + Ja + + + Informationen über SEB + + + Applikations-Protokoll + + + Schliesse Verbindung zur Runtime + + + Lösche Zwischenablage + + + Beende Applikationen + + + Beende Service-Sitzung + + + Initialisiere Applikationen + + + Initialisiere Browser + + + Initialisiere Konfiguration + + + Initialisiere Kiosk-Modus + + + Initialisiere Verbindung zur Runtime + + + Initialisiere Service-Sitzung + + + Initialisiere neue Sitzung + + + Initialisiere Benutzeroberfläche + + + Initialisiere Arbeitsbereich + + + Starte Kommunikations-Host neu + + + Stelle Arbeitsbereich wieder her + + + Beende Kiosk-Modus + + + Starte Client + + + Starte Kommunikations-Host + + + Starte Tastatur-Überwachung + + + Starte Maus-Überwachung + + + Beende Client + + + Beende Kommunikations-Host + + + Beende Tastatur-Überwachung + + + Beende Maus-Überwachung + + + Beende Browser + + + Beende Benutzeroberfläche + + + Validiere Richtlinie für virtuelle Maschinen + + + Warte bis Windows Explorer gestartet ist + + + Warte bis Windows Explorer beendet ist + + + Warte bis Runtime Verbindung trennt + + + Abbrechen + + + Bestätigen + + + Bitte geben Sie das Administrator-Passwort für die lokale Konfiguration ein: + + + Administrator-Passwort erforderlich + + + Bitte geben Sie das Passwort für die lokale Konfiguration ein: + + + Passwort erforderlich + + + Bitte geben Sie das Quit-Passwort ein um SEB zu beenden: + + + Quit-Passwort erforderlich + + + Bitte geben Sie das Passwort für die ausgewählte Konfiguration ein: + + + Passwort erforderlich + + + SEB wird ausgeführt. + + + Sitzung beenden + + + %%NAME%%: %%VOLUME%%% + + + %%NAME%%: Ton aus + + + Klicken um Ton auszuschalten + + + Kein aktives Audio-Gerät gefunden + + + Klicken um Ton einzuschalten + + + Angeschlossen, lade... (%%CHARGE%%%) + + + Aufgeladen (%%CHARGE%%%) + + + Der Akku ist in kritischem Zustand. Bitte schliessen Sie den Computer an eine Stromquelle an! + + + Der Akku nähert sich dem kritischen Zustand. Bitte schliessen Sie den Computer rechtzeitig an eine Stromquelle an... + + + %%HOURS%%h %%MINUTES%%min verbleiben (%%CHARGE%%%) + + + Das aktuelle Tastatur-Layout ist "%%LAYOUT%%" + + + Verbunden mit "%%NAME%%" + + + Verbinde... + + + Getrennt + + + Kein WLAN-Netzwerkadapter verfügbar oder eingestellt + + + Version + + \ No newline at end of file diff --git a/SafeExamBrowser.I18n/Text.xml b/SafeExamBrowser.I18n/Data/en.xml similarity index 98% rename from SafeExamBrowser.I18n/Text.xml rename to SafeExamBrowser.I18n/Data/en.xml index 70e05ee3..ab3c2d1b 100644 --- a/SafeExamBrowser.I18n/Text.xml +++ b/SafeExamBrowser.I18n/Data/en.xml @@ -3,6 +3,9 @@ This application is subject to the terms of the Mozilla Public License, version 2.0. Safe Exam Browser uses the following frameworks and third-party libraries: + + Version & License Information + Content blocked @@ -109,7 +112,7 @@ Running Applications Detected - IMPORTANT: Any unsaved application data might be lost! + WARNING: Any unsaved application data might be lost! An unrecoverable error has occurred! Please consult the log files for more information. SEB will now shut down... @@ -154,7 +157,7 @@ The local client configuration has failed! Please consult the log files for more information. SEB will now shut down... - Client Configuration Error + Configuration Error The client configuration has been saved and will be used when you start SEB the next time. Do you want to quit for now? @@ -247,25 +250,25 @@ Service Unavailable - SEB failed to start a new session! Please consult the log files for more information... + SEB failed to start a new session! Please consult the log files for more information. Session Start Error - An unexpected error occurred during the shutdown procedure! Please consult the log files for more information... + An unexpected error occurred during the shutdown procedure! Please consult the log files for more information. Shutdown Error - An unexpected error occurred during the startup procedure! Please consult the log files for more information... + An unexpected error occurred during the startup procedure! Please consult the log files for more information. Startup Error - An unexpected error occurred while trying to load configuration resource "%%URI%%"! Please consult the log files for more information... + An unexpected error occurred while trying to load configuration resource "%%URI%%"! Please consult the log files for more information. Configuration Error diff --git a/SafeExamBrowser.I18n/SafeExamBrowser.I18n.csproj b/SafeExamBrowser.I18n/SafeExamBrowser.I18n.csproj index adf67d61..a4d0b415 100644 --- a/SafeExamBrowser.I18n/SafeExamBrowser.I18n.csproj +++ b/SafeExamBrowser.I18n/SafeExamBrowser.I18n.csproj @@ -62,10 +62,9 @@ - + Designer - Always - + @@ -77,5 +76,10 @@ SafeExamBrowser.Logging.Contracts + + + Designer + + \ No newline at end of file diff --git a/SafeExamBrowser.I18n/Text.cs b/SafeExamBrowser.I18n/Text.cs index 49cd0704..d3d6b6e4 100644 --- a/SafeExamBrowser.I18n/Text.cs +++ b/SafeExamBrowser.I18n/Text.cs @@ -8,43 +8,69 @@ using System; using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Reflection; using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.Logging.Contracts; namespace SafeExamBrowser.I18n { /// - /// Default implementation of the module. + /// Default implementation of . /// public class Text : IText { - private IDictionary cache = new Dictionary(); private ILogger logger; + private IDictionary text; public Text(ILogger logger) { this.logger = logger; + this.text = new Dictionary(); } public string Get(TextKey key) { - return cache.ContainsKey(key) ? cache[key] : $"Could not find string for key '{key}'!"; + return text.ContainsKey(key) ? text[key] : $"Could not find text for key '{key}'!"; } - public void Initialize(ITextResource resource) + public void Initialize() { - if (resource == null) - { - throw new ArgumentNullException(nameof(resource)); - } - try { - cache = resource.LoadText() ?? new Dictionary(); + var assembly = Assembly.GetAssembly(typeof(Text)); + var data = default(Stream); + var language = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.ToLower(); + var path = $"{typeof(Text).Namespace}.Data"; + var resource = default(ITextResource); + + try + { + logger.Debug($"System language is '{language}', trying to load data..."); + data = assembly.GetManifestResourceStream($"{path}.{language}.xml"); + } + catch (FileNotFoundException) + { + } + + if (data == default(Stream)) + { + logger.Warn($"Could not find data for language '{language}'! Loading default language 'en'..."); + data = assembly.GetManifestResourceStream($"{path}.en.xml"); + } + + using (data) + { + resource = new XmlTextResource(data); + text = resource.LoadText(); + } + + logger.Debug("Data successfully loaded."); } catch (Exception e) { - logger.Error("Failed to load text data from provided resource!", e); + logger.Error("Failed to initialize data!", e); } } } diff --git a/SafeExamBrowser.I18n/XmlTextResource.cs b/SafeExamBrowser.I18n/XmlTextResource.cs index a9a8fbd0..2ad7c279 100644 --- a/SafeExamBrowser.I18n/XmlTextResource.cs +++ b/SafeExamBrowser.I18n/XmlTextResource.cs @@ -15,35 +15,24 @@ using SafeExamBrowser.I18n.Contracts; namespace SafeExamBrowser.I18n { /// - /// Default implementation of to load text data from XML files. + /// Default implementation of an for text data in XML. /// public class XmlTextResource : ITextResource { - private string path; + private Stream data; /// - /// Initializes a new text resource for an XML file located at the specified path. + /// Initializes a new text resource for an XML data stream. /// - /// If the specifed file does not exist. - /// If the given path is null. - public XmlTextResource(string path) + /// If the given stream is null. + public XmlTextResource(Stream data) { - if (path == null) - { - throw new ArgumentNullException(nameof(path)); - } - - if (!File.Exists(path)) - { - throw new ArgumentException("The specified file does not exist!"); - } - - this.path = path; + this.data = data ?? throw new ArgumentNullException(nameof(data)); } public IDictionary LoadText() { - var xml = XDocument.Load(path); + var xml = XDocument.Load(data); var text = new Dictionary(); foreach (var definition in xml.Root.Descendants()) diff --git a/SafeExamBrowser.Runtime/CompositionRoot.cs b/SafeExamBrowser.Runtime/CompositionRoot.cs index e439b2c6..bba6486c 100644 --- a/SafeExamBrowser.Runtime/CompositionRoot.cs +++ b/SafeExamBrowser.Runtime/CompositionRoot.cs @@ -8,8 +8,6 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Reflection; using SafeExamBrowser.Communication.Contracts; using SafeExamBrowser.Communication.Hosts; using SafeExamBrowser.Communication.Proxies; @@ -44,7 +42,6 @@ namespace SafeExamBrowser.Runtime private ILogger logger; private ISystemInfo systemInfo; private IText text; - private ITextResource textResource; internal IRuntimeController RuntimeController { get; private set; } @@ -53,9 +50,6 @@ namespace SafeExamBrowser.Runtime const int FIVE_SECONDS = 5000; const int THIRTY_SECONDS = 30000; - var args = Environment.GetCommandLineArgs(); - var nativeMethods = new NativeMethods(); - logger = new Logger(); systemInfo = new SystemInfo(); @@ -63,7 +57,9 @@ namespace SafeExamBrowser.Runtime InitializeLogging(); InitializeText(); + var args = Environment.GetCommandLineArgs(); var messageBox = new MessageBox(text); + var nativeMethods = new NativeMethods(); var uiFactory = new UserInterfaceFactory(text); var desktopFactory = new DesktopFactory(ModuleLogger(nameof(DesktopFactory))); var explorerShell = new ExplorerShell(ModuleLogger(nameof(ExplorerShell)), nativeMethods); @@ -80,7 +76,7 @@ namespace SafeExamBrowser.Runtime var bootstrapOperations = new Queue(); var sessionOperations = new Queue(); - bootstrapOperations.Enqueue(new I18nOperation(logger, text, textResource)); + bootstrapOperations.Enqueue(new I18nOperation(logger, text)); bootstrapOperations.Enqueue(new CommunicationHostOperation(runtimeHost, logger)); sessionOperations.Enqueue(new SessionInitializationOperation(configuration, logger, runtimeHost, sessionContext)); @@ -176,11 +172,7 @@ namespace SafeExamBrowser.Runtime private void InitializeText() { - var location = Assembly.GetAssembly(typeof(XmlTextResource)).Location; - var path = $@"{Path.GetDirectoryName(location)}\Text.xml"; - - text = new Text(logger); - textResource = new XmlTextResource(path); + text = new Text(ModuleLogger(nameof(Text))); } private IModuleLogger ModuleLogger(string moduleInfo) diff --git a/SafeExamBrowser.UserInterface.Desktop/AboutWindow.xaml b/SafeExamBrowser.UserInterface.Desktop/AboutWindow.xaml index 7341576e..c7c291a1 100644 --- a/SafeExamBrowser.UserInterface.Desktop/AboutWindow.xaml +++ b/SafeExamBrowser.UserInterface.Desktop/AboutWindow.xaml @@ -4,8 +4,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop" - mc:Ignorable="d" Title="Version & License Information" Background="White" Height="350" Width="575" ResizeMode="NoResize" - Icon="./Images/SafeExamBrowser.ico" ShowInTaskbar="False" WindowStartupLocation="CenterScreen"> + mc:Ignorable="d" Background="White" Height="350" Width="575" ResizeMode="NoResize" Icon="./Images/SafeExamBrowser.ico" ShowInTaskbar="False" + WindowStartupLocation="CenterScreen"> diff --git a/SafeExamBrowser.UserInterface.Desktop/AboutWindow.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/AboutWindow.xaml.cs index 21bd3465..88cd7d39 100644 --- a/SafeExamBrowser.UserInterface.Desktop/AboutWindow.xaml.cs +++ b/SafeExamBrowser.UserInterface.Desktop/AboutWindow.xaml.cs @@ -45,8 +45,8 @@ namespace SafeExamBrowser.UserInterface.Desktop private void InitializeAboutWindow() { Closing += (o, args) => closing?.Invoke(); - MainText.Inlines.InsertBefore(MainText.Inlines.FirstInline, new Run(text.Get(TextKey.AboutWindow_LicenseInfo))); + Title = text.Get(TextKey.AboutWindow_Title); VersionInfo.Inlines.Add(new Run($"{text.Get(TextKey.Version)} {appConfig.ProgramInformationalVersion}") { FontSize = 12 }); VersionInfo.Inlines.Add(new LineBreak()); diff --git a/SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml b/SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml index 3c21ceb2..f849e96f 100644 --- a/SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml +++ b/SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml @@ -4,9 +4,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile" - mc:Ignorable="d" - Title="Version & License Information" Background="White" Height="450" Width="675" ResizeMode="NoResize" Icon="./Images/SafeExamBrowser.ico" - FontSize="16" ShowInTaskbar="False" WindowStartupLocation="CenterScreen"> + mc:Ignorable="d" Background="White" Height="450" Width="675" ResizeMode="NoResize" Icon="./Images/SafeExamBrowser.ico" FontSize="16" + ShowInTaskbar="False" WindowStartupLocation="CenterScreen"> diff --git a/SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml.cs b/SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml.cs index 7be03ae3..e294881e 100644 --- a/SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml.cs +++ b/SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml.cs @@ -45,8 +45,8 @@ namespace SafeExamBrowser.UserInterface.Mobile private void InitializeAboutWindow() { Closing += (o, args) => closing?.Invoke(); - MainText.Inlines.InsertBefore(MainText.Inlines.FirstInline, new Run(text.Get(TextKey.AboutWindow_LicenseInfo))); + Title = text.Get(TextKey.AboutWindow_Title); VersionInfo.Inlines.Add(new Run($"{text.Get(TextKey.Version)} {appConfig.ProgramInformationalVersion}")); VersionInfo.Inlines.Add(new LineBreak());