diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml index ddf31c3..15a7e89 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/build_windows.yml @@ -109,12 +109,12 @@ jobs: id: get-exe-filename shell: pwsh run: | - $baseName = (Get-ChildItem -Path dist-installer -Filter *.exe).BaseName + $baseName = (Get-ChildItem -Path installer/dist-installer -Filter *.exe).BaseName $unsignedName = "$baseName-unsigned.exe" # The final name depends on whether this is a release build $finalName = if ('${{ inputs.release }}' -eq 'true') { "$baseName.exe" } else { $unsignedName } # Rename the built file to have the "-unsigned" suffix - Rename-Item -Path "dist-installer\$baseName.exe" -NewName $unsignedName + Rename-Item -Path "installer/dist-installer\$baseName.exe" -NewName $unsignedName echo "unsigned-exe-file-name=$unsignedName" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append echo "final-exe-file-name=$finalName" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append @@ -128,7 +128,7 @@ jobs: endpoint: 'https://wus2.codesigning.azure.net/' trusted-signing-account-name: 'LE-Trusted-Signing-Acct' certificate-profile-name: 'LE-Windows-Certificates' - files-folder: dist-installer + files-folder: installer/dist-installer files-folder-filter: ${{ steps.get-exe-filename.outputs.unsigned-exe-file-name }} file-digest: SHA256 timestamp-rfc3161: 'http://timestamp.acs.microsoft.com' @@ -138,11 +138,10 @@ jobs: if: ${{ inputs.release }} shell: pwsh run: | - # Only for a release, rename the file from "-unsigned.exe" to its final name after signing. - Rename-Item -Path "dist-installer\${{ steps.get-exe-filename.outputs.unsigned-exe-file-name }}" -NewName "${{ steps.get-exe-filename.outputs.final-exe-file-name }}" + Rename-Item -Path "installer/dist-installer\${{ steps.get-exe-filename.outputs.unsigned-exe-file-name }}" -NewName "${{ steps.get-exe-filename.outputs.final-exe-file-name }}" - name: Upload installer artifact uses: actions/upload-artifact@v5 with: name: ${{ steps.get-exe-filename.outputs.final-exe-file-name }} - path: dist-installer/${{ steps.get-exe-filename.outputs.final-exe-file-name }} + path: installer/dist-installer/${{ steps.get-exe-filename.outputs.final-exe-file-name }} diff --git a/.gitignore b/.gitignore index bb0af52..756a0e7 100644 --- a/.gitignore +++ b/.gitignore @@ -136,3 +136,8 @@ whl package kolibrisrc hooks/kolibri_plugins_entrypoints_hook.py +installer/MicrosoftEdgeWebView2RuntimeInstallerX64.exe +installer/nssm.exe +update_report.txt +installer/dist-installer/ +installer/translations/locale/*/*.isl diff --git a/Makefile b/Makefile index 1c21318..dab99de 100644 --- a/Makefile +++ b/Makefile @@ -90,13 +90,13 @@ build-dmg: needs-version .PHONY: webview2 # Download WebView2 runtime installer webview2: - @if [ ! -f MicrosoftEdgeWebView2RuntimeInstallerX64.exe ]; then \ + @if [ ! -f installer/MicrosoftEdgeWebView2RuntimeInstallerX64.exe ]; then \ echo "Downloading WebView2 full installer..."; \ ( \ - trap 'echo "Interrupted. Cleaning up..."; rm -f MicrosoftEdgeWebView2RuntimeInstallerX64.exe; exit 1' INT TERM; \ - wget https://go.microsoft.com/fwlink/?linkid=2124701 -O MicrosoftEdgeWebView2RuntimeInstallerX64.exe || { \ + trap 'echo "Interrupted. Cleaning up..."; rm -f installer/MicrosoftEdgeWebView2RuntimeInstallerX64.exe; exit 1' INT TERM; \ + wget https://go.microsoft.com/fwlink/?linkid=2124701 -O installer/MicrosoftEdgeWebView2RuntimeInstallerX64.exe || { \ echo "\Download failed. Cleaning up..."; \ - rm -f MicrosoftEdgeWebView2RuntimeInstallerX64.exe; \ + rm -f installer/MicrosoftEdgeWebView2RuntimeInstallerX64.exe; \ exit 1; \ } \ ); \ @@ -107,23 +107,23 @@ webview2: .PHONY: nssm # Download NSSM for Windows service management nssm: - @if [ ! -f nssm.exe ]; then \ + @if [ ! -f installer/nssm.exe ]; then \ echo "Downloading NSSM..."; \ ( \ - trap 'echo "Interrupted. Cleaning up..."; rm -f nssm.zip; rm -rf nssm; exit 1' INT TERM; \ - mkdir -p nssm && \ - wget https://nssm.cc/release/nssm-$(NSSM_VERSION).zip -O nssm.zip || { \ + trap 'echo "Interrupted. Cleaning up..."; rm -f installer/nssm.zip; rm -rf installer/nssm; exit 1' INT TERM; \ + mkdir -p installer/nssm && \ + wget https://nssm.cc/release/nssm-$(NSSM_VERSION).zip -O installer/nssm.zip || { \ echo "Download failed. Cleaning up..."; \ - rm -f nssm.zip; rm -rf nssm; \ + rm -f installer/nssm.zip; rm -rf installer/nssm; \ exit 1; \ }; \ - unzip -n nssm.zip -d nssm || { \ + unzip -n installer/nssm.zip -d installer/nssm || { \ echo "Unzip failed. Cleaning up..."; \ - rm -f nssm.zip; rm -rf nssm; \ + rm -f installer/nssm.zip; rm -rf installer/nssm; \ exit 1; \ }; \ - cp nssm/nssm-$(NSSM_VERSION)/win64/nssm.exe . && \ - rm -rf nssm nssm.zip \ + cp installer/nssm/nssm-$(NSSM_VERSION)/win64/nssm.exe installer/ && \ + rm -rf installer/nssm installer/nssm.zip \ ); \ else \ echo "NSSM already present."; \ @@ -131,15 +131,82 @@ nssm: # Windows Installer Build .PHONY: build-installer-windows -build-installer-windows: needs-version nssm webview2 +build-installer-windows: translations-compile needs-version nssm webview2 ifeq ($(OS),Windows_NT) # Assumes Inno Setup is installed in the default location. # MSYS_NO_PATHCONV=1 prevents Git Bash/MINGW from converting the /D flag into a file path. - MSYS_NO_PATHCONV=1 "C:\Program Files (x86)\Inno Setup 6\iscc.exe" /DAppVersion=$(KOLIBRI_VERSION) kolibri.iss + MSYS_NO_PATHCONV=1 "C:\Program Files (x86)\Inno Setup 6\iscc.exe" /DAppVersion=$(KOLIBRI_VERSION) installer/kolibri.iss else @echo "Windows installer can only be built on Windows." endif +INNO_DEFAULT_ISL ?= C:/Program Files (x86)/Inno Setup 6/Default.isl +INNO_LANGUAGES_DIR ?= C:/Program Files (x86)/Inno Setup 6/Languages + +TRANSLATIONS_DIR := installer/translations +LOCALE_DIR := $(TRANSLATIONS_DIR)/locale +TEMPLATE_ISL := $(TRANSLATIONS_DIR)/en.isl +SCRIPT_ISL_TO_PO := $(TRANSLATIONS_DIR)/isl_to_po.py +SCRIPT_PO_TO_ISL := $(TRANSLATIONS_DIR)/po_to_isl.py + +# New Language Target +# Usage: make new-language LANG=es_ES +.PHONY: new-language +new-language: + $(MAKE) guard-LANG + @echo "Scaffolding new PO file for locale '$(LANG)'..." + $(PYTHON_EXEC) $(SCRIPT_ISL_TO_PO) \ + --template $(TEMPLATE_ISL) \ + --output $(LOCALE_DIR)/$(LANG)/messages.po \ + --lang "$(LANG)" \ + --inno-dir "$(INNO_LANGUAGES_DIR)" \ + --no-overwrite + +# Export Source Target (en) +.PHONY: translations-export-source +translations-export-source: + @echo "Exporting master en.isl to locale/en/messages.po (Source)..." + $(PYTHON_EXEC) $(SCRIPT_ISL_TO_PO) \ + --template $(TEMPLATE_ISL) \ + --output $(LOCALE_DIR)/en/messages.po \ + --lang "en" + +# Compile Target (PO -> ISL) +.PHONY: translations-compile +translations-compile: + @echo "Compiling PO files to ISL format..." + @# Loop through directories in translations/locale/ + @for lang_dir in $(LOCALE_DIR)/*; do \ + if [ -d "$$lang_dir" ]; then \ + lang_code=$$(basename "$$lang_dir"); \ + \ + # Skip 'en' because we use the master en.isl template directly \ + if [ "$$lang_code" = "en" ]; then \ + continue; \ + fi; \ + \ + po_file="$$lang_dir/messages.po"; \ + isl_file="$$lang_dir/$${lang_code}.isl"; \ + \ + if [ -f "$$po_file" ]; then \ + echo " -> Processing $$lang_code ..."; \ + $(PYTHON_EXEC) $(SCRIPT_PO_TO_ISL) \ + -t $(TEMPLATE_ISL) \ + -i "$$po_file" \ + -o "$$isl_file" \ + -l "$$lang_code"; \ + fi \ + fi \ + done + +.PHONY: update-translations +update-translations: + @echo "Updating master language file from '$(INNO_DEFAULT_ISL)'..." + $(PYTHON_EXEC) installer/translations/update_from_inno_default.py \ + --new-default "$(INNO_DEFAULT_ISL)" \ + --project-master "$(TEMPLATE_ISL)" + @echo "Update complete. Please review update_report.txt and commit the changes to en.isl." + compile-mo: find src/kolibri_app/locales -name LC_MESSAGES -exec msgfmt {}/wxapp.po -o {}/wxapp.mo \; diff --git a/build_requires.txt b/build_requires.txt index 3a756d7..5bff430 100644 --- a/build_requires.txt +++ b/build_requires.txt @@ -3,3 +3,4 @@ pkginfo PyInstaller==6.16.0 dmgbuild==1.6.5; sys_platform == 'darwin' attrdict==2.0.1 # required to install wxpython +polib==1.2.0 # required for handling .po translation files diff --git a/kolibri.iss b/installer/kolibri.iss similarity index 87% rename from kolibri.iss rename to installer/kolibri.iss index 94f120a..a0a636a 100644 --- a/kolibri.iss +++ b/installer/kolibri.iss @@ -7,7 +7,7 @@ #ifndef AppVersion #error "The AppVersion definition must be passed to the compiler via the command line, e.g., /DAppVersion=x.y.z" #endif -#define SourceDir "dist\" + AppName + "-" + AppVersion +#define SourceDir "..\dist\" + AppName + "-" + AppVersion #define KolibriDataDir "{commonappdata}\kolibri" #define NssmExePath "{app}\nssm\nssm.exe" #define TaskkillExePath "{sys}\taskkill.exe" @@ -38,6 +38,42 @@ ArchitecturesInstallIn64BitMode=x64compatible UninstallDisplayIcon={app}\{#AppExeName} SetupLogging=yes CloseApplicationsFilter={#AppExeName} +ShowLanguageDialog=yes + +[Languages] +Name: "en"; MessagesFile: "translations\en.isl" +; Name: "ar"; MessagesFile: "translations\locale\ar\ar.isl" +; Name: "bg_bg"; MessagesFile: "translations\locale\bg-bg\bg-bg.isl" +; Name: "bn_bd"; MessagesFile: "translations\locale\bn-bd\bn-bd.isl" +Name: "de"; MessagesFile: "translations\locale\de\de.isl" +; Name: "el"; MessagesFile: "translations\locale\el\el.isl" +; Name: "es_es"; MessagesFile: "translations\locale\es-es\es-es.isl" +; Name: "es_419"; MessagesFile: "translations\locale\es-419\es-419.isl" +; Name: "fa"; MessagesFile: "translations\locale\fa\fa.isl" +; Name: "fr_fr"; MessagesFile: "translations\locale\fr-fr\fr-fr.isl" +; Name: "ff_cm"; MessagesFile: "translations\locale\ff-cm\ff-cm.isl" +; Name: "gu_in"; MessagesFile: "translations\locale\gu-in\gu-in.isl" +; Name: "ha"; MessagesFile: "translations\locale\ha\ha.isl" +; Name: "hi_in"; MessagesFile: "translations\locale\hi-in\hi-in.isl" +; Name: "ht"; MessagesFile: "translations\locale\ht\ht.isl" +; Name: "id"; MessagesFile: "translations\locale\id\id.isl" +; Name: "it"; MessagesFile: "translations\locale\it\it.isl" +; Name: "ka"; MessagesFile: "translations\locale\ka\ka.isl" +; Name: "km"; MessagesFile: "translations\locale\km\km.isl" +; Name: "ko"; MessagesFile: "translations\locale\ko\ko.isl" +; Name: "mr"; MessagesFile: "translations\locale\mr\mr.isl" +; Name: "my"; MessagesFile: "translations\locale\my\my.isl" +; Name: "ny"; MessagesFile: "translations\locale\ny\ny.isl" +; Name: "pa"; MessagesFile: "translations\locale\pa\pa.isl" +; Name: "pt_br"; MessagesFile: "translations\locale\pt-br\pt-br.isl" +; Name: "pt_mz"; MessagesFile: "translations\locale\pt-mz\pt-mz.isl" +; Name: "sw_tz"; MessagesFile: "translations\locale\sw-tz\sw-tz.isl" +; Name: "te"; MessagesFile: "translations\locale\te\te.isl" +; Name: "uk"; MessagesFile: "translations\locale\uk\uk.isl" +; Name: "ur_pk"; MessagesFile: "translations\locale\ur-pk\ur-pk.isl" +; Name: "vi"; MessagesFile: "translations\locale\vi\vi.isl" +; Name: "yo"; MessagesFile: "translations\locale\yo\yo.isl" +; Name: "zh_hans"; MessagesFile: "translations\locale\zh-hans\zh-hans.isl" [Registry] ; This registry key is used to detect the installed version for upgrades/repairs. @@ -47,7 +83,7 @@ Root: HKLM; Subkey: "Software\Kolibri"; ValueType: dword; ValueName: "ShowTrayIc Root: HKLM; Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; ValueName: "KolibriTray"; Flags: uninsdeletevalue [Tasks] -Name: "installservice"; Description: "Run Kolibri automatically when the computer starts"; GroupDescription: "Installation Type:"; +Name: "installservice"; Description: "{cm:InstallServiceTask}"; GroupDescription: "{cm:InstallationType}"; Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; [Dirs] @@ -210,14 +246,14 @@ begin begin Log('ERROR: User data migration failed. Robocopy exit code: ' + IntToStr(ResultCode)); // Even if robocopy runs but fails, we should inform the user. - MsgBox('Kolibri was unable to automatically move your user data to the new location. Please move the contents of "' + SourcePath + '" to "' + DestPath + '" manually.', mbError, MB_OK); + MsgBox(FmtMessage(CustomMessage('MigrationFailed'), [SourcePath, DestPath]), mbError, MB_OK); end end else begin // This block runs if robocopy.exe itself could not be found or executed. Log('ERROR: Failed to execute robocopy.exe. Ensure it is in the system PATH. Error code: ' + IntToStr(ResultCode)); - MsgBox('Kolibri was unable to automatically move your user data to the new location. Please move the contents of "' + SourcePath + '" to "' + DestPath + '" manually.', mbError, MB_OK); + MsgBox(FmtMessage(CustomMessage('MigrationFailed'), [SourcePath, DestPath]), mbError, MB_OK); end; end; @@ -234,14 +270,14 @@ begin // if the process fails to launch Log(Format('ERROR: Failed to launch process for "%s". System Error: %s', [Description, SysErrorMessage(ResultCode)])); if not WizardSilent() then - MsgBox(Format('A critical error occurred while trying to run a setup command: %s.'#13#10'The installation cannot continue.', [Description]), mbError, MB_OK); + MsgBox(FmtMessage(CustomMessage('CriticalError'), [Description]), mbError, MB_OK); Abort; end; if ResultCode <> 0 then begin Log(Format('ERROR: Command "%s" failed with a non-zero exit code: %d.', [Description, ResultCode])); if not WizardSilent() then - MsgBox(Format('A command required for setup failed to execute correctly: %s.'#13#10'Error Code: %d'#13#10'The installation cannot continue.', [Description, ResultCode]), mbError, MB_OK); + MsgBox(FmtMessage(CustomMessage('CommandError'), [Description, IntToStr(ResultCode)]), mbError, MB_OK); Abort; end else @@ -305,7 +341,7 @@ begin Log(Format(' -> Installer Version String: "%s"', [InstallerVersionString])); Log(Format(' -> Installed Version String: "%s"', [InstalledVersionString])); if not WizardSilent() then - MsgBox('Could not compare versions due to an invalid version format. Please uninstall the previous version manually and try again.', mbError, MB_OK); + MsgBox(CustomMessage('VersionParseError'), mbError, MB_OK); Result := False; Exit; end; @@ -319,7 +355,7 @@ begin begin Log(Format('Downgrade detected. Installed version %s is newer than installer version %s. Aborting.', [InstalledVersionString, InstallerVersionString])); if not WizardSilent() then - MsgBox(Format('A newer version of {#AppName} (%s) is already installed.' + #13#10#13#10 + 'This installer contains version %s, which is older than the installed version.' + #13#10 + 'The setup will now exit.', [InstalledVersionString, InstallerVersionString]), mbInformation, MB_OK); + MsgBox(FmtMessage(CustomMessage('NewerVersionInstalled'), [InstalledVersionString, InstallerVersionString]), mbInformation, MB_OK); Result := False; end else if VersionDiff = 0 then @@ -327,7 +363,7 @@ begin Log('Same version detected. Proposing a repair/reinstall.'); if not WizardSilent() then begin - if MsgBox('This version of {#AppName} is already installed.' + #13#10#13#10 + 'Do you want to repair the installation by reinstalling it?', mbConfirmation, MB_YESNO) <> IDYES then + if MsgBox(FmtMessage(CustomMessage('SameVersionInstalled'), ['{#AppName}']), mbConfirmation, MB_YESNO) <> IDYES then Result := False; end; end @@ -336,7 +372,7 @@ begin Log('Older version detected. Proposing an upgrade.'); if not WizardSilent() then begin - if MsgBox(Format('An older version of {#AppName} (%s) was detected.' + #13#10#13#10 + 'Do you want to upgrade to version {#AppVersion}?', [InstalledVersionString]), mbConfirmation, MB_YESNO) <> IDYES then + if MsgBox(FmtMessage(CustomMessage('OlderVersionInstalled'), [InstalledVersionString]), mbConfirmation, MB_YESNO) <> IDYES then Result := False; end; end; @@ -527,8 +563,7 @@ begin // Default to NOT deleting user data unless the user explicitly agrees. g_DeleteUserData := False; - if MsgBox('Do you want to completely remove all Kolibri user data?' + #13#10 + - 'This includes all downloaded content, user accounts, and progress, and cannot be undone.', + if MsgBox(CustomMessage('ConfirmUninstallData'), mbConfirmation, MB_YESNO) = IDYES then begin g_DeleteUserData := True; diff --git a/installer/translations/definitions.py b/installer/translations/definitions.py new file mode 100644 index 0000000..6b55c09 --- /dev/null +++ b/installer/translations/definitions.py @@ -0,0 +1,192 @@ +# Map functionality: +# inno_name: The filename of the standard Inno Setup translation (e.g., 'Spanish.isl') +# or just use the name you want to display in the installer's language selection. +# id: The Microsoft Language ID required by Windows, can be found here: +# MS IDs: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c +# font: (Optional) Only required if Segoe UI (Inno 6.6 default) does not support the language. +# International fonts: https://learn.microsoft.com/en-us/windows/apps/design/globalizing/loc-international-fonts +# rtl: (Optional) Set to True for Right-to-Left languages. + +LANG_DEFINITIONS = { + # --- Official Inno Setup Languages --- + "ar": { + "inno_name": "Arabic", + "id": "$0401", + "rtl": True, + "display_name": "العَرَبِيَّة", + }, + "bg-bg": { + "inno_name": "Bulgarian", + "id": "$0402", + "display_name": "Български", + }, + "de": { + "inno_name": "German", + "id": "$0407", + "display_name": "Deutsch", + }, + "en": { + "inno_name": "English", + "id": "$0409", + "display_name": "English", + }, + "es-es": { + "inno_name": "Spanish", + "id": "$040A", + "display_name": "Español (España)", + }, + "fr-fr": { + "inno_name": "French", + "id": "$040C", + "display_name": "Français", + }, + "it": { + "inno_name": "Italian", + "id": "$0410", + "display_name": "Italiano", + }, + "ko": { + "inno_name": "Korean", + "id": "$0412", + "display_name": "한국어", + }, + "pt-br": { + "inno_name": "BrazilianPortuguese", + "id": "$0416", + "display_name": "Português (Brazil)", + }, + "uk": { + "inno_name": "Ukrainian", + "id": "$0422", + "display_name": "Украї́нська мо́ва", + }, + # --- Unofficial Inno Languages --- + "bn-bd": { + "inno_name": "Bengali", + "id": "$0845", + "font": "Nirmala UI", + "display_name": "বাংলা", + }, + "el": { + "inno_name": "Greek", + "id": "$0408", + "display_name": "Ελληνικά", + }, + "fa": { + "inno_name": "Persian", + "id": "$0429", + "rtl": True, + "display_name": "فارسی", + }, + "hi-in": { + "inno_name": "Hindi", + "id": "$0439", + "font": "Nirmala UI", + "display_name": "हिंदी (भारत)", + }, + "id": { + "inno_name": "Indonesian", + "id": "$0421", + "display_name": "Bahasa Indonesia", + }, + "ka": { + "inno_name": "Georgian", + "id": "$0437", + "display_name": "ქართული", + }, + "mr": { + "inno_name": "Marathi", + "id": "$044E", + "font": "Nirmala UI", + "display_name": "मराठी", + }, + "ur-pk": { + "inno_name": "Urdu", + "id": "$0420", + "font": "Nirmala UI", + "rtl": True, + "display_name": "اُردو (پاکستان)", + }, + "vi": { + "inno_name": "Vietnamese", + "id": "$042A", + "display_name": "Tiếng Việt", + }, + "zh-hans": { + "inno_name": "ChineseSimplified", + "id": "$0804", + "font": "Microsoft YaHei UI", + "display_name": "简体中文", + }, + # --- No Inno Translations --- + "es-419": { + "inno_name": "Spanish (Latin America)", + "id": "$580A", + "display_name": "Español", + }, + "ff-cm": { + "inno_name": "Fulah", + "id": "$0467", + "display_name": "Fulfulde Mbororoore", + }, + "gu-in": { + "inno_name": "Gujarati", + "id": "$0447", + "font": "Nirmala UI", + "display_name": "ગુજરાતી", + }, + "ha": { + "inno_name": "Hausa", + "id": "$0468", + "display_name": "Hausa", + }, + "ht": { + "inno_name": "Haitian Creole", + "id": "$1000", + "display_name": "Kreyòl Ayisyen", + }, + "km": { + "inno_name": "Khmer", + "id": "$0453", + "font": "Leelawadee UI", + "display_name": "ភាសាខ្មែរ", + }, + "my": { + "inno_name": "Burmese", + "id": "$0455", + "font": "Myanmar Text", + "display_name": "ဗမာစာ", + }, + "ny": { + "inno_name": "Chichewa", + "id": "$1000", + "display_name": "Chinyanja", + }, + "pa": { + "inno_name": "Punjabi", + "id": "$0446", + "font": "Nirmala UI", + "display_name": "ਪੰਜਾਬੀ", + }, + "pt-mz": { + "inno_name": "Portuguese (Mozambique)", + "id": "$0816", + "display_name": "Português (Moçambique)", + }, + "sw-tz": { + "inno_name": "Swahili", + "id": "$1000", + "display_name": "Kiswahili", + }, + "te": { + "inno_name": "Telugu", + "id": "$044A", + "font": "Nirmala UI", + "display_name": "తెలుగు", + }, + "yo": { + "inno_name": "Yoruba", + "id": "$046A", + "display_name": "Yorùbá", + }, +} diff --git a/installer/translations/en.isl b/installer/translations/en.isl new file mode 100644 index 0000000..dfcd100 --- /dev/null +++ b/installer/translations/en.isl @@ -0,0 +1,302 @@ +[LangOptions] +languagecodepage=0 +LanguageName=English +LanguageID=$0409 + +[Messages] +SetupAppTitle=Setup +SetupWindowTitle=Setup - %1 +UninstallAppTitle=Uninstall +UninstallAppFullTitle=%1 Uninstall +InformationTitle=Information +ConfirmTitle=Confirm +ErrorTitle=Error +SetupLdrStartupMessage=This will install %1. Do you wish to continue? +LdrCannotCreateTemp=Unable to create a temporary file. Setup aborted +LdrCannotExecTemp=Unable to execute file in the temporary directory. Setup aborted +HelpTextNote= +LastErrorMessage=%1.%n%nError %2: %3 +SetupFileMissing=The file %1 is missing from the installation directory. Please correct the problem or obtain a new copy of the program. +SetupFileCorrupt=The setup files are corrupted. Please obtain a new copy of the program. +SetupFileCorruptOrWrongVer=The setup files are corrupted, or are incompatible with this version of Setup. Please correct the problem or obtain a new copy of the program. +InvalidParameter=An invalid parameter was passed on the command line:%n%n%1 +SetupAlreadyRunning=Setup is already running. +WindowsVersionNotSupported=This program does not support the version of Windows your computer is running. +WindowsServicePackRequired=This program requires %1 Service Pack %2 or later. +NotOnThisPlatform=This program will not run on %1. +OnlyOnThisPlatform=This program must be run on %1. +OnlyOnTheseArchitectures=This program can only be installed on versions of Windows designed for the following processor architectures:%n%n%1 +WinVersionTooLowError=This program requires %1 version %2 or later. +WinVersionTooHighError=This program cannot be installed on %1 version %2 or later. +AdminPrivilegesRequired=You must be logged in as an administrator when installing this program. +PowerUserPrivilegesRequired=You must be logged in as an administrator or as a member of the Power Users group when installing this program. +SetupAppRunningError=Setup has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit. +UninstallAppRunningError=Uninstall has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit. +PrivilegesRequiredOverrideTitle=Select Setup Install Mode +PrivilegesRequiredOverrideInstruction=Select install mode +PrivilegesRequiredOverrideText1=%1 can be installed for all users (requires administrative privileges), or for you only. +PrivilegesRequiredOverrideText2=%1 can be installed for you only, or for all users (requires administrative privileges). +PrivilegesRequiredOverrideAllUsers=Install for &all users +PrivilegesRequiredOverrideAllUsersRecommended=Install for &all users (recommended) +PrivilegesRequiredOverrideCurrentUser=Install for &me only +PrivilegesRequiredOverrideCurrentUserRecommended=Install for &me only (recommended) +ErrorCreatingDir=Setup was unable to create the directory "%1" +ErrorTooManyFilesInDir=Unable to create a file in the directory "%1" because it contains too many files +ExitSetupTitle=Exit Setup +ExitSetupMessage=Setup is not complete. If you exit now, the program will not be installed.%n%nYou may run Setup again at another time to complete the installation.%n%nExit Setup? +AboutSetupMenuItem=&About Setup... +AboutSetupTitle=About Setup +AboutSetupMessage=%1 version %2%n%3%n%n%1 home page:%n%4 +AboutSetupNote= +TranslatorNote= +ButtonBack=< &Back +ButtonNext=&Next > +ButtonInstall=&Install +ButtonOK=OK +ButtonCancel=Cancel +ButtonYes=&Yes +ButtonYesToAll=Yes to &All +ButtonNo=&No +ButtonNoToAll=N&o to All +ButtonFinish=&Finish +ButtonBrowse=&Browse... +ButtonWizardBrowse=B&rowse... +ButtonNewFolder=&Make New Folder +SelectLanguageTitle=Select Setup Language +SelectLanguageLabel=Select the language to use during the installation. +ClickNext=Click Next to continue, or Cancel to exit Setup. +BeveledLabel= +BrowseDialogTitle=Browse For Folder +BrowseDialogLabel=Select a folder in the list below, then click OK. +NewFolderName=New Folder +WelcomeLabel1=Welcome to the [name] Setup Wizard +WelcomeLabel2=This will install [name/ver] on your computer.%n%nIt is recommended that you close all other applications before continuing. +WizardPassword=Password +PasswordLabel1=This installation is password protected. +PasswordLabel3=Please provide the password, then click Next to continue. Passwords are case-sensitive. +PasswordEditLabel=&Password: +IncorrectPassword=The password you entered is not correct. Please try again. +WizardLicense=License Agreement +LicenseLabel=Please read the following important information before continuing. +LicenseLabel3=Please read the following License Agreement. You must accept the terms of this agreement before continuing with the installation. +LicenseAccepted=I &accept the agreement +LicenseNotAccepted=I &do not accept the agreement +WizardInfoBefore=Information +InfoBeforeLabel=Please read the following important information before continuing. +InfoBeforeClickLabel=When you are ready to continue with Setup, click Next. +WizardInfoAfter=Information +InfoAfterLabel=Please read the following important information before continuing. +InfoAfterClickLabel=When you are ready to continue with Setup, click Next. +WizardUserInfo=User Information +UserInfoDesc=Please enter your information. +UserInfoName=&User Name: +UserInfoOrg=&Organization: +UserInfoSerial=&Serial Number: +UserInfoNameRequired=You must enter a name. +WizardSelectDir=Select Destination Location +SelectDirDesc=Where should [name] be installed? +SelectDirLabel3=Setup will install [name] into the following folder. +SelectDirBrowseLabel=To continue, click Next. If you would like to select a different folder, click Browse. +DiskSpaceGBLabel=At least [gb] GB of free disk space is required. +DiskSpaceMBLabel=At least [mb] MB of free disk space is required. +CannotInstallToNetworkDrive=Setup cannot install to a network drive. +CannotInstallToUNCPath=Setup cannot install to a UNC path. +InvalidPath=You must enter a full path with drive letter; for example:%n%nC:\APP%n%nor a UNC path in the form:%n%n\\server\share +InvalidDrive=The drive or UNC share you selected does not exist or is not accessible. Please select another. +DiskSpaceWarningTitle=Not Enough Disk Space +DiskSpaceWarning=Setup requires at least %1 KB of free space to install, but the selected drive only has %2 KB available.%n%nDo you want to continue anyway? +DirNameTooLong=The folder name or path is too long. +InvalidDirName=The folder name is not valid. +BadDirName32=Folder names cannot include any of the following characters:%n%n%1 +DirExistsTitle=Folder Exists +DirExists=The folder:%n%n%1%n%nalready exists. Would you like to install to that folder anyway? +DirDoesntExistTitle=Folder Does Not Exist +DirDoesntExist=The folder:%n%n%1%n%ndoes not exist. Would you like the folder to be created? +WizardSelectComponents=Select Components +SelectComponentsDesc=Which components should be installed? +SelectComponentsLabel2=Select the components you want to install; clear the components you do not want to install. Click Next when you are ready to continue. +FullInstallation=Full installation +CompactInstallation=Compact installation +CustomInstallation=Custom installation +NoUninstallWarningTitle=Components Exist +NoUninstallWarning=Setup has detected that the following components are already installed on your computer:%n%n%1%n%nDeselecting these components will not uninstall them.%n%nWould you like to continue anyway? +ComponentSize1=%1 KB +ComponentSize2=%1 MB +ComponentsDiskSpaceGBLabel=Current selection requires at least [gb] GB of disk space. +ComponentsDiskSpaceMBLabel=Current selection requires at least [mb] MB of disk space. +WizardSelectTasks=Select Additional Tasks +SelectTasksDesc=Which additional tasks should be performed? +SelectTasksLabel2=Select the additional tasks you would like Setup to perform while installing [name], then click Next. +WizardSelectProgramGroup=Select Start Menu Folder +SelectStartMenuFolderDesc=Where should Setup place the program's shortcuts? +SelectStartMenuFolderLabel3=Setup will create the program's shortcuts in the following Start Menu folder. +SelectStartMenuFolderBrowseLabel=To continue, click Next. If you would like to select a different folder, click Browse. +MustEnterGroupName=You must enter a folder name. +GroupNameTooLong=The folder name or path is too long. +InvalidGroupName=The folder name is not valid. +BadGroupName=The folder name cannot include any of the following characters:%n%n%1 +NoProgramGroupCheck2=&Don't create a Start Menu folder +WizardReady=Ready to Install +ReadyLabel1=Setup is now ready to begin installing [name] on your computer. +ReadyLabel2a=Click Install to continue with the installation, or click Back if you want to review or change any settings. +ReadyLabel2b=Click Install to continue with the installation. +ReadyMemoUserInfo=User information: +ReadyMemoDir=Destination location: +ReadyMemoType=Setup type: +ReadyMemoComponents=Selected components: +ReadyMemoGroup=Start Menu folder: +ReadyMemoTasks=Additional tasks: +DownloadingLabel2=Downloading files... +ButtonStopDownload=&Stop download +StopDownload=Are you sure you want to stop the download? +ErrorDownloadAborted=Download aborted +ErrorDownloadFailed=Download failed: %1 %2 +ErrorDownloadSizeFailed=Getting size failed: %1 %2 +ErrorProgress=Invalid progress: %1 of %2 +ErrorFileSize=Invalid file size: expected %1, found %2 +ExtractingLabel=Extracting files... +ButtonStopExtraction=&Stop extraction +StopExtraction=Are you sure you want to stop the extraction? +ErrorExtractionAborted=Extraction aborted +ErrorExtractionFailed=Extraction failed: %1 +ArchiveIncorrectPassword=The password is incorrect +ArchiveIsCorrupted=The archive is corrupted +ArchiveUnsupportedFormat=The archive format is unsupported +WizardPreparing=Preparing to Install +PreparingDesc=Setup is preparing to install [name] on your computer. +PreviousInstallNotCompleted=The installation/removal of a previous program was not completed. You will need to restart your computer to complete that installation.%n%nAfter restarting your computer, run Setup again to complete the installation of [name]. +CannotContinue=Setup cannot continue. Please click Cancel to exit. +ApplicationsFound=The following applications are using files that need to be updated by Setup. It is recommended that you allow Setup to automatically close these applications. +ApplicationsFound2=The following applications are using files that need to be updated by Setup. It is recommended that you allow Setup to automatically close these applications. After the installation has completed, Setup will attempt to restart the applications. +CloseApplications=&Automatically close the applications +DontCloseApplications=&Do not close the applications +ErrorCloseApplications=Setup was unable to automatically close all applications. It is recommended that you close all applications using files that need to be updated by Setup before continuing. +PrepareToInstallNeedsRestart=Setup must restart your computer. After restarting your computer, run Setup again to complete the installation of [name].%n%nWould you like to restart now? +WizardInstalling=Installing +InstallingLabel=Please wait while Setup installs [name] on your computer. +FinishedHeadingLabel=Completing the [name] Setup Wizard +FinishedLabelNoIcons=Setup has finished installing [name] on your computer. +FinishedLabel=Setup has finished installing [name] on your computer. The application may be launched by selecting the installed shortcuts. +ClickFinish=Click Finish to exit Setup. +FinishedRestartLabel=To complete the installation of [name], Setup must restart your computer. Would you like to restart now? +FinishedRestartMessage=To complete the installation of [name], Setup must restart your computer.%n%nWould you like to restart now? +ShowReadmeCheck=Yes, I would like to view the README file +YesRadio=&Yes, restart the computer now +NoRadio=&No, I will restart the computer later +RunEntryExec=Run %1 +RunEntryShellExec=View %1 +ChangeDiskTitle=Setup Needs the Next Disk +SelectDiskLabel2=Please insert Disk %1 and click OK.%n%nIf the files on this disk can be found in a folder other than the one displayed below, enter the correct path or click Browse. +PathLabel=&Path: +FileNotInDir2=The file "%1" could not be located in "%2". Please insert the correct disk or select another folder. +SelectDirectoryLabel=Please specify the location of the next disk. +SetupAborted=Setup was not completed.%n%nPlease correct the problem and run Setup again. +AbortRetryIgnoreSelectAction=Select action +AbortRetryIgnoreRetry=&Try again +AbortRetryIgnoreIgnore=&Ignore the error and continue +AbortRetryIgnoreCancel=Cancel installation +RetryCancelSelectAction=Select action +RetryCancelRetry=&Try again +RetryCancelCancel=Cancel +StatusClosingApplications=Closing applications... +StatusCreateDirs=Creating directories... +StatusExtractFiles=Extracting files... +StatusDownloadFiles=Downloading files... +StatusCreateIcons=Creating shortcuts... +StatusCreateIniEntries=Creating INI entries... +StatusCreateRegistryEntries=Creating registry entries... +StatusRegisterFiles=Registering files... +StatusSavingUninstall=Saving uninstall information... +StatusRunProgram=Finishing installation... +StatusRestartingApplications=Restarting applications... +StatusRollback=Rolling back changes... +ErrorInternal2=Internal error: %1 +ErrorFunctionFailedNoCode=%1 failed +ErrorFunctionFailed=%1 failed; code %2 +ErrorFunctionFailedWithMessage=%1 failed; code %2.%n%3 +ErrorExecutingProgram=Unable to execute file:%n%1 +ErrorRegOpenKey=Error opening registry key:%n%1\%2 +ErrorRegCreateKey=Error creating registry key:%n%1\%2 +ErrorRegWriteKey=Error writing to registry key:%n%1\%2 +ErrorIniEntry=Error creating INI entry in file "%1". +FileAbortRetryIgnoreSkipNotRecommended=&Skip this file (not recommended) +FileAbortRetryIgnoreIgnoreNotRecommended=&Ignore the error and continue (not recommended) +SourceIsCorrupted=The source file is corrupted +SourceDoesntExist=The source file "%1" does not exist +SourceVerificationFailed=Verification of the source file failed: %1 +VerificationSignatureDoesntExist=The signature file "%1" does not exist +VerificationSignatureInvalid=The signature file "%1" is invalid +VerificationKeyNotFound=The signature file "%1" uses an unknown key +VerificationFileNameIncorrect=The name of the file is incorrect +VerificationFileTagIncorrect=The tag of the file is incorrect +VerificationFileSizeIncorrect=The size of the file is incorrect +VerificationFileHashIncorrect=The hash of the file is incorrect +ExistingFileReadOnly2=The existing file could not be replaced because it is marked read-only. +ExistingFileReadOnlyRetry=&Remove the read-only attribute and try again +ExistingFileReadOnlyKeepExisting=&Keep the existing file +ErrorReadingExistingDest=An error occurred while trying to read the existing file: +FileExistsSelectAction=Select action +FileExists2=The file already exists. +FileExistsOverwriteExisting=&Overwrite the existing file +FileExistsKeepExisting=&Keep the existing file +FileExistsOverwriteOrKeepAll=&Do this for the next conflicts +ExistingFileNewerSelectAction=Select action +ExistingFileNewer2=The existing file is newer than the one Setup is trying to install. +ExistingFileNewerOverwriteExisting=&Overwrite the existing file +ExistingFileNewerKeepExisting=&Keep the existing file (recommended) +ExistingFileNewerOverwriteOrKeepAll=&Do this for the next conflicts +ErrorChangingAttr=An error occurred while trying to change the attributes of the existing file: +ErrorCreatingTemp=An error occurred while trying to create a file in the destination directory: +ErrorReadingSource=An error occurred while trying to read the source file: +ErrorCopying=An error occurred while trying to copy a file: +ErrorDownloading=An error occurred while trying to download a file: +ErrorExtracting=An error occurred while trying to extract an archive: +ErrorReplacingExistingFile=An error occurred while trying to replace the existing file: +ErrorRestartReplace=RestartReplace failed: +ErrorRenamingTemp=An error occurred while trying to rename a file in the destination directory: +ErrorRegisterServer=Unable to register the DLL/OCX: %1 +ErrorRegSvr32Failed=RegSvr32 failed with exit code %1 +ErrorRegisterTypeLib=Unable to register the type library: %1 +UninstallDisplayNameMark=%1 (%2) +UninstallDisplayNameMarks=%1 (%2, %3) +UninstallDisplayNameMark32Bit=32-bit +UninstallDisplayNameMark64Bit=64-bit +UninstallDisplayNameMarkAllUsers=All users +UninstallDisplayNameMarkCurrentUser=Current user +ErrorOpeningReadme=An error occurred while trying to open the README file. +ErrorRestartingComputer=Setup was unable to restart the computer. Please do this manually. +UninstallNotFound=File "%1" does not exist. Cannot uninstall. +UninstallOpenError=File "%1" could not be opened. Cannot uninstall +UninstallUnsupportedVer=The uninstall log file "%1" is in a format not recognized by this version of the uninstaller. Cannot uninstall +UninstallUnknownEntry=An unknown entry (%1) was encountered in the uninstall log +ConfirmUninstall=Are you sure you want to completely remove %1 and all of its components? +UninstallOnlyOnWin64=This installation can only be uninstalled on 64-bit Windows. +OnlyAdminCanUninstall=This installation can only be uninstalled by a user with administrative privileges. +UninstallStatusLabel=Please wait while %1 is removed from your computer. +UninstalledAll=%1 was successfully removed from your computer. +UninstalledMost=%1 uninstall complete.%n%nSome elements could not be removed. These can be removed manually. +UninstalledAndNeedsRestart=To complete the uninstallation of %1, your computer must be restarted.%n%nWould you like to restart now? +UninstallDataCorrupted="%1" file is corrupted. Cannot uninstall +ConfirmDeleteSharedFileTitle=Remove Shared File? +ConfirmDeleteSharedFile2=The system indicates that the following shared file is no longer in use by any programs. Would you like for Uninstall to remove this shared file?%n%nIf any programs are still using this file and it is removed, those programs may not function properly. If you are unsure, choose No. Leaving the file on your system will not cause any harm. +SharedFileNameLabel=File name: +SharedFileLocationLabel=Location: +WizardUninstalling=Uninstall Status +StatusUninstalling=Uninstalling %1... +ShutdownBlockReasonInstallingApp=Installing %1. +ShutdownBlockReasonUninstallingApp=Uninstalling %1. + +[CustomMessages] +installservicetask=Run Kolibri automatically when the computer starts +newerversioninstalled=A newer version of {#AppName} (%1) is already installed. This installer contains version %2, which is older. The setup will now exit. +sameversioninstalled=This version of %1 is already installed. Do you want to repair the installation by reinstalling it? +olderversioninstalled=An older version of {#AppName} (%1) was detected. Do you want to upgrade to version {#AppVersion}? +confirmuninstalldata=Do you want to completely remove all Kolibri user data? This includes all downloaded content, user accounts, and progress, and cannot be undone. +criticalerror=A critical error occurred while trying to run a setup command: %1. The installation cannot continue. +commanderror=A command required for setup failed to execute correctly: %1. Error Code: %2. The installation cannot continue. +versionparseerror=Could not compare versions due to an invalid version format. Please uninstall the previous version manually and try again. +migrationfailed=The installer failed to migrate user data from the old location (%1) to the new location (%2). Your data has not been moved. Please contact support for assistance. +createdesktopicon=Create a &desktop icon +additionalicons=Additional icons: +launchprogram=Launch %1 +installationtype=Installation Type: diff --git a/installer/translations/isl_to_po.py b/installer/translations/isl_to_po.py new file mode 100644 index 0000000..ce119ae --- /dev/null +++ b/installer/translations/isl_to_po.py @@ -0,0 +1,142 @@ +import argparse +import configparser +import os +import sys +from datetime import datetime +from pathlib import Path + +import polib +from definitions import LANG_DEFINITIONS + + +def resolve_input_file(locale_code, inno_dir, direct_input): + """ + Determines the path to the translation file (e.g., es_ES.isl). + Returns None if generating the source (en) or if file not found. + """ + # Case 1: Direct file path provided + if direct_input: + return direct_input + + # Case 2: Auto-lookup based on directory and definitions + if inno_dir and locale_code in LANG_DEFINITIONS: + inno_name = LANG_DEFINITIONS[locale_code]["inno_name"] + candidate = Path(inno_dir) / f"{inno_name}.isl" + if candidate.exists(): + print(f" -> Found standard Inno Setup translations: {candidate}") + return str(candidate) + else: + print( + f" -> Warning: Standard file '{inno_name}.isl' not found in {inno_dir}." + ) + + return None + + +def main( + template_path, + output_path, + locale_code, + input_path=None, + inno_dir=None, + no_overwrite=False, +): + encoding = "utf-8-sig" + + if no_overwrite and os.path.exists(output_path): + print(f"Error: The file '{output_path}' already exists.") + print("Aborting to prevent overwriting existing translations.") + sys.exit(1) + + # Resolve the secondary file (Translations) + translated_file_path = resolve_input_file(locale_code, inno_dir, input_path) + + # Read English Template (Keys) + template_config = configparser.ConfigParser(interpolation=None) + template_config.optionxform = str + template_config.read(template_path, encoding=encoding) + + # Read Translated File (Values) - if it exists + translated_config = configparser.ConfigParser(interpolation=None) + translated_config.optionxform = str + + has_translation = False + if translated_file_path and os.path.exists(translated_file_path): + translated_config.read(translated_file_path, encoding=encoding) + has_translation = True + + # Create PO Object + po = polib.POFile() + now_iso = datetime.now().astimezone().isoformat() + po.metadata = { + "Project-Id-Version": "kolibri-windows-installer", + "POT-Creation-Date": now_iso, + "PO-Revision-Date": now_iso, + "Language": locale_code, + "Content-Type": "text/plain; charset=utf-8", + } + + # Merge Logic + print(f" -> Generating PO file for '{locale_code}'...") + + for section in template_config.sections(): + # Filter out technical sections + if section in ["LangOptions", "Setup"]: + continue + + for key in template_config[section]: + if not key: + continue + + msgid = template_config[section][key] + msgstr = "" + + # Only fill msgstr if we are NOT in English AND we have a translation file + if locale_code != "en" and has_translation: + if translated_config.has_section(section): + msgstr = translated_config.get(section, key, fallback="") + + entry = polib.POEntry( + msgid=msgid, msgstr=msgstr, msgctxt=f"[{section}]{key}" + ) + po.append(entry) + + output_dir = os.path.dirname(output_path) + if output_dir and not os.path.exists(output_dir): + os.makedirs(output_dir) + + po.save(output_path) + print(f" -> Success! Created: {output_path}") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Generate PO files from Inno Setup ISL files." + ) + + # Required + parser.add_argument("-t", "--template", required=True, help="Path to en.isl") + parser.add_argument("-o", "--output", required=True, help="Path to output .po file") + parser.add_argument("-l", "--lang", required=True, help="Locale code (e.g. es_ES)") + + # Optional (Choose one or the other or neither) + group = parser.add_mutually_exclusive_group() + group.add_argument("-i", "--input", help="Direct path to a translated ISL file") + group.add_argument( + "--inno-dir", help="Directory of Inno Setup Languages to auto-lookup files" + ) + + parser.add_argument( + "--no-overwrite", action="store_true", help="Prevent overwriting existing files" + ) + + args = parser.parse_args() + + main( + args.template, + args.output, + args.lang, + args.input, + args.inno_dir, + args.no_overwrite, + ) diff --git a/installer/translations/locale/de/messages.po b/installer/translations/locale/de/messages.po new file mode 100644 index 0000000..6290234 --- /dev/null +++ b/installer/translations/locale/de/messages.po @@ -0,0 +1,1454 @@ +# +msgid "" +msgstr "" +"Project-Id-Version: kolibri-windows-installer\n" +"POT-Creation-Date: 2025-12-10T11:57:24.029462+02:00\n" +"PO-Revision-Date: 2025-12-10T11:57:24.029462+02:00\n" +"Language: de\n" +"Content-Type: text/plain; charset=utf-8\n" + +msgctxt "[Messages]SetupAppTitle" +msgid "Setup" +msgstr "Setup" + +msgctxt "[Messages]SetupWindowTitle" +msgid "Setup - %1" +msgstr "Setup - %1" + +msgctxt "[Messages]UninstallAppTitle" +msgid "Uninstall" +msgstr "Entfernen" + +msgctxt "[Messages]UninstallAppFullTitle" +msgid "%1 Uninstall" +msgstr "%1 entfernen" + +msgctxt "[Messages]InformationTitle" +msgid "Information" +msgstr "Information" + +msgctxt "[Messages]ConfirmTitle" +msgid "Confirm" +msgstr "Bestätigen" + +msgctxt "[Messages]ErrorTitle" +msgid "Error" +msgstr "Fehler" + +msgctxt "[Messages]SetupLdrStartupMessage" +msgid "This will install %1. Do you wish to continue?" +msgstr "%1 wird jetzt installiert. Möchten Sie fortfahren?" + +msgctxt "[Messages]LdrCannotCreateTemp" +msgid "Unable to create a temporary file. Setup aborted" +msgstr "" +"Es konnte keine temporäre Datei erstellt werden. Das Setup wurde abgebrochen" + +msgctxt "[Messages]LdrCannotExecTemp" +msgid "Unable to execute file in the temporary directory. Setup aborted" +msgstr "" +"Die Datei konnte nicht im temporären Ordner ausgeführt werden. Das Setup " +"wurde abgebrochen" + +msgctxt "[Messages]HelpTextNote" +msgid "" +msgstr "" + +msgctxt "[Messages]LastErrorMessage" +msgid "%1.%n%nError %2: %3" +msgstr "%1.%n%nFehler %2: %3" + +msgctxt "[Messages]SetupFileMissing" +msgid "" +"The file %1 is missing from the installation directory. Please correct the " +"problem or obtain a new copy of the program." +msgstr "" +"Die Datei %1 fehlt im Installationsordner. Bitte beheben Sie das Problem " +"oder besorgen Sie sich eine neue Kopie des Programms." + +msgctxt "[Messages]SetupFileCorrupt" +msgid "" +"The setup files are corrupted. Please obtain a new copy of the program." +msgstr "" +"Die Setup-Dateien sind beschädigt. Besorgen Sie sich bitte eine neue Kopie " +"des Programms." + +msgctxt "[Messages]SetupFileCorruptOrWrongVer" +msgid "" +"The setup files are corrupted, or are incompatible with this version of " +"Setup. Please correct the problem or obtain a new copy of the program." +msgstr "" +"Die Setup-Dateien sind beschädigt oder inkompatibel zu dieser Version des " +"Setups. Bitte beheben Sie das Problem oder besorgen Sie sich eine neue Kopie" +" des Programms." + +msgctxt "[Messages]InvalidParameter" +msgid "An invalid parameter was passed on the command line:%n%n%1" +msgstr "Ein ungültiger Parameter wurde auf der Kommandozeile übergeben:%n%n%1" + +msgctxt "[Messages]SetupAlreadyRunning" +msgid "Setup is already running." +msgstr "Setup läuft bereits." + +msgctxt "[Messages]WindowsVersionNotSupported" +msgid "" +"This program does not support the version of Windows your computer is " +"running." +msgstr "" +"Dieses Programm unterstützt die auf Ihrem Computer installierte Windows-" +"Version nicht." + +msgctxt "[Messages]WindowsServicePackRequired" +msgid "This program requires %1 Service Pack %2 or later." +msgstr "Dieses Programm benötigt %1 Service Pack %2 oder höher." + +msgctxt "[Messages]NotOnThisPlatform" +msgid "This program will not run on %1." +msgstr "Dieses Programm kann nicht unter %1 ausgeführt werden." + +msgctxt "[Messages]OnlyOnThisPlatform" +msgid "This program must be run on %1." +msgstr "Dieses Programm muss unter %1 ausgeführt werden." + +msgctxt "[Messages]OnlyOnTheseArchitectures" +msgid "" +"This program can only be installed on versions of Windows designed for the " +"following processor architectures:%n%n%1" +msgstr "" +"Dieses Programm kann nur auf Windows-Versionen installiert werden, die " +"folgende Prozessor-Architekturen unterstützen:%n%n%1" + +msgctxt "[Messages]WinVersionTooLowError" +msgid "This program requires %1 version %2 or later." +msgstr "Dieses Programm benötigt %1 Version %2 oder höher." + +msgctxt "[Messages]WinVersionTooHighError" +msgid "This program cannot be installed on %1 version %2 or later." +msgstr "" +"Dieses Programm kann nicht unter %1 Version %2 oder höher installiert " +"werden." + +msgctxt "[Messages]AdminPrivilegesRequired" +msgid "" +"You must be logged in as an administrator when installing this program." +msgstr "" +"Sie müssen als Administrator angemeldet sein, um dieses Programm " +"installieren zu können." + +msgctxt "[Messages]PowerUserPrivilegesRequired" +msgid "" +"You must be logged in as an administrator or as a member of the Power Users " +"group when installing this program." +msgstr "" +"Sie müssen als Administrator oder als Mitglied der Hauptbenutzer-Gruppe " +"angemeldet sein, um dieses Programm installieren zu können." + +msgctxt "[Messages]SetupAppRunningError" +msgid "" +"Setup has detected that %1 is currently running.%n%nPlease close all " +"instances of it now, then click OK to continue, or Cancel to exit." +msgstr "" +"Das Setup hat entdeckt, dass %1 zurzeit ausgeführt wird.%n%nBitte schließen " +"Sie jetzt alle laufenden Instanzen und klicken Sie auf \"OK\", um " +"fortzufahren, oder auf \"Abbrechen\", um zu beenden." + +msgctxt "[Messages]UninstallAppRunningError" +msgid "" +"Uninstall has detected that %1 is currently running.%n%nPlease close all " +"instances of it now, then click OK to continue, or Cancel to exit." +msgstr "" +"Die Deinstallation hat entdeckt, dass %1 zurzeit ausgeführt wird.%n%nBitte " +"schließen Sie jetzt alle laufenden Instanzen und klicken Sie auf \"OK\", um " +"fortzufahren, oder auf \"Abbrechen\", um zu beenden." + +msgctxt "[Messages]PrivilegesRequiredOverrideTitle" +msgid "Select Setup Install Mode" +msgstr "Installationsmodus auswählen" + +msgctxt "[Messages]PrivilegesRequiredOverrideInstruction" +msgid "Select install mode" +msgstr "Bitte wählen Sie den Installationsmodus" + +msgctxt "[Messages]PrivilegesRequiredOverrideText1" +msgid "" +"%1 can be installed for all users (requires administrative privileges), or " +"for you only." +msgstr "" +"%1 kann für alle Benutzer (erfordert Administrationsrechte) oder nur für Sie" +" installiert werden." + +msgctxt "[Messages]PrivilegesRequiredOverrideText2" +msgid "" +"%1 can be installed for you only, or for all users (requires administrative " +"privileges)." +msgstr "" +"%1 kann nur für Sie oder für alle Benutzer (erfordert Administrationsrechte)" +" installiert werden." + +msgctxt "[Messages]PrivilegesRequiredOverrideAllUsers" +msgid "Install for &all users" +msgstr "Installation für &alle Benutzer" + +msgctxt "[Messages]PrivilegesRequiredOverrideAllUsersRecommended" +msgid "Install for &all users (recommended)" +msgstr "Installation für &alle Benutzer (empfohlen)" + +msgctxt "[Messages]PrivilegesRequiredOverrideCurrentUser" +msgid "Install for &me only" +msgstr "Installation nur für &Sie" + +msgctxt "[Messages]PrivilegesRequiredOverrideCurrentUserRecommended" +msgid "Install for &me only (recommended)" +msgstr "Installation nur für &Sie (empfohlen)" + +msgctxt "[Messages]ErrorCreatingDir" +msgid "Setup was unable to create the directory \"%1\"" +msgstr "Das Setup konnte den Ordner \"%1\" nicht erstellen." + +msgctxt "[Messages]ErrorTooManyFilesInDir" +msgid "" +"Unable to create a file in the directory \"%1\" because it contains too many" +" files" +msgstr "" +"Das Setup konnte eine Datei im Ordner \"%1\" nicht erstellen, weil er zu " +"viele Dateien enthält." + +msgctxt "[Messages]ExitSetupTitle" +msgid "Exit Setup" +msgstr "Setup verlassen" + +msgctxt "[Messages]ExitSetupMessage" +msgid "" +"Setup is not complete. If you exit now, the program will not be " +"installed.%n%nYou may run Setup again at another time to complete the " +"installation.%n%nExit Setup?" +msgstr "" +"Das Setup ist noch nicht abgeschlossen. Wenn Sie jetzt beenden, wird das " +"Programm nicht installiert.%n%nSie können das Setup zu einem späteren " +"Zeitpunkt nochmals ausführen, um die Installation zu " +"vervollständigen.%n%nSetup verlassen?" + +msgctxt "[Messages]AboutSetupMenuItem" +msgid "&About Setup..." +msgstr "&Über das Setup ..." + +msgctxt "[Messages]AboutSetupTitle" +msgid "About Setup" +msgstr "Über das Setup" + +msgctxt "[Messages]AboutSetupMessage" +msgid "%1 version %2%n%3%n%n%1 home page:%n%4" +msgstr "%1 Version %2%n%3%n%n%1 Webseite:%n%4" + +msgctxt "[Messages]AboutSetupNote" +msgid "" +msgstr "" + +msgctxt "[Messages]TranslatorNote" +msgid "" +msgstr "" +"German translation maintained by Jens Brand (jens.brand@wolf-software.de)" + +msgctxt "[Messages]ButtonBack" +msgid "< &Back" +msgstr "< &Zurück" + +msgctxt "[Messages]ButtonNext" +msgid "&Next >" +msgstr "&Weiter >" + +msgctxt "[Messages]ButtonInstall" +msgid "&Install" +msgstr "&Installieren" + +msgctxt "[Messages]ButtonOK" +msgid "OK" +msgstr "OK" + +msgctxt "[Messages]ButtonCancel" +msgid "Cancel" +msgstr "Abbrechen" + +msgctxt "[Messages]ButtonYes" +msgid "&Yes" +msgstr "&Ja" + +msgctxt "[Messages]ButtonYesToAll" +msgid "Yes to &All" +msgstr "J&a für Alle" + +msgctxt "[Messages]ButtonNo" +msgid "&No" +msgstr "&Nein" + +msgctxt "[Messages]ButtonNoToAll" +msgid "N&o to All" +msgstr "N&ein für Alle" + +msgctxt "[Messages]ButtonFinish" +msgid "&Finish" +msgstr "&Fertigstellen" + +msgctxt "[Messages]ButtonBrowse" +msgid "&Browse..." +msgstr "&Durchsuchen ..." + +msgctxt "[Messages]ButtonWizardBrowse" +msgid "B&rowse..." +msgstr "Du&rchsuchen ..." + +msgctxt "[Messages]ButtonNewFolder" +msgid "&Make New Folder" +msgstr "&Neuen Ordner erstellen" + +msgctxt "[Messages]SelectLanguageTitle" +msgid "Select Setup Language" +msgstr "Setup-Sprache auswählen" + +msgctxt "[Messages]SelectLanguageLabel" +msgid "Select the language to use during the installation." +msgstr "" +"Wählen Sie die Sprache aus, die während der Installation benutzt werden " +"soll:" + +msgctxt "[Messages]ClickNext" +msgid "Click Next to continue, or Cancel to exit Setup." +msgstr "\"Weiter\" zum Fortfahren, \"Abbrechen\" zum Verlassen." + +msgctxt "[Messages]BeveledLabel" +msgid "" +msgstr "" + +msgctxt "[Messages]BrowseDialogTitle" +msgid "Browse For Folder" +msgstr "Ordner suchen" + +msgctxt "[Messages]BrowseDialogLabel" +msgid "Select a folder in the list below, then click OK." +msgstr "Wählen Sie einen Ordner aus und klicken Sie danach auf \"OK\"." + +msgctxt "[Messages]NewFolderName" +msgid "New Folder" +msgstr "Neuer Ordner" + +msgctxt "[Messages]WelcomeLabel1" +msgid "Welcome to the [name] Setup Wizard" +msgstr "Willkommen zum [name] Setup-Assistenten" + +msgctxt "[Messages]WelcomeLabel2" +msgid "" +"This will install [name/ver] on your computer.%n%nIt is recommended that you" +" close all other applications before continuing." +msgstr "" +"Dieser Assistent wird jetzt [name/ver] auf Ihrem Computer " +"installieren.%n%nSie sollten alle anderen Anwendungen beenden, bevor Sie mit" +" dem Setup fortfahren." + +msgctxt "[Messages]WizardPassword" +msgid "Password" +msgstr "Passwort" + +msgctxt "[Messages]PasswordLabel1" +msgid "This installation is password protected." +msgstr "Diese Installation wird durch ein Passwort geschützt." + +msgctxt "[Messages]PasswordLabel3" +msgid "" +"Please provide the password, then click Next to continue. Passwords are " +"case-sensitive." +msgstr "" +"Bitte geben Sie das Passwort ein und klicken Sie danach auf \"Weiter\". " +"Achten Sie auf korrekte Groß-/Kleinschreibung." + +msgctxt "[Messages]PasswordEditLabel" +msgid "&Password:" +msgstr "&Passwort:" + +msgctxt "[Messages]IncorrectPassword" +msgid "The password you entered is not correct. Please try again." +msgstr "" +"Das eingegebene Passwort ist nicht korrekt. Bitte versuchen Sie es noch " +"einmal." + +msgctxt "[Messages]WizardLicense" +msgid "License Agreement" +msgstr "Lizenzvereinbarung" + +msgctxt "[Messages]LicenseLabel" +msgid "Please read the following important information before continuing." +msgstr "" +"Lesen Sie bitte folgende wichtige Informationen, bevor Sie fortfahren." + +msgctxt "[Messages]LicenseLabel3" +msgid "" +"Please read the following License Agreement. You must accept the terms of " +"this agreement before continuing with the installation." +msgstr "" +"Lesen Sie bitte die folgenden Lizenzvereinbarungen. Benutzen Sie bei Bedarf " +"die Bildlaufleiste oder drücken Sie die \"Bild Ab\"-Taste." + +msgctxt "[Messages]LicenseAccepted" +msgid "I &accept the agreement" +msgstr "Ich &akzeptiere die Vereinbarung" + +msgctxt "[Messages]LicenseNotAccepted" +msgid "I &do not accept the agreement" +msgstr "Ich &lehne die Vereinbarung ab" + +msgctxt "[Messages]WizardInfoBefore" +msgid "Information" +msgstr "Information" + +msgctxt "[Messages]InfoBeforeLabel" +msgid "Please read the following important information before continuing." +msgstr "" +"Lesen Sie bitte folgende wichtige Informationen, bevor Sie fortfahren." + +msgctxt "[Messages]InfoBeforeClickLabel" +msgid "When you are ready to continue with Setup, click Next." +msgstr "" +"Klicken Sie auf \"Weiter\", sobald Sie bereit sind, mit dem Setup " +"fortzufahren." + +msgctxt "[Messages]WizardInfoAfter" +msgid "Information" +msgstr "Information" + +msgctxt "[Messages]InfoAfterLabel" +msgid "Please read the following important information before continuing." +msgstr "" +"Lesen Sie bitte folgende wichtige Informationen, bevor Sie fortfahren." + +msgctxt "[Messages]InfoAfterClickLabel" +msgid "When you are ready to continue with Setup, click Next." +msgstr "" +"Klicken Sie auf \"Weiter\", sobald Sie bereit sind, mit dem Setup " +"fortzufahren." + +msgctxt "[Messages]WizardUserInfo" +msgid "User Information" +msgstr "Benutzerinformationen" + +msgctxt "[Messages]UserInfoDesc" +msgid "Please enter your information." +msgstr "Bitte tragen Sie Ihre Daten ein." + +msgctxt "[Messages]UserInfoName" +msgid "&User Name:" +msgstr "&Name:" + +msgctxt "[Messages]UserInfoOrg" +msgid "&Organization:" +msgstr "&Organisation:" + +msgctxt "[Messages]UserInfoSerial" +msgid "&Serial Number:" +msgstr "&Seriennummer:" + +msgctxt "[Messages]UserInfoNameRequired" +msgid "You must enter a name." +msgstr "Sie müssen einen Namen eintragen." + +msgctxt "[Messages]WizardSelectDir" +msgid "Select Destination Location" +msgstr "Ziel-Ordner wählen" + +msgctxt "[Messages]SelectDirDesc" +msgid "Where should [name] be installed?" +msgstr "Wohin soll [name] installiert werden?" + +msgctxt "[Messages]SelectDirLabel3" +msgid "Setup will install [name] into the following folder." +msgstr "Das Setup wird [name] in den folgenden Ordner installieren." + +msgctxt "[Messages]SelectDirBrowseLabel" +msgid "" +"To continue, click Next. If you would like to select a different folder, " +"click Browse." +msgstr "" +"Klicken Sie auf \"Weiter\", um fortzufahren. Klicken Sie auf " +"\"Durchsuchen\", falls Sie einen anderen Ordner auswählen möchten." + +msgctxt "[Messages]DiskSpaceGBLabel" +msgid "At least [gb] GB of free disk space is required." +msgstr "Mindestens [gb] GB freier Speicherplatz ist erforderlich." + +msgctxt "[Messages]DiskSpaceMBLabel" +msgid "At least [mb] MB of free disk space is required." +msgstr "Mindestens [mb] MB freier Speicherplatz ist erforderlich." + +msgctxt "[Messages]CannotInstallToNetworkDrive" +msgid "Setup cannot install to a network drive." +msgstr "Das Setup kann nicht in einen Netzwerk-Pfad installieren." + +msgctxt "[Messages]CannotInstallToUNCPath" +msgid "Setup cannot install to a UNC path." +msgstr "" +"Das Setup kann nicht in einen UNC-Pfad installieren. Wenn Sie auf ein " +"Netzlaufwerk installieren möchten, müssen Sie dem Netzwerkpfad einen " +"Laufwerksbuchstaben zuordnen." + +msgctxt "[Messages]InvalidPath" +msgid "" +"You must enter a full path with drive letter; for example:%n%nC:\\APP%n%nor " +"a UNC path in the form:%n%n\\\\server\\share" +msgstr "" +"Sie müssen einen vollständigen Pfad mit einem Laufwerksbuchstaben angeben, " +"z. B.:%n%nC:\\Beispiel%n%noder einen UNC-Pfad in der " +"Form:%n%n\\\\Server\\Freigabe" + +msgctxt "[Messages]InvalidDrive" +msgid "" +"The drive or UNC share you selected does not exist or is not accessible. " +"Please select another." +msgstr "" +"Das angegebene Laufwerk bzw. der UNC-Pfad existiert nicht oder es kann nicht" +" darauf zugegriffen werden. Wählen Sie bitte einen anderen Ordner." + +msgctxt "[Messages]DiskSpaceWarningTitle" +msgid "Not Enough Disk Space" +msgstr "Nicht genug freier Speicherplatz" + +msgctxt "[Messages]DiskSpaceWarning" +msgid "" +"Setup requires at least %1 KB of free space to install, but the selected " +"drive only has %2 KB available.%n%nDo you want to continue anyway?" +msgstr "" +"Das Setup benötigt mindestens %1 KB freien Speicherplatz zum Installieren, " +"aber auf dem ausgewählten Laufwerk sind nur %2 KB verfügbar.%n%nMöchten Sie " +"trotzdem fortfahren?" + +msgctxt "[Messages]DirNameTooLong" +msgid "The folder name or path is too long." +msgstr "Der Ordnername/Pfad ist zu lang." + +msgctxt "[Messages]InvalidDirName" +msgid "The folder name is not valid." +msgstr "Der Ordnername ist nicht gültig." + +msgctxt "[Messages]BadDirName32" +msgid "Folder names cannot include any of the following characters:%n%n%1" +msgstr "Ordnernamen dürfen keine der folgenden Zeichen enthalten:%n%n%1" + +msgctxt "[Messages]DirExistsTitle" +msgid "Folder Exists" +msgstr "Ordner existiert bereits" + +msgctxt "[Messages]DirExists" +msgid "" +"The folder:%n%n%1%n%nalready exists. Would you like to install to that " +"folder anyway?" +msgstr "" +"Der Ordner:%n%n%1%n%n existiert bereits. Möchten Sie trotzdem in diesen " +"Ordner installieren?" + +msgctxt "[Messages]DirDoesntExistTitle" +msgid "Folder Does Not Exist" +msgstr "Ordner ist nicht vorhanden" + +msgctxt "[Messages]DirDoesntExist" +msgid "" +"The folder:%n%n%1%n%ndoes not exist. Would you like the folder to be " +"created?" +msgstr "" +"Der Ordner:%n%n%1%n%nist nicht vorhanden. Soll der Ordner erstellt werden?" + +msgctxt "[Messages]WizardSelectComponents" +msgid "Select Components" +msgstr "Komponenten auswählen" + +msgctxt "[Messages]SelectComponentsDesc" +msgid "Which components should be installed?" +msgstr "Welche Komponenten sollen installiert werden?" + +msgctxt "[Messages]SelectComponentsLabel2" +msgid "" +"Select the components you want to install; clear the components you do not " +"want to install. Click Next when you are ready to continue." +msgstr "" +"Wählen Sie die Komponenten aus, die Sie installieren möchten. Klicken Sie " +"auf \"Weiter\", wenn Sie bereit sind, fortzufahren." + +msgctxt "[Messages]FullInstallation" +msgid "Full installation" +msgstr "Vollständige Installation" + +msgctxt "[Messages]CompactInstallation" +msgid "Compact installation" +msgstr "Kompakte Installation" + +msgctxt "[Messages]CustomInstallation" +msgid "Custom installation" +msgstr "Benutzerdefinierte Installation" + +msgctxt "[Messages]NoUninstallWarningTitle" +msgid "Components Exist" +msgstr "Komponenten vorhanden" + +msgctxt "[Messages]NoUninstallWarning" +msgid "" +"Setup has detected that the following components are already installed on " +"your computer:%n%n%1%n%nDeselecting these components will not uninstall " +"them.%n%nWould you like to continue anyway?" +msgstr "" +"Das Setup hat festgestellt, dass die folgenden Komponenten bereits auf Ihrem" +" Computer installiert sind:%n%n%1%n%nDiese nicht mehr ausgewählten " +"Komponenten werden nicht vom Computer entfernt.%n%nMöchten Sie trotzdem " +"fortfahren?" + +msgctxt "[Messages]ComponentSize1" +msgid "%1 KB" +msgstr "%1 KB" + +msgctxt "[Messages]ComponentSize2" +msgid "%1 MB" +msgstr "%1 MB" + +msgctxt "[Messages]ComponentsDiskSpaceGBLabel" +msgid "Current selection requires at least [gb] GB of disk space." +msgstr "Die aktuelle Auswahl erfordert mindestens [gb] GB Speicherplatz." + +msgctxt "[Messages]ComponentsDiskSpaceMBLabel" +msgid "Current selection requires at least [mb] MB of disk space." +msgstr "Die aktuelle Auswahl erfordert mindestens [mb] MB Speicherplatz." + +msgctxt "[Messages]WizardSelectTasks" +msgid "Select Additional Tasks" +msgstr "Zusätzliche Aufgaben auswählen" + +msgctxt "[Messages]SelectTasksDesc" +msgid "Which additional tasks should be performed?" +msgstr "Welche zusätzlichen Aufgaben sollen ausgeführt werden?" + +msgctxt "[Messages]SelectTasksLabel2" +msgid "" +"Select the additional tasks you would like Setup to perform while installing" +" [name], then click Next." +msgstr "" +"Wählen Sie die zusätzlichen Aufgaben aus, die das Setup während der " +"Installation von [name] ausführen soll, und klicken Sie danach auf " +"\"Weiter\"." + +msgctxt "[Messages]WizardSelectProgramGroup" +msgid "Select Start Menu Folder" +msgstr "Startmenü-Ordner auswählen" + +msgctxt "[Messages]SelectStartMenuFolderDesc" +msgid "Where should Setup place the program's shortcuts?" +msgstr "Wo soll das Setup die Programm-Verknüpfungen erstellen?" + +msgctxt "[Messages]SelectStartMenuFolderLabel3" +msgid "" +"Setup will create the program's shortcuts in the following Start Menu " +"folder." +msgstr "" +"Das Setup wird die Programm-Verknüpfungen im folgenden Startmenü-Ordner " +"erstellen." + +msgctxt "[Messages]SelectStartMenuFolderBrowseLabel" +msgid "" +"To continue, click Next. If you would like to select a different folder, " +"click Browse." +msgstr "" +"Klicken Sie auf \"Weiter\", um fortzufahren. Klicken Sie auf " +"\"Durchsuchen\", falls Sie einen anderen Ordner auswählen möchten." + +msgctxt "[Messages]MustEnterGroupName" +msgid "You must enter a folder name." +msgstr "Sie müssen einen Ordnernamen eingeben." + +msgctxt "[Messages]GroupNameTooLong" +msgid "The folder name or path is too long." +msgstr "Der Ordnername/Pfad ist zu lang." + +msgctxt "[Messages]InvalidGroupName" +msgid "The folder name is not valid." +msgstr "Der Ordnername ist nicht gültig." + +msgctxt "[Messages]BadGroupName" +msgid "The folder name cannot include any of the following characters:%n%n%1" +msgstr "Der Ordnername darf keine der folgenden Zeichen enthalten:%n%n%1" + +msgctxt "[Messages]NoProgramGroupCheck2" +msgid "&Don't create a Start Menu folder" +msgstr "&Keinen Ordner im Startmenü erstellen" + +msgctxt "[Messages]WizardReady" +msgid "Ready to Install" +msgstr "Bereit zur Installation." + +msgctxt "[Messages]ReadyLabel1" +msgid "Setup is now ready to begin installing [name] on your computer." +msgstr "" +"Das Setup ist jetzt bereit, [name] auf Ihrem Computer zu installieren." + +msgctxt "[Messages]ReadyLabel2a" +msgid "" +"Click Install to continue with the installation, or click Back if you want " +"to review or change any settings." +msgstr "" +"Klicken Sie auf \"Installieren\", um mit der Installation zu beginnen, oder " +"auf \"Zurück\", um Ihre Einstellungen zu überprüfen oder zu ändern." + +msgctxt "[Messages]ReadyLabel2b" +msgid "Click Install to continue with the installation." +msgstr "Klicken Sie auf \"Installieren\", um mit der Installation zu beginnen." + +msgctxt "[Messages]ReadyMemoUserInfo" +msgid "User information:" +msgstr "Benutzerinformationen:" + +msgctxt "[Messages]ReadyMemoDir" +msgid "Destination location:" +msgstr "Ziel-Ordner:" + +msgctxt "[Messages]ReadyMemoType" +msgid "Setup type:" +msgstr "Setup-Typ:" + +msgctxt "[Messages]ReadyMemoComponents" +msgid "Selected components:" +msgstr "Ausgewählte Komponenten:" + +msgctxt "[Messages]ReadyMemoGroup" +msgid "Start Menu folder:" +msgstr "Startmenü-Ordner:" + +msgctxt "[Messages]ReadyMemoTasks" +msgid "Additional tasks:" +msgstr "Zusätzliche Aufgaben:" + +msgctxt "[Messages]DownloadingLabel2" +msgid "Downloading files..." +msgstr "Lade Dateien herunter..." + +msgctxt "[Messages]ButtonStopDownload" +msgid "&Stop download" +msgstr "Download &abbrechen" + +msgctxt "[Messages]StopDownload" +msgid "Are you sure you want to stop the download?" +msgstr "Sind Sie sicher, dass Sie den Download abbrechen wollen?" + +msgctxt "[Messages]ErrorDownloadAborted" +msgid "Download aborted" +msgstr "Download abgebrochen" + +msgctxt "[Messages]ErrorDownloadFailed" +msgid "Download failed: %1 %2" +msgstr "Download fehlgeschlagen: %1 %2" + +msgctxt "[Messages]ErrorDownloadSizeFailed" +msgid "Getting size failed: %1 %2" +msgstr "Fehler beim Ermitteln der Größe: %1 %2" + +msgctxt "[Messages]ErrorProgress" +msgid "Invalid progress: %1 of %2" +msgstr "Ungültiger Fortschritt: %1 von %2" + +msgctxt "[Messages]ErrorFileSize" +msgid "Invalid file size: expected %1, found %2" +msgstr "Ungültige Dateigröße: erwartet %1, gefunden %2" + +msgctxt "[Messages]ExtractingLabel" +msgid "Extracting files..." +msgstr "Entpacke Dateien..." + +msgctxt "[Messages]ButtonStopExtraction" +msgid "&Stop extraction" +msgstr "Entpacken &abbrechen" + +msgctxt "[Messages]StopExtraction" +msgid "Are you sure you want to stop the extraction?" +msgstr "Sind Sie sicher, dass Sie das Entpacken abbrechen wollen?" + +msgctxt "[Messages]ErrorExtractionAborted" +msgid "Extraction aborted" +msgstr "Entpacken abgebrochen" + +msgctxt "[Messages]ErrorExtractionFailed" +msgid "Extraction failed: %1" +msgstr "Entpacken fehlgeschlagen: %1" + +msgctxt "[Messages]ArchiveIncorrectPassword" +msgid "The password is incorrect" +msgstr "Ungültiges Passwort" + +msgctxt "[Messages]ArchiveIsCorrupted" +msgid "The archive is corrupted" +msgstr "Das Archiv ist defekt" + +msgctxt "[Messages]ArchiveUnsupportedFormat" +msgid "The archive format is unsupported" +msgstr "Das Archivformat wird nicht unterstützt" + +msgctxt "[Messages]WizardPreparing" +msgid "Preparing to Install" +msgstr "Vorbereitung der Installation" + +msgctxt "[Messages]PreparingDesc" +msgid "Setup is preparing to install [name] on your computer." +msgstr "" +"Das Setup bereitet die Installation von [name] auf diesem Computer vor." + +msgctxt "[Messages]PreviousInstallNotCompleted" +msgid "" +"The installation/removal of a previous program was not completed. You will " +"need to restart your computer to complete that installation.%n%nAfter " +"restarting your computer, run Setup again to complete the installation of " +"[name]." +msgstr "" +"Eine vorherige Installation/Deinstallation eines Programms wurde nicht " +"abgeschlossen. Der Computer muss neu gestartet werden, um die " +"Installation/Deinstallation zu beenden.%n%nStarten Sie das Setup nach dem " +"Neustart Ihres Computers erneut, um die Installation von [name] " +"durchzuführen." + +msgctxt "[Messages]CannotContinue" +msgid "Setup cannot continue. Please click Cancel to exit." +msgstr "" +"Das Setup kann nicht fortfahren. Bitte klicken Sie auf \"Abbrechen\" zum " +"Verlassen." + +msgctxt "[Messages]ApplicationsFound" +msgid "" +"The following applications are using files that need to be updated by Setup." +" It is recommended that you allow Setup to automatically close these " +"applications." +msgstr "" +"Die folgenden Anwendungen benutzen Dateien, die aktualisiert werden müssen. " +"Es wird empfohlen, Setup zu erlauben, diese Anwendungen zu schließen." + +msgctxt "[Messages]ApplicationsFound2" +msgid "" +"The following applications are using files that need to be updated by Setup." +" It is recommended that you allow Setup to automatically close these " +"applications. After the installation has completed, Setup will attempt to " +"restart the applications." +msgstr "" +"Die folgenden Anwendungen benutzen Dateien, die aktualisiert werden müssen. " +"Es wird empfohlen, Setup zu erlauben, diese Anwendungen zu schließen. " +"Nachdem die Installation fertiggestellt wurde, versucht Setup, diese " +"Anwendungen wieder zu starten." + +msgctxt "[Messages]CloseApplications" +msgid "&Automatically close the applications" +msgstr "&Schließe die Anwendungen automatisch" + +msgctxt "[Messages]DontCloseApplications" +msgid "&Do not close the applications" +msgstr "Schließe die A&nwendungen nicht" + +msgctxt "[Messages]ErrorCloseApplications" +msgid "" +"Setup was unable to automatically close all applications. It is recommended " +"that you close all applications using files that need to be updated by Setup" +" before continuing." +msgstr "" +"Das Setup konnte nicht alle Anwendungen automatisch schließen. Es wird " +"empfohlen, alle Anwendungen zu schließen, die Dateien benutzen, die vom " +"Setup vor einer Fortsetzung aktualisiert werden müssen." + +msgctxt "[Messages]PrepareToInstallNeedsRestart" +msgid "" +"Setup must restart your computer. After restarting your computer, run Setup " +"again to complete the installation of [name].%n%nWould you like to restart " +"now?" +msgstr "" +"Das Setup muss Ihren Computer neu starten. Führen Sie nach dem Neustart " +"Setup erneut aus, um die Installation von [name] abzuschließen.%n%nWollen " +"Sie jetzt neu starten?" + +msgctxt "[Messages]WizardInstalling" +msgid "Installing" +msgstr "Installiere ..." + +msgctxt "[Messages]InstallingLabel" +msgid "Please wait while Setup installs [name] on your computer." +msgstr "Warten Sie bitte, während [name] auf Ihrem Computer installiert wird." + +msgctxt "[Messages]FinishedHeadingLabel" +msgid "Completing the [name] Setup Wizard" +msgstr "Beenden des [name] Setup-Assistenten" + +msgctxt "[Messages]FinishedLabelNoIcons" +msgid "Setup has finished installing [name] on your computer." +msgstr "" +"Das Setup hat die Installation von [name] auf Ihrem Computer abgeschlossen." + +msgctxt "[Messages]FinishedLabel" +msgid "" +"Setup has finished installing [name] on your computer. The application may " +"be launched by selecting the installed shortcuts." +msgstr "" +"Das Setup hat die Installation von [name] auf Ihrem Computer abgeschlossen. " +"Die Anwendung kann über die installierten Programm-Verknüpfungen gestartet " +"werden." + +msgctxt "[Messages]ClickFinish" +msgid "Click Finish to exit Setup." +msgstr "Klicken Sie auf \"Fertigstellen\", um das Setup zu beenden." + +msgctxt "[Messages]FinishedRestartLabel" +msgid "" +"To complete the installation of [name], Setup must restart your computer. " +"Would you like to restart now?" +msgstr "" +"Um die Installation von [name] abzuschließen, muss das Setup Ihren Computer " +"neu starten. Möchten Sie jetzt neu starten?" + +msgctxt "[Messages]FinishedRestartMessage" +msgid "" +"To complete the installation of [name], Setup must restart your " +"computer.%n%nWould you like to restart now?" +msgstr "" +"Um die Installation von [name] abzuschließen, muss das Setup Ihren Computer " +"neu starten.%n%nMöchten Sie jetzt neu starten?" + +msgctxt "[Messages]ShowReadmeCheck" +msgid "Yes, I would like to view the README file" +msgstr "Ja, ich möchte die LIESMICH-Datei sehen" + +msgctxt "[Messages]YesRadio" +msgid "&Yes, restart the computer now" +msgstr "&Ja, Computer jetzt neu starten" + +msgctxt "[Messages]NoRadio" +msgid "&No, I will restart the computer later" +msgstr "&Nein, ich werde den Computer später neu starten" + +msgctxt "[Messages]RunEntryExec" +msgid "Run %1" +msgstr "%1 starten" + +msgctxt "[Messages]RunEntryShellExec" +msgid "View %1" +msgstr "%1 anzeigen" + +msgctxt "[Messages]ChangeDiskTitle" +msgid "Setup Needs the Next Disk" +msgstr "Nächsten Datenträger einlegen" + +msgctxt "[Messages]SelectDiskLabel2" +msgid "" +"Please insert Disk %1 and click OK.%n%nIf the files on this disk can be " +"found in a folder other than the one displayed below, enter the correct path" +" or click Browse." +msgstr "" +"Legen Sie bitte Datenträger %1 ein und klicken Sie auf \"OK\".%n%nWenn sich " +"die Dateien von diesem Datenträger in einem anderen als dem angezeigten " +"Ordner befinden, dann geben Sie bitte den korrekten Pfad ein oder klicken " +"auf \"Durchsuchen\"." + +msgctxt "[Messages]PathLabel" +msgid "&Path:" +msgstr "&Pfad:" + +msgctxt "[Messages]FileNotInDir2" +msgid "" +"The file \"%1\" could not be located in \"%2\". Please insert the correct " +"disk or select another folder." +msgstr "" +"Die Datei \"%1\" befindet sich nicht in \"%2\". Bitte Ordner ändern oder " +"richtigen Datenträger einlegen." + +msgctxt "[Messages]SelectDirectoryLabel" +msgid "Please specify the location of the next disk." +msgstr "Geben Sie bitte an, wo der nächste Datenträger eingelegt wird." + +msgctxt "[Messages]SetupAborted" +msgid "" +"Setup was not completed.%n%nPlease correct the problem and run Setup again." +msgstr "" +"Das Setup konnte nicht abgeschlossen werden.%n%nBeheben Sie bitte das " +"Problem und starten Sie das Setup erneut." + +msgctxt "[Messages]AbortRetryIgnoreSelectAction" +msgid "Select action" +msgstr "Bitte auswählen" + +msgctxt "[Messages]AbortRetryIgnoreRetry" +msgid "&Try again" +msgstr "&Nochmals versuchen" + +msgctxt "[Messages]AbortRetryIgnoreIgnore" +msgid "&Ignore the error and continue" +msgstr "&Den Fehler ignorieren und fortfahren" + +msgctxt "[Messages]AbortRetryIgnoreCancel" +msgid "Cancel installation" +msgstr "Installation abbrechen" + +msgctxt "[Messages]RetryCancelSelectAction" +msgid "Select action" +msgstr "Bitte auswählen" + +msgctxt "[Messages]RetryCancelRetry" +msgid "&Try again" +msgstr "&Wiederholen" + +msgctxt "[Messages]RetryCancelCancel" +msgid "Cancel" +msgstr "&Abbrechen" + +msgctxt "[Messages]StatusClosingApplications" +msgid "Closing applications..." +msgstr "Anwendungen werden geschlossen ..." + +msgctxt "[Messages]StatusCreateDirs" +msgid "Creating directories..." +msgstr "Ordner werden erstellt ..." + +msgctxt "[Messages]StatusExtractFiles" +msgid "Extracting files..." +msgstr "Dateien werden entpackt ..." + +msgctxt "[Messages]StatusDownloadFiles" +msgid "Downloading files..." +msgstr "Dateien werden herunter geladen..." + +msgctxt "[Messages]StatusCreateIcons" +msgid "Creating shortcuts..." +msgstr "Verknüpfungen werden erstellt ..." + +msgctxt "[Messages]StatusCreateIniEntries" +msgid "Creating INI entries..." +msgstr "INI-Einträge werden erstellt ..." + +msgctxt "[Messages]StatusCreateRegistryEntries" +msgid "Creating registry entries..." +msgstr "Registry-Einträge werden erstellt ..." + +msgctxt "[Messages]StatusRegisterFiles" +msgid "Registering files..." +msgstr "Dateien werden registriert ..." + +msgctxt "[Messages]StatusSavingUninstall" +msgid "Saving uninstall information..." +msgstr "Deinstallationsinformationen werden gespeichert ..." + +msgctxt "[Messages]StatusRunProgram" +msgid "Finishing installation..." +msgstr "Installation wird beendet ..." + +msgctxt "[Messages]StatusRestartingApplications" +msgid "Restarting applications..." +msgstr "Neustart der Anwendungen ..." + +msgctxt "[Messages]StatusRollback" +msgid "Rolling back changes..." +msgstr "Änderungen werden rückgängig gemacht ..." + +msgctxt "[Messages]ErrorInternal2" +msgid "Internal error: %1" +msgstr "Interner Fehler: %1" + +msgctxt "[Messages]ErrorFunctionFailedNoCode" +msgid "%1 failed" +msgstr "%1 schlug fehl" + +msgctxt "[Messages]ErrorFunctionFailed" +msgid "%1 failed; code %2" +msgstr "%1 schlug fehl; Code %2" + +msgctxt "[Messages]ErrorFunctionFailedWithMessage" +msgid "%1 failed; code %2.%n%3" +msgstr "%1 schlug fehl; Code %2.%n%3" + +msgctxt "[Messages]ErrorExecutingProgram" +msgid "Unable to execute file:%n%1" +msgstr "Datei kann nicht ausgeführt werden:%n%1" + +msgctxt "[Messages]ErrorRegOpenKey" +msgid "Error opening registry key:%n%1\\%2" +msgstr "Registry-Schlüssel konnte nicht geöffnet werden:%n%1\\%2" + +msgctxt "[Messages]ErrorRegCreateKey" +msgid "Error creating registry key:%n%1\\%2" +msgstr "Registry-Schlüssel konnte nicht erstellt werden:%n%1\\%2" + +msgctxt "[Messages]ErrorRegWriteKey" +msgid "Error writing to registry key:%n%1\\%2" +msgstr "Fehler beim Schreiben des Registry-Schlüssels:%n%1\\%2" + +msgctxt "[Messages]ErrorIniEntry" +msgid "Error creating INI entry in file \"%1\"." +msgstr "Fehler beim Erstellen eines INI-Eintrages in der Datei \"%1\"." + +msgctxt "[Messages]FileAbortRetryIgnoreSkipNotRecommended" +msgid "&Skip this file (not recommended)" +msgstr "Diese Datei &überspringen (nicht empfohlen)" + +msgctxt "[Messages]FileAbortRetryIgnoreIgnoreNotRecommended" +msgid "&Ignore the error and continue (not recommended)" +msgstr "Den Fehler &ignorieren und fortfahren (nicht empfohlen)" + +msgctxt "[Messages]SourceIsCorrupted" +msgid "The source file is corrupted" +msgstr "Die Quelldatei ist beschädigt" + +msgctxt "[Messages]SourceDoesntExist" +msgid "The source file \"%1\" does not exist" +msgstr "Die Quelldatei \"%1\" existiert nicht" + +msgctxt "[Messages]SourceVerificationFailed" +msgid "Verification of the source file failed: %1" +msgstr "Überprüfung der Quelldatei fehlgeschlagen: %1" + +msgctxt "[Messages]VerificationSignatureDoesntExist" +msgid "The signature file \"%1\" does not exist" +msgstr "Die Signaturdatei \"%1\" existiert nicht" + +msgctxt "[Messages]VerificationSignatureInvalid" +msgid "The signature file \"%1\" is invalid" +msgstr "Die Signaturdatei \"%1\" ist ungültig" + +msgctxt "[Messages]VerificationKeyNotFound" +msgid "The signature file \"%1\" uses an unknown key" +msgstr "Die Signaturdatei \"%1\" verwendet einen unbekannten Schlüssel" + +msgctxt "[Messages]VerificationFileNameIncorrect" +msgid "The name of the file is incorrect" +msgstr "Der Name der Datei ist ungültig" + +msgctxt "[Messages]VerificationFileTagIncorrect" +msgid "The tag of the file is incorrect" +msgstr "Der Tag der Datei ist ungültig" + +msgctxt "[Messages]VerificationFileSizeIncorrect" +msgid "The size of the file is incorrect" +msgstr "Die Größe der Datei ist ungültig" + +msgctxt "[Messages]VerificationFileHashIncorrect" +msgid "The hash of the file is incorrect" +msgstr "Der Hashwert der Datei ist ungültig" + +msgctxt "[Messages]ExistingFileReadOnly2" +msgid "" +"The existing file could not be replaced because it is marked read-only." +msgstr "" +"Die vorhandene Datei kann nicht ersetzt werden, da sie schreibgeschützt ist." + +msgctxt "[Messages]ExistingFileReadOnlyRetry" +msgid "&Remove the read-only attribute and try again" +msgstr "&Den Schreibschutz entfernen und noch einmal versuchen" + +msgctxt "[Messages]ExistingFileReadOnlyKeepExisting" +msgid "&Keep the existing file" +msgstr "Die &vorhandene Datei behalten" + +msgctxt "[Messages]ErrorReadingExistingDest" +msgid "An error occurred while trying to read the existing file:" +msgstr "Lesefehler in Datei:" + +msgctxt "[Messages]FileExistsSelectAction" +msgid "Select action" +msgstr "Aktion auswählen" + +msgctxt "[Messages]FileExists2" +msgid "The file already exists." +msgstr "Die Datei ist bereits vorhanden." + +msgctxt "[Messages]FileExistsOverwriteExisting" +msgid "&Overwrite the existing file" +msgstr "Vorhandene Datei &überschreiben" + +msgctxt "[Messages]FileExistsKeepExisting" +msgid "&Keep the existing file" +msgstr "Vorhandene Datei &behalten" + +msgctxt "[Messages]FileExistsOverwriteOrKeepAll" +msgid "&Do this for the next conflicts" +msgstr "&Dies auch für die nächsten Konflikte ausführen" + +msgctxt "[Messages]ExistingFileNewerSelectAction" +msgid "Select action" +msgstr "Aktion auswählen" + +msgctxt "[Messages]ExistingFileNewer2" +msgid "The existing file is newer than the one Setup is trying to install." +msgstr "" +"Die vorhandene Datei ist neuer als die Datei, die installiert werden soll." + +msgctxt "[Messages]ExistingFileNewerOverwriteExisting" +msgid "&Overwrite the existing file" +msgstr "Vorhandene Datei &überschreiben" + +msgctxt "[Messages]ExistingFileNewerKeepExisting" +msgid "&Keep the existing file (recommended)" +msgstr "Vorhandene Datei &behalten (empfohlen)" + +msgctxt "[Messages]ExistingFileNewerOverwriteOrKeepAll" +msgid "&Do this for the next conflicts" +msgstr "&Dies auch für die nächsten Konflikte ausführen" + +msgctxt "[Messages]ErrorChangingAttr" +msgid "" +"An error occurred while trying to change the attributes of the existing " +"file:" +msgstr "Fehler beim Ändern der Datei-Attribute:" + +msgctxt "[Messages]ErrorCreatingTemp" +msgid "" +"An error occurred while trying to create a file in the destination " +"directory:" +msgstr "Fehler beim Erstellen einer Datei im Ziel-Ordner:" + +msgctxt "[Messages]ErrorReadingSource" +msgid "An error occurred while trying to read the source file:" +msgstr "Fehler beim Lesen der Quelldatei:" + +msgctxt "[Messages]ErrorCopying" +msgid "An error occurred while trying to copy a file:" +msgstr "Fehler beim Kopieren einer Datei:" + +msgctxt "[Messages]ErrorDownloading" +msgid "An error occurred while trying to download a file:" +msgstr "Beim Download der Datei ist ein Fehler aufgetreten:" + +msgctxt "[Messages]ErrorExtracting" +msgid "An error occurred while trying to extract an archive:" +msgstr "Beim Entpacken eines Archivs ist ein Fehler aufgetreten:" + +msgctxt "[Messages]ErrorReplacingExistingFile" +msgid "An error occurred while trying to replace the existing file:" +msgstr "Fehler beim Ersetzen einer vorhandenen Datei:" + +msgctxt "[Messages]ErrorRestartReplace" +msgid "RestartReplace failed:" +msgstr "\"Ersetzen nach Neustart\" fehlgeschlagen:" + +msgctxt "[Messages]ErrorRenamingTemp" +msgid "" +"An error occurred while trying to rename a file in the destination " +"directory:" +msgstr "Fehler beim Umbenennen einer Datei im Ziel-Ordner:" + +msgctxt "[Messages]ErrorRegisterServer" +msgid "Unable to register the DLL/OCX: %1" +msgstr "DLL/OCX konnte nicht registriert werden: %1" + +msgctxt "[Messages]ErrorRegSvr32Failed" +msgid "RegSvr32 failed with exit code %1" +msgstr "RegSvr32-Aufruf scheiterte mit Exit-Code %1" + +msgctxt "[Messages]ErrorRegisterTypeLib" +msgid "Unable to register the type library: %1" +msgstr "Typen-Bibliothek konnte nicht registriert werden: %1" + +msgctxt "[Messages]UninstallDisplayNameMark" +msgid "%1 (%2)" +msgstr "%1 (%2)" + +msgctxt "[Messages]UninstallDisplayNameMarks" +msgid "%1 (%2, %3)" +msgstr "%1 (%2, %3)" + +msgctxt "[Messages]UninstallDisplayNameMark32Bit" +msgid "32-bit" +msgstr "32 Bit" + +msgctxt "[Messages]UninstallDisplayNameMark64Bit" +msgid "64-bit" +msgstr "64 Bit" + +msgctxt "[Messages]UninstallDisplayNameMarkAllUsers" +msgid "All users" +msgstr "Alle Benutzer" + +msgctxt "[Messages]UninstallDisplayNameMarkCurrentUser" +msgid "Current user" +msgstr "Aktueller Benutzer" + +msgctxt "[Messages]ErrorOpeningReadme" +msgid "An error occurred while trying to open the README file." +msgstr "Fehler beim Öffnen der LIESMICH-Datei." + +msgctxt "[Messages]ErrorRestartingComputer" +msgid "Setup was unable to restart the computer. Please do this manually." +msgstr "" +"Das Setup konnte den Computer nicht neu starten. Bitte führen Sie den " +"Neustart manuell durch." + +msgctxt "[Messages]UninstallNotFound" +msgid "File \"%1\" does not exist. Cannot uninstall." +msgstr "Die Datei \"%1\" existiert nicht. Entfernen der Anwendung fehlgeschlagen." + +msgctxt "[Messages]UninstallOpenError" +msgid "File \"%1\" could not be opened. Cannot uninstall" +msgstr "" +"Die Datei \"%1\" konnte nicht geöffnet werden. Entfernen der Anwendung " +"fehlgeschlagen." + +msgctxt "[Messages]UninstallUnsupportedVer" +msgid "" +"The uninstall log file \"%1\" is in a format not recognized by this version " +"of the uninstaller. Cannot uninstall" +msgstr "" +"Das Format der Deinstallationsdatei \"%1\" konnte nicht erkannt werden. " +"Entfernen der Anwendung fehlgeschlagen." + +msgctxt "[Messages]UninstallUnknownEntry" +msgid "An unknown entry (%1) was encountered in the uninstall log" +msgstr "" +"In der Deinstallationsdatei wurde ein unbekannter Eintrag (%1) gefunden." + +msgctxt "[Messages]ConfirmUninstall" +msgid "" +"Are you sure you want to completely remove %1 and all of its components?" +msgstr "" +"Sind Sie sicher, dass Sie %1 und alle zugehörigen Komponenten entfernen " +"möchten?" + +msgctxt "[Messages]UninstallOnlyOnWin64" +msgid "This installation can only be uninstalled on 64-bit Windows." +msgstr "" +"Diese Installation kann nur unter 64-Bit-Windows-Versionen entfernt werden." + +msgctxt "[Messages]OnlyAdminCanUninstall" +msgid "" +"This installation can only be uninstalled by a user with administrative " +"privileges." +msgstr "" +"Diese Installation kann nur von einem Benutzer mit Administrator-Rechten " +"entfernt werden." + +msgctxt "[Messages]UninstallStatusLabel" +msgid "Please wait while %1 is removed from your computer." +msgstr "Warten Sie bitte, während %1 von Ihrem Computer entfernt wird." + +msgctxt "[Messages]UninstalledAll" +msgid "%1 was successfully removed from your computer." +msgstr "%1 wurde erfolgreich von Ihrem Computer entfernt." + +msgctxt "[Messages]UninstalledMost" +msgid "" +"%1 uninstall complete.%n%nSome elements could not be removed. These can be " +"removed manually." +msgstr "" +"Entfernen von %1 beendet.%n%nEinige Komponenten konnten nicht entfernt " +"werden. Diese können von Ihnen manuell gelöscht werden." + +msgctxt "[Messages]UninstalledAndNeedsRestart" +msgid "" +"To complete the uninstallation of %1, your computer must be " +"restarted.%n%nWould you like to restart now?" +msgstr "" +"Um die Deinstallation von %1 abzuschließen, muss Ihr Computer neu gestartet " +"werden.%n%nMöchten Sie jetzt neu starten?" + +msgctxt "[Messages]UninstallDataCorrupted" +msgid "\"%1\" file is corrupted. Cannot uninstall" +msgstr "\"%1\"-Datei ist beschädigt. Entfernen der Anwendung fehlgeschlagen." + +msgctxt "[Messages]ConfirmDeleteSharedFileTitle" +msgid "Remove Shared File?" +msgstr "Gemeinsame Datei entfernen?" + +msgctxt "[Messages]ConfirmDeleteSharedFile2" +msgid "" +"The system indicates that the following shared file is no longer in use by " +"any programs. Would you like for Uninstall to remove this shared file?%n%nIf" +" any programs are still using this file and it is removed, those programs " +"may not function properly. If you are unsure, choose No. Leaving the file on" +" your system will not cause any harm." +msgstr "" +"Das System zeigt an, dass die folgende gemeinsame Datei von keinem anderen " +"Programm mehr benutzt wird. Möchten Sie diese Datei entfernen " +"lassen?%nSollte es doch noch Programme geben, die diese Datei benutzen und " +"sie wird entfernt, funktionieren diese Programme vielleicht nicht mehr " +"richtig. Wenn Sie unsicher sind, wählen Sie \"Nein\", um die Datei im System" +" zu belassen. Es schadet Ihrem System nicht, wenn Sie die Datei behalten." + +msgctxt "[Messages]SharedFileNameLabel" +msgid "File name:" +msgstr "Dateiname:" + +msgctxt "[Messages]SharedFileLocationLabel" +msgid "Location:" +msgstr "Ordner:" + +msgctxt "[Messages]WizardUninstalling" +msgid "Uninstall Status" +msgstr "Entfernen (Status)" + +msgctxt "[Messages]StatusUninstalling" +msgid "Uninstalling %1..." +msgstr "Entferne %1 ..." + +msgctxt "[Messages]ShutdownBlockReasonInstallingApp" +msgid "Installing %1." +msgstr "Installation von %1." + +msgctxt "[Messages]ShutdownBlockReasonUninstallingApp" +msgid "Uninstalling %1." +msgstr "Deinstallation von %1." + +msgctxt "[CustomMessages]installservicetask" +msgid "Run Kolibri automatically when the computer starts" +msgstr "" + +msgctxt "[CustomMessages]newerversioninstalled" +msgid "" +"A newer version of {#AppName} (%1) is already installed. This installer " +"contains version %2, which is older. The setup will now exit." +msgstr "" + +msgctxt "[CustomMessages]sameversioninstalled" +msgid "" +"This version of %1 is already installed. Do you want to repair the " +"installation by reinstalling it?" +msgstr "" + +msgctxt "[CustomMessages]olderversioninstalled" +msgid "" +"An older version of {#AppName} (%1) was detected. Do you want to upgrade to " +"version {#AppVersion}?" +msgstr "" + +msgctxt "[CustomMessages]confirmuninstalldata" +msgid "" +"Do you want to completely remove all Kolibri user data? This includes all " +"downloaded content, user accounts, and progress, and cannot be undone." +msgstr "" + +msgctxt "[CustomMessages]criticalerror" +msgid "" +"A critical error occurred while trying to run a setup command: %1. The " +"installation cannot continue." +msgstr "" + +msgctxt "[CustomMessages]commanderror" +msgid "" +"A command required for setup failed to execute correctly: %1. Error Code: " +"%2. The installation cannot continue." +msgstr "" + +msgctxt "[CustomMessages]versionparseerror" +msgid "" +"Could not compare versions due to an invalid version format. Please " +"uninstall the previous version manually and try again." +msgstr "" + +msgctxt "[CustomMessages]migrationfailed" +msgid "" +"The installer failed to migrate user data from the old location (%1) to the " +"new location (%2). Your data has not been moved. Please contact support for " +"assistance." +msgstr "" + +msgctxt "[CustomMessages]createdesktopicon" +msgid "Create a &desktop icon" +msgstr "" + +msgctxt "[CustomMessages]additionalicons" +msgid "Additional icons:" +msgstr "" + +msgctxt "[CustomMessages]launchprogram" +msgid "Launch %1" +msgstr "" + +msgctxt "[CustomMessages]installationtype" +msgid "Installation Type:" +msgstr "" diff --git a/installer/translations/po_to_isl.py b/installer/translations/po_to_isl.py new file mode 100644 index 0000000..fa7e0a1 --- /dev/null +++ b/installer/translations/po_to_isl.py @@ -0,0 +1,70 @@ +import argparse +import configparser + +import polib +from definitions import LANG_DEFINITIONS + + +def convert_po_to_isl( + template_isl_path, translated_po_path, output_isl_path, locale_code +): + encoding = "utf-8-sig" + + # 1. Load PO + po = polib.pofile(translated_po_path, encoding="utf-8") + + # 2. Create a lookup map using a Tuple: (msgid, msgctxt) + translation_map = { + (entry.msgid, entry.msgctxt): entry.msgstr for entry in po if entry.msgstr + } + + # 3. Load Template + config = configparser.ConfigParser(interpolation=None) + config.optionxform = str + config.read(template_isl_path, encoding=encoding) + + # 4. Update Translations + for section in config.sections(): + for key in config[section]: + english_string = config[section][key] + + context_key = f"[{section}]{key}" + + translated_string = translation_map.get((english_string, context_key)) + + if translated_string: + config.set(section, key, translated_string) + + # 5. Add LangOptions section + if locale_code in LANG_DEFINITIONS: + lang_def = LANG_DEFINITIONS[locale_code] + if not config.has_section("LangOptions"): + config.add_section("LangOptions") + ui_name = lang_def.get("display_name", lang_def["inno_name"]) + config.set("LangOptions", "LanguageName", ui_name) + + config.set("LangOptions", "LanguageID", lang_def["id"]) + + if "font" in lang_def: + font_name = lang_def["font"] + config.set("LangOptions", "DialogFontName", font_name) + config.set("LangOptions", "WelcomeFontName", font_name) + + if lang_def.get("rtl", False): + config.set("LangOptions", "RightToLeft", "yes") + + with open(output_isl_path, "w", encoding=encoding) as f: + config.write(f, space_around_delimiters=False) + + print(f"Generated: {output_isl_path}") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("-t", "--template", required=True) + parser.add_argument("-i", "--input", required=True) + parser.add_argument("-o", "--output", required=True) + parser.add_argument("-l", "--lang", required=True) + args = parser.parse_args() + + convert_po_to_isl(args.template, args.input, args.output, args.lang) diff --git a/installer/translations/update_from_inno_default.py b/installer/translations/update_from_inno_default.py new file mode 100644 index 0000000..bc21248 --- /dev/null +++ b/installer/translations/update_from_inno_default.py @@ -0,0 +1,147 @@ +""" +Update Master Language File from Inno Setup Defaults. + +This script is designed to synchronize the project's master +language file (`English.isl`) with an updated `Default.isl` +from a new version of the Inno Setup compiler. + +Workflow: +1. Compares the `[Messages]` section of the new `Default.isl` with the + project's current `English.isl`. +2. Identifies and calculates the differences: strings that have been added, + removed, or modified between the two versions. +3. Merges these changes into the project's `English.isl`, + updating the base translations while preserving the project-specific + `[CustomMessages]` and `[LangOptions]` sections. +4. Generates a `update_report.txt` file that lists all changes. + This report serves as a guide for translators to update the + other language files accordingly. +""" +import argparse +import configparser +import os +from datetime import datetime +from datetime import timezone + + +def _load_config(file_path): + """Loads an ISL file into a ConfigParser object.""" + config = configparser.ConfigParser( + allow_no_value=True, interpolation=None, strict=False + ) + config.optionxform = str # Preserve case + config.read(file_path, encoding="utf-8-sig") + return config + + +def _compare_messages(new_messages, master_messages): + """Compares two dictionaries of messages and returns the differences.""" + added = {k: v for k, v in new_messages.items() if k not in master_messages} + removed = {k: v for k, v in master_messages.items() if k not in new_messages} + modified = { + k: {"old": master_messages[k], "new": v} + for k, v in new_messages.items() + if k in master_messages and master_messages[k] != v + } + return added, removed, modified + + +def _generate_report(report_path, added, removed, modified): + """Writes the comparison results to a text file.""" + with open(report_path, "w", encoding="utf-8") as f: + f.write( + f"Inno Setup String Update Report - {datetime.now(timezone.utc).isoformat(timespec='seconds').replace('+00:00','Z')}\n\n" + ) + f.write("=" * 50 + "\n\n") + + if not any([added, removed, modified]): + f.write( + "No changes detected between the new Default.isl and the project master.\n" + ) + return + + if added: + f.write("--- ADDED STRINGS ---\n") + for key, value in added.items(): + f.write(f"{key}={value}\n") + f.write("\n") + + if removed: + f.write("--- REMOVED STRINGS ---\n") + for key, value in removed.items(): + f.write(f"{key}={value}\n") + f.write("\n") + + if modified: + f.write("--- MODIFIED STRINGS ---\n") + for key, values in modified.items(): + f.write(f"{key}\n") + f.write(f" - OLD: {values['old']}\n") + f.write(f" + NEW: {values['new']}\n") + f.write("\n") + print(f"Update report generated: {report_path}") + + +def update_master_from_default(new_default_path, project_master_path): + """ + Compares a new Inno Setup Default.isl with the project's master English.isl, + merges changes, and generates a report. + """ + if not os.path.exists(new_default_path): + print(f"Error: New default file not found at {new_default_path}") + return + + if not os.path.exists(project_master_path): + print(f"Error: Project master file not found at {project_master_path}") + return + + # 1. Load configuration files + new_config = _load_config(new_default_path) + master_config = _load_config(project_master_path) + + # 2. Perform comparison + new_messages = dict(new_config["Messages"]) + master_messages = dict(master_config["Messages"]) + added, removed, modified = _compare_messages(new_messages, master_messages) + + # 3. Merge the configurations + final_config = configparser.ConfigParser( + allow_no_value=True, interpolation=None, strict=False + ) + final_config.optionxform = str # Preserve case + final_config.read_dict(new_config) + if "CustomMessages" in master_config: + final_config["CustomMessages"] = master_config["CustomMessages"] + if "LangOptions" in master_config: + final_config["LangOptions"] = master_config["LangOptions"] + + # 4. Write the updated master file + with open(project_master_path, "w", encoding="utf-8") as f: + f.write("; Master English messages for Kolibri Installer\n") + f.write( + f"; Last updated: {datetime.now(timezone.utc).isoformat(timespec='seconds').replace('+00:00','Z')}\n\n" + ) + final_config.write(f, space_around_delimiters=False) + print(f"Successfully updated master file: {project_master_path}") + + # 5. Generate the update report + _generate_report("update_report.txt", added, removed, modified) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Update the project's master Inno Setup language file from a new Default.isl." + ) + parser.add_argument( + "--new-default", + required=True, + help="Path to the Default.isl from the new Inno Setup installation.", + ) + parser.add_argument( + "--project-master", + required=True, + help="Path to the project's master English.isl file to be updated.", + ) + args = parser.parse_args() + + update_master_from_default(args.new_default, args.project_master) diff --git a/kolibri.spec b/kolibri.spec index e0d9142..f93184c 100644 --- a/kolibri.spec +++ b/kolibri.spec @@ -70,7 +70,7 @@ datas_list = [ if sys.platform == "win32": datas_list.extend([ ('src/kolibri_app/icons', 'kolibri_app/icons'), - ('nssm.exe', 'nssm') + (os.path.join('installer', 'nssm.exe'), 'nssm') ]) binaries_list = []