diff --git a/.github/workflows/fork-release.yml b/.github/workflows/fork-release.yml new file mode 100644 index 00000000..5a48cc39 --- /dev/null +++ b/.github/workflows/fork-release.yml @@ -0,0 +1,181 @@ +name: Build Fork Prerelease + +on: + push: + branches: [feat/one-click-extraction] + paths-ignore: + - '.github/workflows/**' + - 'scripts/sync-localizations.sh' + - '**/*.xcstrings' + workflow_dispatch: + inputs: + release_tag: + description: Optional tag (blank creates a unique build tag) + required: false + type: string + +permissions: + contents: write + +concurrency: + group: fork-release-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-release: + if: github.repository == 'n4dh1x/MacPacker' + runs-on: macos-26-intel + timeout-minutes: 60 + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + REQUESTED_TAG: ${{ inputs.release_tag }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + ref: ${{ github.sha }} + + - name: Choose a new prerelease tag + shell: bash + run: | + set -euo pipefail + release_tag="${REQUESTED_TAG:-one-click-build-${GITHUB_RUN_NUMBER}-${GITHUB_RUN_ATTEMPT}}" + git check-ref-format "refs/tags/$release_tag" + if git show-ref --verify --quiet "refs/tags/$release_tag"; then + echo "::error::The requested tag already exists. Choose a new tag." + exit 1 + fi + echo "RELEASE_TAG=$release_tag" >> "$GITHUB_ENV" + xcodebuild -version + swift --version + toolchain_hash=$(xcodebuild -version | shasum -a 256 | cut -c 1-12) + echo "TOOLCHAIN_HASH=$toolchain_hash" >> "$GITHUB_ENV" + + - name: Restore build caches + uses: actions/cache/restore@v4 + with: + path: | + Modules/.build + ${{ runner.temp }}/MacPackerBuild + key: fork-build-${{ runner.os }}-${{ runner.arch }}-${{ env.TOOLCHAIN_HASH }}-${{ hashFiles('Modules/Package.resolved', 'MacPacker.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }}-${{ github.sha }} + restore-keys: | + fork-build-${{ runner.os }}-${{ runner.arch }}-${{ env.TOOLCHAIN_HASH }}-${{ hashFiles('Modules/Package.resolved', 'MacPacker.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }}- + + - name: Install the test archive reader + run: bash .ci/install-sevenzip.sh + + - name: Run package tests + shell: bash + run: | + set -euo pipefail + swift test --package-path Modules 2>&1 | tee "$RUNNER_TEMP/swift-test.log" + + - name: Build the universal app with ad-hoc signing + shell: bash + run: | + set -euo pipefail + # This fork is downloaded from GitHub Releases. Its updater must not + # replace it with an upstream build that lacks the branch's features. + /usr/libexec/PlistBuddy -c 'Add :SUEnableAutomaticChecks bool false' MacPacker/Info.plist + /usr/libexec/PlistBuddy -c 'Add :SUAllowsAutomaticUpdates bool false' MacPacker/Info.plist + xcodebuild \ + -project MacPacker.xcodeproj \ + -scheme MacPacker \ + -configuration Release \ + -destination 'generic/platform=macOS' \ + -derivedDataPath "$RUNNER_TEMP/MacPackerBuild" \ + 'ARCHS=arm64 x86_64' \ + ONLY_ACTIVE_ARCH=NO \ + CODE_SIGN_STYLE=Manual \ + CODE_SIGN_IDENTITY=- \ + DEVELOPMENT_TEAM= \ + PROVISIONING_PROFILE_SPECIFIER= \ + BUNDLE_ID_SUFFIX=.fork \ + APP_URL_SCHEME=app.macpacker.fork \ + APP_GROUP_ID=UNSIGNED00.com.n4dh1x.MacPacker \ + build 2>&1 | tee "$RUNNER_TEMP/app-build.log" + + - name: Verify the app and package the download + shell: bash + run: | + set -euo pipefail + app="$RUNNER_TEMP/MacPackerBuild/Build/Products/Release/MacPacker.app" + bash scripts/check-architectures.sh "$app" + codesign --verify --deep --strict --verbose=2 "$app" + mkdir -p dist + ditto -c -k --sequesterRsrc --keepParent "$app" dist/MacPacker.zip + (cd dist && shasum -a 256 MacPacker.zip > SHA256SUMS.txt) + + - name: Save Xcode-generated localization catalogs + shell: bash + run: | + set -euo pipefail + bash scripts/sync-localizations.sh "$RUNNER_TEMP/MacPackerBuild" + git add -- \ + MacPacker/Localizable.xcstrings \ + MacPacker/LeanBytes.xcstrings \ + Modules/Sources/Core/Localizable.xcstrings \ + Modules/Sources/ArchivePreviewUI/Localizable.xcstrings + if ! git diff --cached --quiet; then + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git commit -m 'lang: save Xcode-generated localization strings' + git push origin "HEAD:$GITHUB_REF_NAME" + fi + echo "RELEASE_COMMIT=$(git rev-parse HEAD)" >> "$GITHUB_ENV" + + - name: Publish the GitHub prerelease + shell: bash + run: | + set -euo pipefail + cat > "$RUNNER_TEMP/release-notes.md" <&1 | tee "$RUNNER_TEMP/ui-$REVISION.log" + - name: Export screenshots + if: always() + run: | + if [[ -d "$RUNNER_TEMP/ui-$REVISION.xcresult" ]]; then + xcrun xcresulttool export attachments \ + --path "$RUNNER_TEMP/ui-$REVISION.xcresult" \ + --output-path "$RUNNER_TEMP/screenshots-$REVISION" + fi + - uses: actions/upload-artifact@v4 + if: always() + with: + name: one-click-ui-${{ matrix.revision }} + path: | + ${{ runner.temp }}/ui-${{ matrix.revision }}.log + ${{ runner.temp }}/screenshots-${{ matrix.revision }} + retention-days: 30 diff --git a/Config/products/macpacker.json b/Config/products/macpacker.json index f7e661ab..181ce0ea 100644 --- a/Config/products/macpacker.json +++ b/Config/products/macpacker.json @@ -38,6 +38,34 @@ { "version": "1.1.0", "items": [ + { + "type": "feat", + "highlight": true, + "title": { + "en": "One-click archive extraction", + "zh-Hans": "一键解压归档", + "fr": "Extraction d’archives en un clic", + "de": "Archive mit einem Klick entpacken", + "it": "Estrazione archivi con un clic", + "ja": "ワンクリックでアーカイブを展開", + "fa": "استخراج بایگانی با یک کلیک", + "pl": "Rozpakowywanie archiwów jednym kliknięciem", + "pt-BR": "Extração de arquivos com um clique", + "ru": "Распаковка архивов одним щелчком", + "uk": "Розпакування архівів одним клацанням", + "es-MX": "Extracción de archivos con un clic", + "ko": "클릭 한 번으로 압축 풀기", + "nl": "Archieven uitpakken met één klik", + "tr": "Tek tıkla arşiv çıkarma", + "vi": "Giải nén lưu trữ bằng một cú nhấp", + "ar": "استخراج الأرشيفات بنقرة واحدة", + "ca": "Extracció d’arxius amb un clic", + "el": "Εξαγωγή αρχείων με ένα κλικ", + "nb": "Pakk ut arkiver med ett klikk", + "zh-TW": "一鍵解壓縮封存檔" + }, + "issues": ["280"] + }, { "type": "feat", "highlight": true, diff --git a/MacPacker/AppDelegate.swift b/MacPacker/AppDelegate.swift index 7e177826..b859330f 100644 --- a/MacPacker/AppDelegate.swift +++ b/MacPacker/AppDelegate.swift @@ -23,6 +23,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { @AppStorage("updateBetaChannelOn") var updateBetaChannelOn: Bool = false @AppStorage("checkForUpdates") var checkForUpdates: SettingUpdateCheck = .automatically @AppStorage(Keys.quitOnLastWindowClosed) var quitOnLastWindowClosed: Bool = false + @AppStorage(Keys.oneClickExtraction) private var oneClickExtraction: Bool = false private var archiveWindowManager: ArchiveWindowManager? = nil private var extractionProgressWindowController: ExtractionProgressWindowController? = nil private var dropMenuBarItem: DropMenuBarItem? = nil @@ -88,11 +89,17 @@ final class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { // first check if this is an app url, and handle it accordingly let appUrl: AppUrl? = urls.first.flatMap { UrlParser().parse(appUrl: $0) } + let detector = ArchiveTypeDetector(catalog: appState.catalog) + let archivesToExtract = oneClickExtraction && appUrl == nil + ? urls.filter { $0.isFileURL && detector.detect(for: $0) != nil } + : [] // On a cold start this is what the launch was started for, so it // decides the launch windows. The welcome window goes on top of what // opens below. - let showsLaunchWindows = launch.started(for: appUrl == nil ? .openWith : .finderExtension) + let reason: Launch.Reason = appUrl != nil ? .finderExtension + : archivesToExtract.isEmpty ? .openWith : .oneClickExtraction + let showsLaunchWindows = launch.started(for: reason) if showsLaunchWindows { openLaunchWindow() } @@ -154,9 +161,21 @@ final class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject { return } + if let first = archivesToExtract.first, let archiveWindowManager { + let handler = AppUrlOneClickExtractionHandler( + destination: .saved(), catalog: appState.catalog, engineSelector: appState.engineSelector) + let request = AppUrl(action: .open, files: archivesToExtract, target: first.deletingLastPathComponent()) + Task { + await ExtractionProgressCenter.shared.run { + await handler.handle(appUrl: request, archiveWindowManager: archiveWindowManager) + } + if finderLaunchIsOver { NSApp.terminate(nil) } + } + } + // it is not an app url, therefore the assumption is that the app // was opened via Finder > right click > Open with... - for url in urls { + for url in urls where !archivesToExtract.contains(url) { log.notice("Open-with: opening \(url.lastPathComponent)") archiveWindowManager?.openArchiveWindow(for: url) } diff --git a/MacPacker/Core/UrlHandling/AppUrlExtractToChosenFolderHandler.swift b/MacPacker/Core/UrlHandling/AppUrlExtractToChosenFolderHandler.swift index c9c576d3..028aa1ee 100644 --- a/MacPacker/Core/UrlHandling/AppUrlExtractToChosenFolderHandler.swift +++ b/MacPacker/Core/UrlHandling/AppUrlExtractToChosenFolderHandler.swift @@ -29,7 +29,7 @@ class AppUrlExtractToChosenFolderHandler: AppUrlHandler { func handle(appUrl: AppUrl, archiveWindowManager: ArchiveWindowManager) async { log.notice("Extract-to handler: \(appUrl.files.count) archive(s)") - guard let destination = await chooseDestination(startingIn: appUrl.target) else { + guard let destination = await chooseExtractionDestination(startingIn: appUrl.target) else { log.notice("Extract-to cancelled") return } @@ -54,24 +54,4 @@ class AppUrlExtractToChosenFolderHandler: AppUrlHandler { NSWorkspace.shared.activateFileViewerSelecting(extracted) } } - - /// Asks where to extract. `nil` when the panel is cancelled. - private func chooseDestination(startingIn folder: URL) async -> URL? { - await withCheckedContinuation { continuation in - let panel = NSOpenPanel() - panel.canChooseFiles = false - panel.canChooseDirectories = true - panel.canCreateDirectories = true - panel.allowsMultipleSelection = false - panel.directoryURL = folder - panel.prompt = String(localized: .commonExtract) - panel.message = String(localized: .archiveExtractChooseDestination) - panel.level = .floating - NSApp.activate(ignoringOtherApps: true) - - panel.begin { response in - continuation.resume(returning: response == .OK ? panel.url : nil) - } - } - } } diff --git a/MacPacker/Core/UrlHandling/AppUrlHandler.swift b/MacPacker/Core/UrlHandling/AppUrlHandler.swift index 21ea7b4b..9908fb12 100644 --- a/MacPacker/Core/UrlHandling/AppUrlHandler.swift +++ b/MacPacker/Core/UrlHandling/AppUrlHandler.swift @@ -21,6 +21,26 @@ protocol AppUrlHandler { } extension AppUrlHandler { + /// Picking a destination also grants access to it in the sandbox. + func chooseExtractionDestination(startingIn folder: URL) async -> URL? { + await withCheckedContinuation { continuation in + let panel = NSOpenPanel() + panel.canChooseFiles = false + panel.canChooseDirectories = true + panel.canCreateDirectories = true + panel.allowsMultipleSelection = false + panel.directoryURL = folder + panel.prompt = String(localized: .commonExtract) + panel.message = String(localized: .archiveExtractChooseDestination) + panel.level = .floating + NSApp.activate(ignoringOtherApps: true) + + panel.begin { response in + continuation.resume(returning: response == .OK ? panel.url : nil) + } + } + } + /// Opens `archive`, extracts all of it into `destination` and waits for /// the job to end. Returns what the extraction added to `destination`, so /// the caller can select it in Finder. @@ -35,6 +55,7 @@ extension AppUrlHandler { _ archive: URL, into destination: URL, smart: Bool, + preservingExistingFiles: Bool = false, catalog: ArchiveTypeCatalog, engineSelector: ArchiveEngineSelectorProtocol ) async -> [URL] { @@ -55,10 +76,11 @@ extension AppUrlHandler { // extract(to:) raises isBusy before it returns and lowers it once the // job ends — done, cancelled or failed - state.extract(to: destination, smart: smart) + state.extract(to: destination, smart: smart, preservingExistingFiles: preservingExistingFiles) for await busy in state.$isBusy.values where !busy { break } + guard state.error == nil else { return [] } let added = folderContents(destination).filter { !before.contains($0) } if !added.isEmpty { @@ -66,12 +88,16 @@ extension AppUrlHandler { } // extracted over existing items: nothing is new, so point at what the // archive holds - return topLevel - .map { destination.appendingPathComponent($0) } - .filter { FileManager.default.fileExists(atPath: $0.path) } + return Sandbox.accessSync(url: destination) { + topLevel + .map { destination.appendingPathComponent($0) } + .filter { FileManager.default.fileExists(atPath: $0.path) } + } } } private func folderContents(_ folder: URL) -> [URL] { - (try? FileManager.default.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil)) ?? [] + Sandbox.accessSync(url: folder) { + (try? FileManager.default.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil)) ?? [] + } } diff --git a/MacPacker/Core/UrlHandling/AppUrlOneClickExtractionHandler.swift b/MacPacker/Core/UrlHandling/AppUrlOneClickExtractionHandler.swift new file mode 100644 index 00000000..a3a83b31 --- /dev/null +++ b/MacPacker/Core/UrlHandling/AppUrlOneClickExtractionHandler.swift @@ -0,0 +1,73 @@ +import AppKit +import Core +import FinderMenu +import Foundation +import tb + +private let log = tb.Logger(subsystem: "app.MacPacker", category: "extraction") + +/// Extracts files opened through Launch Services using the user's explicit destination. +final class AppUrlOneClickExtractionHandler: AppUrlHandler { + private let destination: OneClickExtractionDestination + private let catalog: ArchiveTypeCatalog + private let engineSelector: ArchiveEngineSelectorProtocol + + init(destination: OneClickExtractionDestination, catalog: ArchiveTypeCatalog, + engineSelector: ArchiveEngineSelectorProtocol) { + self.destination = destination + self.catalog = catalog + self.engineSelector = engineSelector + } + + func handle(appUrl: AppUrl, archiveWindowManager: ArchiveWindowManager) async { + let chosenFolder: URL? + if destination == .chooseFolder { + guard let folder = await chooseExtractionDestination(startingIn: appUrl.target) else { return } + Sandbox.storeBookmark(url: folder) + chosenFolder = folder + } else { + chosenFolder = nil + } + + let detector = ArchiveTypeDetector(catalog: catalog) + var extracted: [URL] = [] + var processedArchives: Set = [] + for archive in appUrl.files { + // Each source may be in a different folder. The grant also covers + // sibling volumes and writing beside the archive when requested. + guard await FolderAccessStore.shared.ensureAccess(forFileIn: archive) else { continue } + // Selecting several volumes of a split archive still extracts the + // archive once. Resolve after the grant so split markers are readable. + let canonicalArchive = detector.detect(for: archive)?.split.map { + SplitVolumeResolver.firstVolume(for: archive, split: $0) + } ?? archive + guard processedArchives.insert(canonicalArchive.standardizedFileURL).inserted, + let folder = chosenFolder ?? destination.directory(for: canonicalArchive, detector: detector) + else { continue } + + do { + try Sandbox.accessSync(url: folder) { + try FileManager.default.createDirectory(at: folder, withIntermediateDirectories: true) + } + } catch { + log.error("Could not create extraction folder", context: ["error": error.localizedDescription]) + NSApp.presentError(error) + continue + } + + // These destinations are explicit: Smart Extraction must not move + // same-folder output or add another container inside a named folder. + let output = await extractArchive( + archive, into: folder, smart: false, preservingExistingFiles: true, + catalog: catalog, engineSelector: engineSelector) + if destination == .archiveFolder, !output.isEmpty { + extracted.append(folder) + } else { + extracted += output + } + } + if !extracted.isEmpty { + NSWorkspace.shared.activateFileViewerSelecting(extracted) + } + } +} diff --git a/MacPacker/Features/Settings/GeneralSettingsView.swift b/MacPacker/Features/Settings/GeneralSettingsView.swift index f5c96a9e..54137fb5 100644 --- a/MacPacker/Features/Settings/GeneralSettingsView.swift +++ b/MacPacker/Features/Settings/GeneralSettingsView.swift @@ -20,6 +20,8 @@ struct GeneralSettingsView: View { @AppStorage(Keys.showMenuBarItem) var showMenuBarItem: Bool = false @AppStorage(Keys.rememberRecentArchives) var rememberRecentArchives: Bool = true @AppStorage(Keys.smartExtraction, store: .macPackerShared) var smartExtraction: Bool = true + @AppStorage(Keys.oneClickExtraction) var oneClickExtraction: Bool = false + @AppStorage(Keys.oneClickExtractionDestination) var oneClickDestination: OneClickExtractionDestination = .archiveFolder var body: some View { VStack(spacing: 8) { @@ -109,6 +111,31 @@ struct GeneralSettingsView: View { Divider() + HStack(alignment: .top) { + Text("One-click extraction", comment: "General settings label for automatically extracting archives opened from Finder.") + .frame(width: 200, alignment: .trailing) + + VStack(alignment: .leading, spacing: 8) { + Toggle(isOn: $oneClickExtraction) { + Text("Extract archives when opened", comment: "General settings toggle. Opening a recognized archive from Finder extracts it instead of showing the archive browser.") + } + Picker(selection: $oneClickDestination) { + Text("Same folder as the archive", comment: "One-click extraction destination: put the contents directly beside the archive.") + .tag(OneClickExtractionDestination.sameFolder) + Text("Folder named after the archive", comment: "One-click extraction destination: create a folder beside the archive using the archive's name.") + .tag(OneClickExtractionDestination.archiveFolder) + Text("Ask for a location", comment: "One-click extraction destination: show a folder picker each time archives are opened.") + .tag(OneClickExtractionDestination.chooseFolder) + } label: { + Text("Extract to", comment: "Label for the one-click extraction destination picker in General settings.") + } + .labelsHidden() + .disabled(!oneClickExtraction) + } + .padding(.leading, 8) + .frame(width: 240, alignment: .leading) + } + HStack(alignment: .top) { Text(.settingsSmartExtraction) .frame(width: 200, alignment: .trailing) diff --git a/MacPacker/Localizable.xcstrings b/MacPacker/Localizable.xcstrings index 46868947..64caafd6 100644 --- a/MacPacker/Localizable.xcstrings +++ b/MacPacker/Localizable.xcstrings @@ -1,6 +1,30 @@ { "sourceLanguage": "en", "strings": { + "Ask for a location": { + "comment": "One-click extraction destination: show a folder picker each time archives are opened.", + "extractionState": "manual" + }, + "Extract archives when opened": { + "comment": "General settings toggle. Opening a recognized archive from Finder extracts it instead of showing the archive browser.", + "extractionState": "manual" + }, + "Extract to": { + "comment": "Label for the one-click extraction destination picker in General settings.", + "extractionState": "manual" + }, + "Folder named after the archive": { + "comment": "One-click extraction destination: create a folder beside the archive using the archive's name.", + "extractionState": "manual" + }, + "One-click extraction": { + "comment": "General settings label for automatically extracting archives opened from Finder.", + "extractionState": "manual" + }, + "Same folder as the archive": { + "comment": "One-click extraction destination: put the contents directly beside the archive.", + "extractionState": "manual" + }, "appCompressionInProgress": { "comment": "Title of the alert shown when the user quits while Finder's \"Compress to …\" is still writing an archive.", "extractionState": "manual", @@ -35,7 +59,7 @@ "value": "A compression is still in progress" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "A compression is still in progress" @@ -71,13 +95,13 @@ "value": "A compression is still in progress" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", "value": "A compression is still in progress" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", "value": "A compression is still in progress" @@ -89,7 +113,7 @@ "value": "A compression is still in progress" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "A compression is still in progress" @@ -167,7 +191,7 @@ "value": "An extraction is still in progress" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Una extracción sigue en proceso" @@ -203,16 +227,16 @@ "value": "An extraction is still in progress" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "An extraction is still in progress" + "value": "En utpakking pågår fortsatt" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "En utpakking pågår fortsatt" + "value": "An extraction is still in progress" } }, "pl": { @@ -221,7 +245,7 @@ "value": "Rozpakowywanie nadal jest w toku" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "An extraction is still in progress" @@ -299,7 +323,7 @@ "value": "Quit Anyway" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Salir" @@ -335,16 +359,16 @@ "value": "그래도 종료" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Stop toch" + "value": "Avslutt uansett" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Avslutt uansett" + "value": "Stop toch" } }, "pl": { @@ -353,7 +377,7 @@ "value": "Zakończ mimo to" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Encerrar Mesmo Assim" @@ -431,7 +455,7 @@ "value": "Quitting stops the compression." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Quitting stops the compression." @@ -467,13 +491,13 @@ "value": "Quitting stops the compression." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", "value": "Quitting stops the compression." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", "value": "Quitting stops the compression." @@ -485,7 +509,7 @@ "value": "Quitting stops the compression." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Quitting stops the compression." @@ -563,7 +587,7 @@ "value": "Quitting now stops the extraction and may leave incomplete files at the destination." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Salir ahora detendrá la extracción y podría dejar archivos incompletos en el destino." @@ -599,16 +623,16 @@ "value": "Quitting now stops the extraction and may leave incomplete files at the destination." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Quitting now stops the extraction and may leave incomplete files at the destination." + "value": "Hvis du avslutter nå, stoppes utpakkingen, og det kan hende at ufullstendige filer blir liggende igjen på destinasjonen." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Hvis du avslutter nå, stoppes utpakkingen, og det kan hende at ufullstendige filer blir liggende igjen på destinasjonen." + "value": "Quitting now stops the extraction and may leave incomplete files at the destination." } }, "pl": { @@ -617,7 +641,7 @@ "value": "Zakończenie operacji rozpakowywania może spowodować niekompletność plików w miejscu docelowym." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Quitting now stops the extraction and may leave incomplete files at the destination." @@ -694,7 +718,7 @@ "value": "Delete the selected items from the archive" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Eliminar los elementos seleccionados del archivo comprimido" @@ -730,16 +754,16 @@ "value": "Delete the selected items from the archive" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Delete the selected items from the archive" + "value": "Slett de valgte elementene fra arkivet" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Slett de valgte elementene fra arkivet" + "value": "Delete the selected items from the archive" } }, "pl": { @@ -748,7 +772,7 @@ "value": "Usuń zaznaczone obiekty z archiwum" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Delete the selected items from the archive" @@ -826,7 +850,7 @@ "value": "Modified" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Modificación" @@ -862,16 +886,16 @@ "value": "수정일" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Bewerking" + "value": "Modifisert" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Modifisert" + "value": "Bewerking" } }, "pl": { @@ -880,7 +904,7 @@ "value": "Zmodyfikowano" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Modificado" @@ -958,7 +982,7 @@ "value": "Enclosing Folder" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Carpeta contenedora" @@ -994,16 +1018,16 @@ "value": "상위 폴더" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Bovenliggende map" + "value": "Omslutter mappe" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Omslutter mappe" + "value": "Bovenliggende map" } }, "pl": { @@ -1012,7 +1036,7 @@ "value": "Folder obejmujący" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Pasta Original" @@ -1090,7 +1114,7 @@ "value": "Open in New Window" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Abrir en una ventana nueva" @@ -1126,16 +1150,16 @@ "value": "새로운 윈도우에서 열기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Open in nieuw venster" + "value": "Åpne i nytt vindu" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Åpne i nytt vindu" + "value": "Open in nieuw venster" } }, "pl": { @@ -1144,7 +1168,7 @@ "value": "Otwórz w nowym oknie" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Abrir em Nova Janela" @@ -1222,7 +1246,7 @@ "value": "Quick Look" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Vista rápida" @@ -1258,13 +1282,13 @@ "value": "Quick Look" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", "value": "Quick Look" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", "value": "Quick Look" @@ -1276,7 +1300,7 @@ "value": "Szybki przegląd" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Visualização Rápida" @@ -1354,7 +1378,7 @@ "value": "Drop here to compress" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Suelta aquí para comprimir" @@ -1390,16 +1414,16 @@ "value": "압축을 하려면 여기에 끌어 놓으세요" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Sleep naar hier om in te pakken" + "value": "Slipp her for å komprimere" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Slipp her for å komprimere" + "value": "Sleep naar hier om in te pakken" } }, "pl": { @@ -1408,7 +1432,7 @@ "value": "Upuść tutaj, aby zarchiwizować." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Solte aqui para comprimir" @@ -1486,7 +1510,7 @@ "value": "Compress here" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Comprime aquí" @@ -1522,16 +1546,16 @@ "value": "여기에 압축하기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Comprimeer hier" + "value": "Komprimer her" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Komprimer her" + "value": "Comprimeer hier" } }, "pl": { @@ -1540,7 +1564,7 @@ "value": "Archiwizuj tutaj" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Comprimir Aqui" @@ -1618,7 +1642,7 @@ "value": "Keep on Top" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Mantener arriba" @@ -1654,16 +1678,16 @@ "value": "상단에 유지" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Houd bovenaan" + "value": "Hold deg på topp" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Hold deg på topp" + "value": "Houd bovenaan" } }, "pl": { @@ -1672,7 +1696,7 @@ "value": "Pozostaw na górze" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Manter em Primeiro Plano" @@ -1749,7 +1773,7 @@ "value": "Add files or folders to the archive" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Añadir archivos o carpetas al archivo comprimido" @@ -1785,16 +1809,16 @@ "value": "Add files or folders to the archive" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Add files or folders to the archive" + "value": "Legg til filer eller mapper i arkivet" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Legg til filer eller mapper i arkivet" + "value": "Add files or folders to the archive" } }, "pl": { @@ -1803,7 +1827,7 @@ "value": "Dodaj pliki lub foldery do archiwum" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Add files or folders to the archive" @@ -1881,7 +1905,7 @@ "value": "Archive info" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Información del archivo" @@ -1917,16 +1941,16 @@ "value": "압축 파일 정보" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Archive info" + "value": "Arkivinformasjon" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Arkivinformasjon" + "value": "Archive info" } }, "pl": { @@ -1935,7 +1959,7 @@ "value": "Informacje o archiwum" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Informações de Arquivo" @@ -2013,7 +2037,7 @@ "value": "Automatic" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Automáticamente" @@ -2049,16 +2073,16 @@ "value": "자동" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Automatisch" + "value": "Automatisk" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Automatisk" + "value": "Automatisch" } }, "pl": { @@ -2067,7 +2091,7 @@ "value": "Automatycznie" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Automaticamente" @@ -2145,7 +2169,7 @@ "value": "Change the password under Options…" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Cambia la contraseña en Opciones…" @@ -2181,16 +2205,16 @@ "value": "Change the password under Options…" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Change the password under Options…" + "value": "Endre passordet under Alternativer…" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Endre passordet under Alternativer…" + "value": "Change the password under Options…" } }, "pl": { @@ -2199,7 +2223,7 @@ "value": "Zmień hasło używając Opcji..." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Change the password under Options…" @@ -2277,7 +2301,7 @@ "value": "A zip password can only use letters A–Z, digits, spaces and common symbols. 7z takes any password." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "La contraseña de un archivo zip sólo puede contener letras A-Z, números, espacios y símbolos comunes. Los archivos 7z pueden tener cualquier contraseña." @@ -2313,16 +2337,16 @@ "value": "A zip password can only use letters A–Z, digits, spaces and common symbols. 7z takes any password." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "A zip password can only use letters A–Z, digits, spaces and common symbols. 7z takes any password." + "value": "Et postnummerpassord kan bare bruke bokstavene A–Å, sifre, mellomrom og vanlige symboler. 7z tar alle passord." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Et postnummerpassord kan bare bruke bokstavene A–Å, sifre, mellomrom og vanlige symboler. 7z tar alle passord." + "value": "A zip password can only use letters A–Z, digits, spaces and common symbols. 7z takes any password." } }, "pl": { @@ -2331,7 +2355,7 @@ "value": "Hasło ZIP może zawierać tylko znaki A-Z, cyfry, spacje i symbole ogólne. 7z akceptuje każde hasło." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "A zip password can only use letters A–Z, digits, spaces and common symbols. 7z takes any password." @@ -2409,7 +2433,7 @@ "value": "Create a new archive" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Crear un nuevo archivo comprimido" @@ -2445,16 +2469,16 @@ "value": "Create a new archive" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Create a new archive" + "value": "Opprett et nytt arkiv" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Opprett et nytt arkiv" + "value": "Create a new archive" } }, "pl": { @@ -2463,7 +2487,7 @@ "value": "Utwórz nowe archiwum" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Create a new archive" @@ -2541,7 +2565,7 @@ "value": "Choose where to extract" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Selecciona a donde extraer" @@ -2577,16 +2601,16 @@ "value": "Choose where to extract" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Choose where to extract" + "value": "Velg hvor du skal utvinne" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Velg hvor du skal utvinne" + "value": "Choose where to extract" } }, "pl": { @@ -2595,7 +2619,7 @@ "value": "Wybierz miejsce rozpakowania" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Choose where to extract" @@ -2673,7 +2697,7 @@ "value": "%@ left" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Quedan %@" @@ -2709,16 +2733,16 @@ "value": "%@ left" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "%@ left" + "value": "%@ gjenstår" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "%@ gjenstår" + "value": "%@ left" } }, "pl": { @@ -2727,7 +2751,7 @@ "value": "%@ pozostało" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "%@ left" @@ -2805,7 +2829,7 @@ "value": "With AES-256, a zip password can be at most %lld characters long." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Con AES-256, la contraseña de un zip puede tener como máximo %lld caracteres." @@ -2841,16 +2865,16 @@ "value": "With AES-256, a zip password can be at most %lld characters long." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "With AES-256, a zip password can be at most %lld characters long." + "value": "Med AES-256 kan et postnummerpassord være maksimalt %lld tegn langt." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Med AES-256 kan et postnummerpassord være maksimalt %lld tegn langt." + "value": "With AES-256, a zip password can be at most %lld characters long." } }, "pl": { @@ -2859,7 +2883,7 @@ "value": "Z szyfrowaniem AES-256 hasło zip może mieć do %lld znaków." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "With AES-256, a zip password can be at most %lld characters long." @@ -2937,7 +2961,7 @@ "value": "ZipCrypto is easily broken. Pick it only for tools that cannot open AES-256." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "ZipCrypto falla regularmente. Úsalo solo para herramientas que no puedan abrir archivos cifrados con AES-256." @@ -2973,16 +2997,16 @@ "value": "ZipCrypto is easily broken. Pick it only for tools that cannot open AES-256." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "ZipCrypto is easily broken. Pick it only for tools that cannot open AES-256." + "value": "ZipCrypto er lett å ødelegge. Velg det bare for verktøy som ikke kan åpne AES-256." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "ZipCrypto er lett å ødelegge. Velg det bare for verktøy som ikke kan åpne AES-256." + "value": "ZipCrypto is easily broken. Pick it only for tools that cannot open AES-256." } }, "pl": { @@ -2991,7 +3015,7 @@ "value": "ZipCrypto można łatwo złamać. Używaj tylko tam, gdzie nie można użyć AES-256." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "ZipCrypto is easily broken. Pick it only for tools that cannot open AES-256." @@ -3069,7 +3093,7 @@ "value": "the archive" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "el archivo comprimido" @@ -3105,16 +3129,16 @@ "value": "the archive" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "the archive" + "value": "arkivet" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "arkivet" + "value": "the archive" } }, "pl": { @@ -3123,7 +3147,7 @@ "value": "archiwum" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "the archive" @@ -3201,7 +3225,7 @@ "value": "Dictionary size" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Tamaño del diccionario" @@ -3237,16 +3261,16 @@ "value": "사전 크기(D)" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Woordenboekgrootte" + "value": "Ordbokstørrelse" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Ordbokstørrelse" + "value": "Woordenboekgrootte" } }, "pl": { @@ -3255,7 +3279,7 @@ "value": "Rozmiar słownika" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Tamanho do dicionário" @@ -3333,7 +3357,7 @@ "value": "Don't Save" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "No guardar" @@ -3369,16 +3393,16 @@ "value": "저장하지 않음" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Bewaar niet" + "value": "Ikke lagre" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Ikke lagre" + "value": "Bewaar niet" } }, "pl": { @@ -3387,7 +3411,7 @@ "value": "Nie zachowuj" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Não Salvar" @@ -3465,7 +3489,7 @@ "value": "Don't split" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "No dividir" @@ -3501,16 +3525,16 @@ "value": "Don't split" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Don't split" + "value": "Ikke del opp" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Ikke del opp" + "value": "Don't split" } }, "pl": { @@ -3519,7 +3543,7 @@ "value": "Nie rozdzielaj" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Don't split" @@ -3597,7 +3621,7 @@ "value": "Encrypt file names" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Cifrar nombres de archivo" @@ -3633,16 +3657,16 @@ "value": "파일 이름 암호화" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Bestandsnamen versleutelen" + "value": "Krypter filnavn" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Krypter filnavn" + "value": "Bestandsnamen versleutelen" } }, "pl": { @@ -3651,7 +3675,7 @@ "value": "Zaszyfruj nazwy plików" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Encriptar nomes de ficheiros" @@ -3729,7 +3753,7 @@ "value": "File names stay readable in a zip archive. 7z can encrypt them too." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "En archivos zip los nombres de los archivos siguen siendo visibles. En archivos 7z pueden ser cifrados." @@ -3765,16 +3789,16 @@ "value": "File names stay readable in a zip archive. 7z can encrypt them too." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "File names stay readable in a zip archive. 7z can encrypt them too." + "value": "Filnavn forblir lesbare i et zip-arkiv. 7z kan også kryptere dem." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Filnavn forblir lesbare i et zip-arkiv. 7z kan også kryptere dem." + "value": "File names stay readable in a zip archive. 7z can encrypt them too." } }, "pl": { @@ -3783,7 +3807,7 @@ "value": "Nazwy plików będą odczytywalne w archiwum ZIP. 7z potrafi je szyfrować." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "File names stay readable in a zip archive. 7z can encrypt them too." @@ -3861,7 +3885,7 @@ "value": "Encryption method" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Método de cifrado" @@ -3897,16 +3921,16 @@ "value": "암호화 방법" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Versleutelingsmethodes" + "value": "Krypteringsmetode" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Krypteringsmetode" + "value": "Versleutelingsmethodes" } }, "pl": { @@ -3915,7 +3939,7 @@ "value": "Sposób szyfrowania" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Método de encriptação" @@ -3993,7 +4017,7 @@ "value": "Exclude .DS_Store files" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Excluir archivos .DS_Store" @@ -4029,16 +4053,16 @@ "value": "Exclude .DS_Store files" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Exclude .DS_Store files" + "value": "Ekskluder .DS_Store-filer" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Ekskluder .DS_Store-filer" + "value": "Exclude .DS_Store files" } }, "pl": { @@ -4047,7 +4071,7 @@ "value": "Wyklucz pliki .DS_Store" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Exclude .DS_Store files" @@ -4125,7 +4149,7 @@ "value": "Format" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Formato" @@ -4161,16 +4185,16 @@ "value": "포맷" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Formaat" + "value": "Format" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Format" + "value": "Formaat" } }, "pl": { @@ -4179,7 +4203,7 @@ "value": "Format" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Formato" @@ -4257,7 +4281,7 @@ "value": "Fast" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Rápida" @@ -4293,16 +4317,16 @@ "value": "빠르게" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Snel" + "value": "Raskt" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Raskt" + "value": "Snel" } }, "pl": { @@ -4311,7 +4335,7 @@ "value": "Szybko" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Rápida" @@ -4389,7 +4413,7 @@ "value": "Fastest" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "El más rápido" @@ -4425,16 +4449,16 @@ "value": "가장 빠름" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Snelst" + "value": "Raskest" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Raskest" + "value": "Snelst" } }, "pl": { @@ -4443,7 +4467,7 @@ "value": "Najszybsza" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Muito rápido" @@ -4521,7 +4545,7 @@ "value": "Maximum" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Máxima" @@ -4557,16 +4581,16 @@ "value": "최대" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Maximaal" + "value": "Maksimalt" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Maksimalt" + "value": "Maximaal" } }, "pl": { @@ -4575,7 +4599,7 @@ "value": "Maksymalna" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Máxima" @@ -4653,7 +4677,7 @@ "value": "Normal" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Normal" @@ -4689,16 +4713,16 @@ "value": "보통" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Normaal" + "value": "Normal" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Normal" + "value": "Normaal" } }, "pl": { @@ -4707,7 +4731,7 @@ "value": "Normalna" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Normal" @@ -4785,7 +4809,7 @@ "value": "Store" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Sin compresión" @@ -4821,16 +4845,16 @@ "value": "압축 안 함" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Geen compressie" + "value": "Lagre" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Lagre" + "value": "Geen compressie" } }, "pl": { @@ -4839,7 +4863,7 @@ "value": "Bez kompresji" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Sem compressão" @@ -4917,7 +4941,7 @@ "value": "Ultra" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Ultra" @@ -4953,13 +4977,13 @@ "value": "가장 느림" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", "value": "Ultra" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", "value": "Ultra" @@ -4971,7 +4995,7 @@ "value": "Ultra" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Ultra" @@ -5049,7 +5073,7 @@ "value": "Method" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Método" @@ -5085,16 +5109,16 @@ "value": "방법" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Methode" + "value": "Metode" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Metode" + "value": "Methode" } }, "pl": { @@ -5103,7 +5127,7 @@ "value": "Tryb" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Método" @@ -5181,7 +5205,7 @@ "value": "Non-solid" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "No sólido" @@ -5217,16 +5241,16 @@ "value": "솔리드 사용 않함" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Niet-compact" + "value": "Ikke-fast" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Ikke-fast" + "value": "Niet-compact" } }, "pl": { @@ -5235,7 +5259,7 @@ "value": "Nieciągły" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Não sólido" @@ -5313,7 +5337,7 @@ "value": "Repeat" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Repetir" @@ -5349,16 +5373,16 @@ "value": "암호 다시 입력" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Herhaal" + "value": "Gjenta" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Gjenta" + "value": "Herhaal" } }, "pl": { @@ -5367,7 +5391,7 @@ "value": "Powtórz" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Repetir" @@ -5445,7 +5469,7 @@ "value": "Solid" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Sólido" @@ -5481,16 +5505,16 @@ "value": "솔리드" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Compact" + "value": "Fast" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Fast" + "value": "Compact" } }, "pl": { @@ -5499,7 +5523,7 @@ "value": "Ciągły" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Sólido" @@ -5577,7 +5601,7 @@ "value": "Solid block size" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Tamaño de bloque sólido" @@ -5613,16 +5637,16 @@ "value": "솔리드 블록 크기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Grootte compact blok" + "value": "Helblokkstørrelse" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Helblokkstørrelse" + "value": "Grootte compact blok" } }, "pl": { @@ -5631,7 +5655,7 @@ "value": "Rozmiar bloku ciągłego" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Tamanho dos blocos sólidos" @@ -5709,7 +5733,7 @@ "value": "Split into volumes" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Dividir en volúmenes" @@ -5745,16 +5769,16 @@ "value": "Split into volumes" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Split into volumes" + "value": "Del opp i volumer" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Del opp i volumer" + "value": "Split into volumes" } }, "pl": { @@ -5763,7 +5787,7 @@ "value": "Dziel na woluminy" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Split into volumes" @@ -5841,7 +5865,7 @@ "value": "Do you want to save the changes you made to “%@”?" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Deseas guardar los cambios que hiciste a “%@”?" @@ -5877,16 +5901,16 @@ "value": "Do you want to save the changes you made to “%@”?" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Do you want to save the changes you made to “%@”?" + "value": "Vil du lagre endringene du gjorde i «%@»?" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Vil du lagre endringene du gjorde i «%@»?" + "value": "Do you want to save the changes you made to “%@”?" } }, "pl": { @@ -5895,7 +5919,7 @@ "value": "Czy chcesz zapisać zmiany, które wprowadziłeś do “%@”?" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Do you want to save the changes you made to “%@”?" @@ -5973,7 +5997,7 @@ "value": "Your changes will be lost if you don’t save them." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Tus cambios se perderán si no los guardas." @@ -6009,16 +6033,16 @@ "value": "Your changes will be lost if you don’t save them." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Your changes will be lost if you don’t save them." + "value": "Endringene dine vil gå tapt hvis du ikke lagrer dem." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Endringene dine vil gå tapt hvis du ikke lagrer dem." + "value": "Your changes will be lost if you don’t save them." } }, "pl": { @@ -6027,7 +6051,7 @@ "value": "Twoje zmiany zostaną utracone, jeśli ich nie zapiszesz." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Your changes will be lost if you don’t save them." @@ -6105,7 +6129,7 @@ "value": "Word size" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Tamaño de la palabra" @@ -6141,16 +6165,16 @@ "value": "단어 크기(W)" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Woordgrootte" + "value": "Ordstørrelse" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Ordstørrelse" + "value": "Woordgrootte" } }, "pl": { @@ -6159,7 +6183,7 @@ "value": "Rozmiar słowa" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Tamanho da palavra" @@ -6237,7 +6261,7 @@ "value": "Date Modified" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Fecha de modificación" @@ -6273,16 +6297,16 @@ "value": "수정 날짜" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Date Modified" + "value": "Dato endret" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Dato endret" + "value": "Date Modified" } }, "pl": { @@ -6291,7 +6315,7 @@ "value": "Data modyfikacji" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Data de Modificação" @@ -6369,7 +6393,7 @@ "value": "Name" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Nombre" @@ -6405,16 +6429,16 @@ "value": "이름" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Name" + "value": "Navn" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Navn" + "value": "Name" } }, "pl": { @@ -6423,7 +6447,7 @@ "value": "Nazwa" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Nome" @@ -6501,7 +6525,7 @@ "value": "Packed Size" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Tamaño comprimido" @@ -6537,16 +6561,16 @@ "value": "압축 크기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Packed Size" + "value": "Pakket størrelse" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Pakket størrelse" + "value": "Packed Size" } }, "pl": { @@ -6555,7 +6579,7 @@ "value": "Rozmiar po spakowaniu" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Tamanho total" @@ -6633,7 +6657,7 @@ "value": "Permissions" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Permisos" @@ -6669,16 +6693,16 @@ "value": "권한" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Permissions" + "value": "Tillatelser" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Tillatelser" + "value": "Permissions" } }, "pl": { @@ -6687,7 +6711,7 @@ "value": "Uprawnienia" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Permissões" @@ -6765,7 +6789,7 @@ "value": "Size" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Tamaño" @@ -6801,16 +6825,16 @@ "value": "원본 크기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Size" + "value": "Størrelse" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Størrelse" + "value": "Size" } }, "pl": { @@ -6819,7 +6843,7 @@ "value": "Rozmiar" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Tamanho" @@ -6897,7 +6921,7 @@ "value": "About %@" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Acerca de %@" @@ -6933,16 +6957,16 @@ "value": "%@ 정보" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "About %@" + "value": "Om %@" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Om %@" + "value": "About %@" } }, "pl": { @@ -6951,7 +6975,7 @@ "value": "O %@" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Sobre %@" @@ -7029,7 +7053,7 @@ "value": "Acknowledgements" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Reconocimientos" @@ -7065,16 +7089,16 @@ "value": "오픈소스 라이선스" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Acknowledgements" + "value": "Takksigelser" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Takksigelser" + "value": "Acknowledgements" } }, "pl": { @@ -7083,7 +7107,7 @@ "value": "Podziękowania" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Reconhecimentos" @@ -7161,7 +7185,7 @@ "value": "Add" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Agregar" @@ -7197,16 +7221,16 @@ "value": "추가" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Add" + "value": "Legg til" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Legg til" + "value": "Add" } }, "pl": { @@ -7215,7 +7239,7 @@ "value": "Dodaj" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Adicionar" @@ -7293,7 +7317,7 @@ "value": "Add to archive..." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Agregar al archivo comprimido..." @@ -7329,16 +7353,16 @@ "value": "압축파일에 추가..." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Toevoegen aan archief..." + "value": "Legg til i arkivet..." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Legg til i arkivet..." + "value": "Toevoegen aan archief..." } }, "pl": { @@ -7347,7 +7371,7 @@ "value": "Dodaj do archiwum..." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Adicionar ao arquivo..." @@ -7425,7 +7449,7 @@ "value": "Add to “%@”" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Agregar a “%@”" @@ -7461,16 +7485,16 @@ "value": "‘%@’에 추가" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Add to “%@”" + "value": "Legg til i «%@»" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Legg til i «%@»" + "value": "Add to “%@”" } }, "pl": { @@ -7479,7 +7503,7 @@ "value": "Dodaj do “%@”" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Adicionar a “%@”" @@ -7557,7 +7581,7 @@ "value": "Back" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Atrás" @@ -7593,16 +7617,16 @@ "value": "뒤로" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Vorige" + "value": "Tilbake" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Tilbake" + "value": "Vorige" } }, "pl": { @@ -7611,7 +7635,7 @@ "value": "Wróć" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Voltar" @@ -7689,7 +7713,7 @@ "value": "Bottom" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Abajo" @@ -7725,16 +7749,16 @@ "value": "하단" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Onder" + "value": "Bunn" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Bunn" + "value": "Onder" } }, "pl": { @@ -7743,7 +7767,7 @@ "value": "na dole" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Inferior" @@ -7821,7 +7845,7 @@ "value": "Cancel" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Cancelar" @@ -7857,16 +7881,16 @@ "value": "Cancel" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Annuleren" + "value": "Avbryt" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Avbryt" + "value": "Annuleren" } }, "pl": { @@ -7875,7 +7899,7 @@ "value": "Anuluj" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Cancel" @@ -7953,7 +7977,7 @@ "value": "Clear" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Borrar" @@ -7989,16 +8013,16 @@ "value": "Clear" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Clear" + "value": "Fjern" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Fjern" + "value": "Clear" } }, "pl": { @@ -8007,7 +8031,7 @@ "value": "Wyczyść" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Clear" @@ -8084,7 +8108,7 @@ "value": "Compress Contents of \"%@\"" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Comprimir el contenido de \"%@\"" @@ -8120,16 +8144,16 @@ "value": "Compress Contents of \"%@\"" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Compress Contents of \"%@\"" + "value": "Komprimer innholdet i «%@»" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Komprimer innholdet i «%@»" + "value": "Compress Contents of \"%@\"" } }, "pl": { @@ -8138,7 +8162,7 @@ "value": "Spakuj zawartość \"%@\"" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Compress Contents of \"%@\"" @@ -8215,7 +8239,7 @@ "value": "Compress to \"%@\"" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Comprimir en \"%@\"" @@ -8251,16 +8275,16 @@ "value": "Compress to \"%@\"" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Compress to \"%@\"" + "value": "Komprimer til «%@»" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Komprimer til «%@»" + "value": "Compress to \"%@\"" } }, "pl": { @@ -8269,7 +8293,7 @@ "value": "Spakuj do \"%@\"" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Compress to \"%@\"" @@ -8347,7 +8371,7 @@ "value": "Compressing" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Comprimiendo" @@ -8383,16 +8407,16 @@ "value": "압축하는 중" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Bezig met comprimeren" + "value": "Komprimerer" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Komprimerer" + "value": "Bezig met comprimeren" } }, "pl": { @@ -8401,7 +8425,7 @@ "value": "Kompresowanie" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Comprimindo" @@ -8479,7 +8503,7 @@ "value": "Compression" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Compresión" @@ -8515,16 +8539,16 @@ "value": "압축" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Inpakken" + "value": "Kompresjon" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Kompresjon" + "value": "Inpakken" } }, "pl": { @@ -8533,7 +8557,7 @@ "value": "Archiwizacja" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Compressão" @@ -8611,7 +8635,7 @@ "value": "Continue" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Continuar" @@ -8647,16 +8671,16 @@ "value": "계속" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Continue" + "value": "Fortsett" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Fortsett" + "value": "Continue" } }, "pl": { @@ -8665,7 +8689,7 @@ "value": "Dalej" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Continuar" @@ -8743,7 +8767,7 @@ "value": "Delete" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Eliminar" @@ -8779,16 +8803,16 @@ "value": "삭제" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Verwijder" + "value": "Slett" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Slett" + "value": "Verwijder" } }, "pl": { @@ -8797,7 +8821,7 @@ "value": "Usuń" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Apagar" @@ -8875,7 +8899,7 @@ "value": "Disabled" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Deshabilitado" @@ -8911,16 +8935,16 @@ "value": "비활성화" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Disabled" + "value": "Deaktivert" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Deaktivert" + "value": "Disabled" } }, "pl": { @@ -8929,7 +8953,7 @@ "value": "Wyłączone" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Desativado" @@ -9007,7 +9031,7 @@ "value": "Done" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Listo" @@ -9043,16 +9067,16 @@ "value": "완료" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Ferdig" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Ferdig" + "value": "OK" } }, "pl": { @@ -9061,7 +9085,7 @@ "value": "OK" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "OK" @@ -9139,7 +9163,7 @@ "value": "enabled" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Habilitado" @@ -9175,16 +9199,16 @@ "value": "활성화" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "enabled" + "value": "Aktivert" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Aktivert" + "value": "enabled" } }, "pl": { @@ -9193,7 +9217,7 @@ "value": "Włączone" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Ativado" @@ -9271,7 +9295,7 @@ "value": "Extract" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Extraer" @@ -9307,16 +9331,16 @@ "value": "압축 풀기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Extraheren" + "value": "Utpakk" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Utpakk" + "value": "Extraheren" } }, "pl": { @@ -9325,7 +9349,7 @@ "value": "Wyodrębnij" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Extrair" @@ -9403,7 +9427,7 @@ "value": "Extract archive" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Extraer archivo" @@ -9439,16 +9463,16 @@ "value": "압축 풀기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Extract archive" + "value": "Pakk ut arkivet" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Pakk ut arkivet" + "value": "Extract archive" } }, "pl": { @@ -9457,7 +9481,7 @@ "value": "Rozpakuj archiwum" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Extrair Arquivo" @@ -9535,7 +9559,7 @@ "value": "Extract Here" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Extraer aquí" @@ -9571,16 +9595,16 @@ "value": "여기에 압축 풀기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Hier uitpakken" + "value": "Utdrag her" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Utdrag her" + "value": "Hier uitpakken" } }, "pl": { @@ -9589,7 +9613,7 @@ "value": "Wypakuj tutaj" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Extrair para aqui" @@ -9667,7 +9691,7 @@ "value": "Extract selected" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Extraer selección" @@ -9703,16 +9727,16 @@ "value": "선택 항목 압축 풀기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Extract selected" + "value": "Uttrekk valgt" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Uttrekk valgt" + "value": "Extract selected" } }, "pl": { @@ -9721,7 +9745,7 @@ "value": "Rozpakuj zaznaczone" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Extrair seleção" @@ -9798,7 +9822,7 @@ "value": "Extract to \"%@\"" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Extraer en \"%@\"" @@ -9834,16 +9858,16 @@ "value": "Extract to \"%@\"" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Extract to \"%@\"" + "value": "Pakk ut til «%@»" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Pakk ut til «%@»" + "value": "Extract to \"%@\"" } }, "pl": { @@ -9852,7 +9876,7 @@ "value": "Rozpakuj do \"%@\"" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Extract to \"%@\"" @@ -9930,7 +9954,7 @@ "value": "Extracting" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Extrayendo" @@ -9966,16 +9990,16 @@ "value": "Extracting" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Extracting" + "value": "Utvinning" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Utvinning" + "value": "Extracting" } }, "pl": { @@ -9984,7 +10008,7 @@ "value": "Wypakowanie" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Extracting" @@ -10062,7 +10086,7 @@ "value": "Find" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Buscar" @@ -10098,16 +10122,16 @@ "value": "찾기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Zoek" + "value": "Finn" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Finn" + "value": "Zoek" } }, "pl": { @@ -10116,7 +10140,7 @@ "value": "Znajdź" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Buscar" @@ -10194,7 +10218,7 @@ "value": "Grant Access" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Permitir acceso" @@ -10230,16 +10254,16 @@ "value": "Grant Access" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Grant Access" + "value": "Gi tilgang" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Gi tilgang" + "value": "Grant Access" } }, "pl": { @@ -10248,7 +10272,7 @@ "value": "Udziel dostępu" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Grant Access" @@ -10326,7 +10350,7 @@ "value": "Help with translation" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Ayuda a traducir" @@ -10362,16 +10386,16 @@ "value": "Help with translation" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Help with translation" + "value": "Hjelp til med oversetting" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Hjelp til med oversetting" + "value": "Help with translation" } }, "pl": { @@ -10380,7 +10404,7 @@ "value": "Pomoc w tłumaczeniu" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Help with translation" @@ -10458,7 +10482,7 @@ "value": "Legal Notice" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Aviso legal" @@ -10494,16 +10518,16 @@ "value": "법적 고지" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Juridische informatie" + "value": "Juridisk merknad" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Juridisk merknad" + "value": "Juridische informatie" } }, "pl": { @@ -10512,7 +10536,7 @@ "value": "Nota prawna" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Aviso legal" @@ -10674,7 +10698,7 @@ } } }, - "es-mx": { + "es-MX": { "variations": { "plural": { "many": { @@ -10788,37 +10812,37 @@ } } }, - "nl": { + "nb": { "variations": { "plural": { "one": { "stringUnit": { "state": "translated", - "value": "%lld item" + "value": "%lld element" } }, "other": { "stringUnit": { "state": "translated", - "value": "" + "value": "%lld elementer" } } } } }, - "no": { + "nl": { "variations": { "plural": { "one": { "stringUnit": { "state": "translated", - "value": "%lld element" + "value": "%lld item" } }, "other": { "stringUnit": { "state": "translated", - "value": "%lld elementer" + "value": "" } } } @@ -10854,7 +10878,7 @@ } } }, - "pt-br": { + "pt-BR": { "variations": { "plural": { "many": { @@ -11028,7 +11052,7 @@ "value": "Learn more…" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Obtén detalles…" @@ -11064,16 +11088,16 @@ "value": "더 알⁠아⁠보⁠기…" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Meer informatie…" + "value": "Finn ut mer…" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Finn ut mer…" + "value": "Meer informatie…" } }, "pl": { @@ -11082,7 +11106,7 @@ "value": "Więcej informacji…" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Saiba mais…" @@ -11160,7 +11184,7 @@ "value": "More" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Más" @@ -11196,16 +11220,16 @@ "value": "더보기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "More" + "value": "Mer" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Mer" + "value": "More" } }, "pl": { @@ -11214,7 +11238,7 @@ "value": "Więcej" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Mais" @@ -11292,7 +11316,7 @@ "value": "New Archive" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Crear archivo comprimido" @@ -11328,16 +11352,16 @@ "value": "New Archive" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Nieuw Archief" + "value": "Nytt arkiv" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Nytt arkiv" + "value": "Nieuw Archief" } }, "pl": { @@ -11346,7 +11370,7 @@ "value": "Nowe archiwum" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "New Archive" @@ -11424,7 +11448,7 @@ "value": "New %@ Window" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Nueva ventana de %@" @@ -11460,16 +11484,16 @@ "value": "새 %@ 윈도우" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "New %@ Window" + "value": "Nytt %@-vindu" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Nytt %@-vindu" + "value": "New %@ Window" } }, "pl": { @@ -11478,7 +11502,7 @@ "value": "Nowe %@ Okno" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "New %@ Window" @@ -11556,7 +11580,7 @@ "value": "None" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Ninguno" @@ -11592,16 +11616,16 @@ "value": "없음" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Geen" + "value": "Ingen" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Ingen" + "value": "Geen" } }, "pl": { @@ -11610,7 +11634,7 @@ "value": "Brak" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Nenhuma" @@ -11687,7 +11711,7 @@ "value": "Nothing selected" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Nada seleccionado" @@ -11723,16 +11747,16 @@ "value": "선택된 항목 없음" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Niets geselecteerd" + "value": "Ingenting er valgt" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Ingenting er valgt" + "value": "Niets geselecteerd" } }, "pl": { @@ -11741,7 +11765,7 @@ "value": "Nic nie jest zaznaczone" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Não há nada selecionado" @@ -11819,7 +11843,7 @@ "value": "OK" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Aceptar" @@ -11855,13 +11879,13 @@ "value": "확인" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", "value": "OK" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", "value": "OK" @@ -11873,7 +11897,7 @@ "value": "OK" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "OK" @@ -11951,7 +11975,7 @@ "value": "Open" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Abrir" @@ -11987,16 +12011,16 @@ "value": "열기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Openen" + "value": "Åpne" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Åpne" + "value": "Openen" } }, "pl": { @@ -12005,7 +12029,7 @@ "value": "Otwórz z dysku" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Abrir" @@ -12083,7 +12107,7 @@ "value": "Open Archive" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Abrir archivo comprimido" @@ -12119,16 +12143,16 @@ "value": "압축 파일 열기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Archief openen" + "value": "Åpne arkivet" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Åpne arkivet" + "value": "Archief openen" } }, "pl": { @@ -12137,7 +12161,7 @@ "value": "Otwórz archiwum" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Abrir arquivo" @@ -12214,7 +12238,7 @@ "value": "Open %lld Archives" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Abrir %lld archivos comprimidos" @@ -12250,16 +12274,16 @@ "value": "Open %lld Archives" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Open %lld Archives" + "value": "Åpne %lld-arkiver" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Åpne %lld-arkiver" + "value": "Open %lld Archives" } }, "pl": { @@ -12268,7 +12292,7 @@ "value": "Otwórz %lld archiwa" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Open %lld Archives" @@ -12346,7 +12370,7 @@ "value": "Options" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Opciones" @@ -12382,16 +12406,16 @@ "value": "옵션(O)" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Voorkeuren" + "value": "Alternativer" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Alternativer" + "value": "Voorkeuren" } }, "pl": { @@ -12400,7 +12424,7 @@ "value": "Opcje" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Opções" @@ -12478,7 +12502,7 @@ "value": "Password:" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Contraseña:" @@ -12514,16 +12538,16 @@ "value": "Password:" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Wachtwoord:" + "value": "Passord:" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Passord:" + "value": "Wachtwoord:" } }, "pl": { @@ -12532,7 +12556,7 @@ "value": "Hasło:" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Senha:" @@ -12610,7 +12634,7 @@ "value": "“%@” is password protected." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "“%@” está protegido con contraseña." @@ -12646,16 +12670,16 @@ "value": "'%@'은(는) 암호로 보호되어 있습니다." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "“%@” is password protected." + "value": "«%@» er passordbeskyttet." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "«%@» er passordbeskyttet." + "value": "“%@” is password protected." } }, "pl": { @@ -12664,7 +12688,7 @@ "value": "„%@” jest chroniony hasłem." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "“%@” está protegido por senha." @@ -12742,7 +12766,7 @@ "value": "Preview" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Vista previa" @@ -12778,16 +12802,16 @@ "value": "미리보기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Preview" + "value": "Forhåndsvisning" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Forhåndsvisning" + "value": "Preview" } }, "pl": { @@ -12796,7 +12820,7 @@ "value": "Podgląd" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Pré Visualização" @@ -12874,7 +12898,7 @@ "value": "Privacy" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Privacidad" @@ -12910,16 +12934,16 @@ "value": "개인정보 보호" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Privacy" + "value": "Privatliv" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Privatliv" + "value": "Privacy" } }, "pl": { @@ -12928,7 +12952,7 @@ "value": "Prywatność" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Privacidade" @@ -13006,7 +13030,7 @@ "value": "Quick Compress" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Compresión rápida" @@ -13042,16 +13066,16 @@ "value": "Quick Compress" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Quick Compress" + "value": "Hurtigkomprimering" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Hurtigkomprimering" + "value": "Quick Compress" } }, "pl": { @@ -13060,7 +13084,7 @@ "value": "Szybka kompresja" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Quick Compress" @@ -13138,7 +13162,7 @@ "value": "Quick Compress Window" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Ventana de Compresión rápida" @@ -13174,16 +13198,16 @@ "value": "Quick Compress Window" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Quick Compress Window" + "value": "Hurtigkomprimeringsvindu" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Hurtigkomprimeringsvindu" + "value": "Quick Compress Window" } }, "pl": { @@ -13192,7 +13216,7 @@ "value": "Okno szybkiej kompresji" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Quick Compress Window" @@ -13270,7 +13294,7 @@ "value": "Refresh" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Actualizar" @@ -13306,16 +13330,16 @@ "value": "새로고침" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Refresh" + "value": "Oppdater" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Oppdater" + "value": "Refresh" } }, "pl": { @@ -13324,7 +13348,7 @@ "value": "Odśwież" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Recarregar" @@ -13402,7 +13426,7 @@ "value": "save" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "guardar" @@ -13438,16 +13462,16 @@ "value": "저장" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "save" + "value": "lagre" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "lagre" + "value": "save" } }, "pl": { @@ -13456,7 +13480,7 @@ "value": "Zachowaj" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "salvar" @@ -13534,7 +13558,7 @@ "value": "Save As…" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Guardar como…" @@ -13570,16 +13594,16 @@ "value": "별도 저장…" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Bewaar als…" + "value": "Lagre som…" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Lagre som…" + "value": "Bewaar als…" } }, "pl": { @@ -13588,7 +13612,7 @@ "value": "Zachowaj jako…" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Salvar Como…" @@ -13750,7 +13774,7 @@ } } }, - "es-mx": { + "es-MX": { "variations": { "plural": { "many": { @@ -13864,37 +13888,37 @@ } } }, - "nl": { + "nb": { "variations": { "plural": { "one": { "stringUnit": { "state": "translated", - "value": "%lld selected" + "value": "%lld valgt" } }, "other": { "stringUnit": { "state": "translated", - "value": "" + "value": "%lld valgt" } } } } }, - "no": { + "nl": { "variations": { "plural": { "one": { "stringUnit": { "state": "translated", - "value": "%lld valgt" + "value": "%lld selected" } }, "other": { "stringUnit": { "state": "translated", - "value": "%lld valgt" + "value": "" } } } @@ -13930,7 +13954,7 @@ } } }, - "pt-br": { + "pt-BR": { "variations": { "plural": { "many": { @@ -14104,7 +14128,7 @@ "value": "Settings..." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Configuración..." @@ -14140,16 +14164,16 @@ "value": "설정..." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Settings..." + "value": "Innstillinger…" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Innstillinger…" + "value": "Settings..." } }, "pl": { @@ -14158,7 +14182,7 @@ "value": "Ustawienia…" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Configurações..." @@ -14236,7 +14260,7 @@ "value": "Start" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Iniciar" @@ -14272,13 +14296,13 @@ "value": "시작" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", "value": "Start" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", "value": "Start" @@ -14290,7 +14314,7 @@ "value": "Start" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Iniciar" @@ -14368,7 +14392,7 @@ "value": "Terms & Conditions" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Términos y condiciones" @@ -14404,16 +14428,16 @@ "value": "이용 약관" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Voorwaarden" + "value": "Vilkår og betingelser" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Vilkår og betingelser" + "value": "Voorwaarden" } }, "pl": { @@ -14422,7 +14446,7 @@ "value": "Warunki i zasady" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Termos e Condições" @@ -14500,7 +14524,7 @@ "value": "Top" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Arriba" @@ -14536,16 +14560,16 @@ "value": "상단" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Bovenaan" + "value": "Topp" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Topp" + "value": "Bovenaan" } }, "pl": { @@ -14554,7 +14578,7 @@ "value": "Na górze" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Acima" @@ -14632,7 +14656,7 @@ "value": "Website" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Sitio web" @@ -14668,16 +14692,16 @@ "value": "웹사이트" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Website" + "value": "Nettside" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Nettside" + "value": "Website" } }, "pl": { @@ -14686,7 +14710,7 @@ "value": "Strona Internetowa" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Site" @@ -14764,7 +14788,7 @@ "value": "What's new" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Novedades" @@ -14800,16 +14824,16 @@ "value": "새로운 소식" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "What's new" + "value": "Dette er nytt" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Dette er nytt" + "value": "What's new" } }, "pl": { @@ -14818,7 +14842,7 @@ "value": "Co nowego" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Novidades" @@ -14896,7 +14920,7 @@ "value": "Contact us" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Contáctanos" @@ -14932,16 +14956,16 @@ "value": "문의하기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Contact us" + "value": "Kontakt oss" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Kontakt oss" + "value": "Contact us" } }, "pl": { @@ -14950,7 +14974,7 @@ "value": "Skontaktuj się z nami" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Fale Conosco" @@ -15028,7 +15052,7 @@ "value": "... raise a Bug" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "...reporta un Bug" @@ -15064,16 +15088,16 @@ "value": "... 버그 신고" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "... raise a Bug" + "value": "... heve en feil" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "... heve en feil" + "value": "... raise a Bug" } }, "pl": { @@ -15082,7 +15106,7 @@ "value": "… zgłoś błąd" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Reportar falhas" @@ -15160,7 +15184,7 @@ "value": "... send a mail to %@" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "...envía un correo a %@" @@ -15196,16 +15220,16 @@ "value": "... %@에게 이메일 보내기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "... send a mail to %@" + "value": "... sende en e-post til %@" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "... sende en e-post til %@" + "value": "... send a mail to %@" } }, "pl": { @@ -15214,7 +15238,7 @@ "value": "… wyślij wiadomość do %@" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Escrever para %@" @@ -15292,7 +15316,7 @@ "value": "... request a Feature" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "...solicita funcionalidad" @@ -15328,16 +15352,16 @@ "value": "... 기능 요청" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "... request a Feature" + "value": "... be om en funksjon" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "... be om en funksjon" + "value": "... request a Feature" } }, "pl": { @@ -15346,7 +15370,7 @@ "value": "… wyślij propozycje" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Pedir nova função" @@ -15424,7 +15448,7 @@ "value": "Go here to ..." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Más opciones..." @@ -15460,16 +15484,16 @@ "value": "문의하기..." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Go here to ..." + "value": "Gå hit for å ..." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Gå hit for å ..." + "value": "Go here to ..." } }, "pl": { @@ -15478,7 +15502,7 @@ "value": "Przejdź do …" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Clique aqui para" @@ -15556,7 +15580,7 @@ "value": "Export failed" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Exportación fallida" @@ -15592,16 +15616,16 @@ "value": "Export failed" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Export failed" + "value": "Eksporten mislyktes" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Eksporten mislyktes" + "value": "Export failed" } }, "pl": { @@ -15610,7 +15634,7 @@ "value": "Eksport nie powiódł się" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Export failed" @@ -15688,7 +15712,7 @@ "value": "Could not open archive" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "No se ha podido abrir el archivo comprimido" @@ -15724,16 +15748,16 @@ "value": "Could not open archive" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Could not open archive" + "value": "Kunne ikke åpne arkivet" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Kunne ikke åpne arkivet" + "value": "Could not open archive" } }, "pl": { @@ -15742,7 +15766,7 @@ "value": "Nie można otworzyć archiwum" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Could not open archive" @@ -15820,7 +15844,7 @@ "value": "That password is incorrect. Try again." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "La contraseña es incorrecta. Inténtalo nuevamente." @@ -15856,16 +15880,16 @@ "value": "That password is incorrect. Try again." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "That password is incorrect. Try again." + "value": "Passordet er feil. Prøv på nytt." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Passordet er feil. Prøv på nytt." + "value": "That password is incorrect. Try again." } }, "pl": { @@ -15874,7 +15898,7 @@ "value": "To hasło jest nieprawidłowe. Spróbuj ponownie." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "That password is incorrect. Try again." @@ -15952,7 +15976,7 @@ "value": "Passwords do not match" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Las contraseñas no coinciden" @@ -15988,16 +16012,16 @@ "value": "암호가 일치하지 않음" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Wachtwoorden komen niet overeen" + "value": "Passordene stemmer ikke overens" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Passordene stemmer ikke overens" + "value": "Wachtwoorden komen niet overeen" } }, "pl": { @@ -16006,7 +16030,7 @@ "value": "Hasła nie zgadzają się" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "As palavras-passe não coincidem" @@ -16084,7 +16108,7 @@ "value": "Could not save archive" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "No se pudo guardar el archivo" @@ -16120,16 +16144,16 @@ "value": "Could not save archive" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Could not save archive" + "value": "Kunne ikke lagre arkivet" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Kunne ikke lagre arkivet" + "value": "Could not save archive" } }, "pl": { @@ -16138,7 +16162,7 @@ "value": "Nie udało się zapisać archiwum" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Could not save archive" @@ -16216,7 +16240,7 @@ "value": "Cancelled - no access to that folder" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Cancelado - sin acceso a ese folder" @@ -16252,16 +16276,16 @@ "value": "Cancelled - no access to that folder" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Cancelled - no access to that folder" + "value": "Avbrutt – ingen tilgang til den mappen" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Avbrutt – ingen tilgang til den mappen" + "value": "Cancelled - no access to that folder" } }, "pl": { @@ -16270,7 +16294,7 @@ "value": "Anulowano – brak dostępu do tego folderu" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Cancelled - no access to that folder" @@ -16348,7 +16372,7 @@ "value": "Leave a review in the App Store" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Escribe una reseña en la App Store" @@ -16384,16 +16408,16 @@ "value": "App Store에서 리뷰 남기기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Leave a review in the App Store" + "value": "Legg igjen en anmeldelse i App Store" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Legg igjen en anmeldelse i App Store" + "value": "Leave a review in the App Store" } }, "pl": { @@ -16402,7 +16426,7 @@ "value": "Zostaw opinię w App Store" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Deixe uma avaliação na App Store" @@ -16480,7 +16504,7 @@ "value": "Follow" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Seguir" @@ -16516,16 +16540,16 @@ "value": "팔로우" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Follow" + "value": "Følg" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Følg" + "value": "Follow" } }, "pl": { @@ -16534,7 +16558,7 @@ "value": "Obserwuj" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Follow" @@ -16612,7 +16636,7 @@ "value": "Review" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Reseña" @@ -16648,16 +16672,16 @@ "value": "리뷰" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Review" + "value": "Anmeldelse" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Anmeldelse" + "value": "Review" } }, "pl": { @@ -16666,7 +16690,7 @@ "value": "Ocena" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Review" @@ -16744,7 +16768,7 @@ "value": "Send a smile" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Enviar una sonrisa" @@ -16780,16 +16804,16 @@ "value": "응원하기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Send a smile" + "value": "Send et smil" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Send et smil" + "value": "Send a smile" } }, "pl": { @@ -16798,7 +16822,7 @@ "value": "Zostaw opinie" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Enviar um sorriso" @@ -16876,7 +16900,7 @@ "value": "Star" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Estrella" @@ -16912,16 +16936,16 @@ "value": "Star" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Star" + "value": "Stjerne" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Stjerne" + "value": "Star" } }, "pl": { @@ -16930,7 +16954,7 @@ "value": "Polub" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Star" @@ -17008,7 +17032,7 @@ "value": "Star the repository on GitHub" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Añadir una estrella en GitHub" @@ -17044,16 +17068,16 @@ "value": "GitHub 저장소에 Star 표시하기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Star the repository on GitHub" + "value": "Stjernemerk depotet på GitHub" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Stjernemerk depotet på GitHub" + "value": "Star the repository on GitHub" } }, "pl": { @@ -17062,7 +17086,7 @@ "value": "Dodaj do ulubionych na GitHubie" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Avalie o repositório no GitHub" @@ -17140,7 +17164,7 @@ "value": "Support the development..." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Apoya el desarrollo..." @@ -17176,16 +17200,16 @@ "value": "개발 지원하기..." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Support the development..." + "value": "Støtt utviklingen..." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Støtt utviklingen..." + "value": "Support the development..." } }, "pl": { @@ -17194,7 +17218,7 @@ "value": "Wesprzyj rozwój aplikacji…" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Suporte o desenvolvimento" @@ -17272,7 +17296,7 @@ "value": "Translate" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Traducir" @@ -17308,16 +17332,16 @@ "value": "번역" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Vertalen" + "value": "Oversett" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Oversett" + "value": "Vertalen" } }, "pl": { @@ -17326,7 +17350,7 @@ "value": "Tłumaczenie" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Traduzir" @@ -17404,7 +17428,7 @@ "value": "Guides & documentation" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Guías y documentación" @@ -17440,16 +17464,16 @@ "value": "가이드 및 문서" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Handleidingen en documentatie" + "value": "Guider og dokumentasjon" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Guider og dokumentasjon" + "value": "Handleidingen en documentatie" } }, "pl": { @@ -17458,7 +17482,7 @@ "value": "Przewodniki i dokumentacja" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Guias e documentação" @@ -17536,7 +17560,7 @@ "value": "Learn to use %@" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Aprende a usar %@" @@ -17572,16 +17596,16 @@ "value": "Learn to use %@" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Learn to use %@" + "value": "Lær å bruke %@" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Lær å bruke %@" + "value": "Learn to use %@" } }, "pl": { @@ -17590,7 +17614,7 @@ "value": "Jak użyć %@" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Learn to use %@" @@ -17668,7 +17692,7 @@ "value": "No recent archives." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "No hay archivos comprimidos recientes" @@ -17704,16 +17728,16 @@ "value": "No recent archives." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "No recent archives." + "value": "Ingen nyere arkiver." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Ingen nyere arkiver." + "value": "No recent archives." } }, "pl": { @@ -17722,7 +17746,7 @@ "value": "Brak ostatnich archiwów." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "No recent archives." @@ -17800,7 +17824,7 @@ "value": "Recent" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Recientes" @@ -17836,16 +17860,16 @@ "value": "최근 항목" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Recent" + "value": "Nylig" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Nylig" + "value": "Recent" } }, "pl": { @@ -17854,7 +17878,7 @@ "value": "Ostatnie" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Recentes" @@ -17932,7 +17956,7 @@ "value": "Release Notes" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Notas de la versión" @@ -17968,16 +17992,16 @@ "value": "릴리즈 노트" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Versienotities" + "value": "Utgivelsesnotater" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Utgivelsesnotater" + "value": "Versienotities" } }, "pl": { @@ -17986,7 +18010,7 @@ "value": "Informacje o wersji" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Notas de Lançamento" @@ -18064,7 +18088,7 @@ "value": "%@ needs access to %@" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "%@ necesita acceso a %@" @@ -18100,16 +18124,16 @@ "value": "%@ needs access to %@" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "%@ needs access to %@" + "value": "%@ trenger tilgang til %@" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "%@ trenger tilgang til %@" + "value": "%@ needs access to %@" } }, "pl": { @@ -18118,7 +18142,7 @@ "value": "%@ wymaga dostępu do %@" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "%@ needs access to %@" @@ -18196,7 +18220,7 @@ "value": "About" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Información" @@ -18232,16 +18256,16 @@ "value": "정보" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "About" + "value": "Om" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Om" + "value": "About" } }, "pl": { @@ -18250,7 +18274,7 @@ "value": "Informacje" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Sobre" @@ -18328,7 +18352,7 @@ "value": "Access granted" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Acceso permitido" @@ -18364,16 +18388,16 @@ "value": "Access granted" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Access granted" + "value": "Tilgang gitt" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Tilgang gitt" + "value": "Access granted" } }, "pl": { @@ -18382,7 +18406,7 @@ "value": "Dostęp nadany" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Access granted" @@ -18460,7 +18484,7 @@ "value": "Advanced" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Avanzado" @@ -18496,16 +18520,16 @@ "value": "고급" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Geavanceerd" + "value": "Avansert" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Avansert" + "value": "Geavanceerd" } }, "pl": { @@ -18514,7 +18538,7 @@ "value": "Zaawansowane" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Avançado" @@ -18592,7 +18616,7 @@ "value": "Archive Formats" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Formatos de archivos comprimidos" @@ -18628,16 +18652,16 @@ "value": "압축 형식" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Archive Formats" + "value": "Arkivformater" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Arkivformater" + "value": "Archive Formats" } }, "pl": { @@ -18646,7 +18670,7 @@ "value": "Format archiwum" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Formatos de Arquivos" @@ -18724,7 +18748,7 @@ "value": "Automatic engine selection" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Selección automática del motor" @@ -18760,16 +18784,16 @@ "value": "Automatic engine selection" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Automatic engine selection" + "value": "Automatisk motorvalg" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Automatisk motorvalg" + "value": "Automatic engine selection" } }, "pl": { @@ -18778,7 +18802,7 @@ "value": "Automatyczny wybór silnika" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Automatic engine selection" @@ -18856,7 +18880,7 @@ "value": "MacPacker chooses the engine for each archive, and tries another one if the first can't read it. Turn this off to choose engines yourself." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "MacPacker selecciona el motor para abrir cada tipo de archivo comprimido e intenta con otro si el primer motor no lo puede leer. Deshabilita esta opción si deseas seleccionar tus motores manualmente." @@ -18892,16 +18916,16 @@ "value": "MacPacker chooses the engine for each archive, and tries another one if the first can't read it. Turn this off to choose engines yourself." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "MacPacker chooses the engine for each archive, and tries another one if the first can't read it. Turn this off to choose engines yourself." + "value": "MacPacker velger motoren for hvert arkiv, og prøver en annen hvis den første ikke kan lese den. Slå av dette for å velge motorer selv." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "MacPacker velger motoren for hvert arkiv, og prøver en annen hvis den første ikke kan lese den. Slå av dette for å velge motorer selv." + "value": "MacPacker chooses the engine for each archive, and tries another one if the first can't read it. Turn this off to choose engines yourself." } }, "pl": { @@ -18910,7 +18934,7 @@ "value": "MacPacker wybiera silnik dla każdego archiwum i próbuje innego, jeśli pierwszy nie może go odczytać. Wyłącz tę opcję, aby samodzielnie wybierać silniki." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "MacPacker chooses the engine for each archive, and tries another one if the first can't read it. Turn this off to choose engines yourself." @@ -18988,7 +19012,7 @@ "value": "Automatically check for updates" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Comprobar actualizaciones automaticamente" @@ -19024,16 +19048,16 @@ "value": "Automatically check for updates" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Automatically check for updates" + "value": "Se etter oppdateringer automatisk" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Se etter oppdateringer automatisk" + "value": "Automatically check for updates" } }, "pl": { @@ -19042,7 +19066,7 @@ "value": "Automatycznie szukaj aktualizacji" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Automatically check for updates" @@ -19120,7 +19144,7 @@ "value": "Breadcrumb position" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Posición de la ruta de navegación" @@ -19156,16 +19180,16 @@ "value": "이동 경로 위치" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Breadcrumb position" + "value": "Brødsmuleposisjon" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Brødsmuleposisjon" + "value": "Breadcrumb position" } }, "pl": { @@ -19174,7 +19198,7 @@ "value": "Pole nawigacyjne" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Posição da barra de navegação" @@ -19252,7 +19276,7 @@ "value": "Cache" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Caché" @@ -19288,16 +19312,16 @@ "value": "캐시" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Cache" + "value": "Hurtigbuffer" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Hurtigbuffer" + "value": "Cache" } }, "pl": { @@ -19306,7 +19330,7 @@ "value": "Pamięć podręczna" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Cachê" @@ -19384,7 +19408,7 @@ "value": "Clear cache" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Limpiar caché" @@ -19420,16 +19444,16 @@ "value": "캐시 지우기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Clear cache" + "value": "Tøm hurtigbufferen" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Tøm hurtigbufferen" + "value": "Clear cache" } }, "pl": { @@ -19438,7 +19462,7 @@ "value": "Wyczyść pamięć podręczną" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Limpar Cachê" @@ -19516,7 +19540,7 @@ "value": "Clears all content from the cache" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Limpiar todo el contenido del caché" @@ -19552,16 +19576,16 @@ "value": "캐시된 모든 내용을 지웁니다" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Clears all content from the cache" + "value": "Fjerner alt innhold fra hurtigbufferen" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Fjerner alt innhold fra hurtigbufferen" + "value": "Clears all content from the cache" } }, "pl": { @@ -19570,7 +19594,7 @@ "value": "Wyczyść całą zawartość pamięci podręcznej" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Limpa todo o conteúdo do cachê" @@ -19648,7 +19672,7 @@ "value": "Columns" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Columnas" @@ -19684,16 +19708,16 @@ "value": "열:" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Columns" + "value": "Kolonner" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Kolonner" + "value": "Columns" } }, "pl": { @@ -19702,7 +19726,7 @@ "value": "Kolumny:" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Colunas:" @@ -19780,7 +19804,7 @@ "value": "Compress each item separately" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Comprimir cada elemento por separado" @@ -19816,16 +19840,16 @@ "value": "Compress each item separately" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Compress each item separately" + "value": "Komprimer hvert element separat" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Komprimer hvert element separat" + "value": "Compress each item separately" } }, "pl": { @@ -19834,7 +19858,7 @@ "value": "Skompresuj każdy element osobno" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Compress each item separately" @@ -19912,7 +19936,7 @@ "value": "Compress a folder’s contents" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Comprimir el contenido de una carpeta" @@ -19948,16 +19972,16 @@ "value": "Compress a folder’s contents" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Compress a folder’s contents" + "value": "Komprimer innholdet i en mappe" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Komprimer innholdet i en mappe" + "value": "Compress a folder’s contents" } }, "pl": { @@ -19966,7 +19990,7 @@ "value": "Skompresuj zwartość folderu" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Compress a folder’s contents" @@ -20044,7 +20068,7 @@ "value": "Compress to 7z" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Comprimir a 7z" @@ -20080,16 +20104,16 @@ "value": "Compress to 7z" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Compress to 7z" + "value": "Komprimer til 7z" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Komprimer til 7z" + "value": "Compress to 7z" } }, "pl": { @@ -20098,7 +20122,7 @@ "value": "Skompresuj do 7z" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Compress to 7z" @@ -20176,7 +20200,7 @@ "value": "Compress to zip" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Comprimir a zip" @@ -20212,16 +20236,16 @@ "value": "Compress to zip" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Compress to zip" + "value": "Komprimer til zip" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Komprimer til zip" + "value": "Compress to zip" } }, "pl": { @@ -20230,7 +20254,7 @@ "value": "Skompresuj do zip" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Compress to zip" @@ -20308,7 +20332,7 @@ "value": "Compress to zip with date and time" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Comprimir a zip con fecha y hora" @@ -20344,16 +20368,16 @@ "value": "Compress to zip with date and time" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Compress to zip with date and time" + "value": "Komprimer til zip med dato og klokkeslett" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Komprimer til zip med dato og klokkeslett" + "value": "Compress to zip with date and time" } }, "pl": { @@ -20362,7 +20386,7 @@ "value": "Skompresuj do zip z datą i czasem" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Compress to zip with date and time" @@ -20440,7 +20464,7 @@ "value": "Context Menu" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Menú contextual" @@ -20476,16 +20500,16 @@ "value": "빠른 메뉴" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Context­menu" + "value": "Kontekstmeny" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Kontekstmeny" + "value": "Context­menu" } }, "pl": { @@ -20494,7 +20518,7 @@ "value": "Menu kontekstowe" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Menu Contextual" @@ -20572,7 +20596,7 @@ "value": "To make MacPacker the default for a file type: Right-click a file → 'Get Info' → choose MacPacker under 'Open with:' → click 'Change All…' to apply it to all similar archives." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Para hacer que MacPacker sea la aplicación por defecto para un tipo de archivo en específico: Haz clic derecho en un archivo → 'Obtener Información' → selecciona MacPacker en el menu 'Abrir con:' → Haz clic en 'Cambiar todo…' para aplicar los cambios a todos los archivos del mismo tipo." @@ -20608,16 +20632,16 @@ "value": "To make MacPacker the default for a file type: Right-click a file → 'Get Info' → choose MacPacker under 'Open with:' → click 'Change All…' to apply it to all similar archives." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "To make MacPacker the default for a file type: Right-click a file → 'Get Info' → choose MacPacker under 'Open with:' → click 'Change All…' to apply it to all similar archives." + "value": "Slik gjør du MacPacker til standard for en filtype: Høyreklikk på en fil → «Hent info» → velg MacPacker under «Åpne med:» → klikk på «Endre alle…» for å bruke den på alle lignende arkiver." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Slik gjør du MacPacker til standard for en filtype: Høyreklikk på en fil → «Hent info» → velg MacPacker under «Åpne med:» → klikk på «Endre alle…» for å bruke den på alle lignende arkiver." + "value": "To make MacPacker the default for a file type: Right-click a file → 'Get Info' → choose MacPacker under 'Open with:' → click 'Change All…' to apply it to all similar archives." } }, "pl": { @@ -20626,7 +20650,7 @@ "value": "Aby ustawić MacPacker domyślnie dla danego typu pliku: Kliknij plik prawym przyciskiem myszy → „Informacje” → wybierz MacPacker w sekcji „Otwórz za pomocą:” → kliknij „Zmień wszystko…”, aby zastosować tę opcję do wszystkich podobnych archiwów." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "To make MacPacker the default for a file type: Right-click a file → 'Get Info' → choose MacPacker under 'Open with:' → click 'Change All…' to apply it to all similar archives." @@ -20704,7 +20728,7 @@ "value": "Default status & engine settings" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Configuración por defecto y motores de compresión" @@ -20740,16 +20764,16 @@ "value": "기본 상태 및 엔진 설정:" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Default status & engine settings" + "value": "Standardstatus og motorinnstillinger" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Standardstatus og motorinnstillinger" + "value": "Default status & engine settings" } }, "pl": { @@ -20758,7 +20782,7 @@ "value": "Ustawienia domyślne oraz ustawienia jądra" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Status Padrão & Configuração de Motor" @@ -20836,7 +20860,7 @@ "value": "Edits archives, not only opens them" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Edita archivos comprimidos, no solo los abre." @@ -20872,16 +20896,16 @@ "value": "Edits archives, not only opens them" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Edits archives, not only opens them" + "value": "Redigerer arkiver, ikke bare åpner dem" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Redigerer arkiver, ikke bare åpner dem" + "value": "Edits archives, not only opens them" } }, "pl": { @@ -20890,7 +20914,7 @@ "value": "Edytuje archiwa, nie tylko je otwiera" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Edits archives, not only opens them" @@ -20968,7 +20992,7 @@ "value": "Engine" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Motor de compresión" @@ -21004,16 +21028,16 @@ "value": "엔진" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Engine" + "value": "Motor" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Motor" + "value": "Engine" } }, "pl": { @@ -21022,7 +21046,7 @@ "value": "Silnik" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Motor" @@ -21100,7 +21124,7 @@ "value": "MacPacker includes several archive engines. The default is recommended; alternative engines can help with format-specific problems. Keep in mind that engine support varies by format." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "MacPacker hace uso de varios motores de compresión. El motor predeterminado es el recomendado; motores adicionales pueden ayudar con problemas específicos de un formato. Ten en cuenta que el soporte para cada motor varía dependiendo del formato." @@ -21136,16 +21160,16 @@ "value": "MacPacker에는 여러 압축 엔진이 포함되어 있습니다. 기본 엔진을 권장하며, 대체 엔진은 특정 확장자 관련 문제 해결에 도움이 될 수 있습니다. 단, 확장자별로 지원하는 엔진이 다를 수 있습니다." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "MacPacker includes several archive engines. The default is recommended; alternative engines can help with format-specific problems. Keep in mind that engine support varies by format." + "value": "MacPacker inneholder flere arkivmotorer. Standardverdien anbefales; alternative motorer kan hjelpe med formatspesifikke problemer. Husk at motorstøtten varierer etter format." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "MacPacker inneholder flere arkivmotorer. Standardverdien anbefales; alternative motorer kan hjelpe med formatspesifikke problemer. Husk at motorstøtten varierer etter format." + "value": "MacPacker includes several archive engines. The default is recommended; alternative engines can help with format-specific problems. Keep in mind that engine support varies by format." } }, "pl": { @@ -21154,7 +21178,7 @@ "value": "MacPacker zawiera w sobie kilka różnych silników archiwizujących. Rekomendowany jest domyślny; inne silniki mogą pomóc z problemami dla konkretnych formatów. Miej na uwadze, że wsparcie silnika różni się w zależności od formatu." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "MacPacker includes several archive engines. The default is recommended; alternative engines can help with format-specific problems. Keep in mind that engine support varies by format." @@ -21232,7 +21256,7 @@ "value": "Export Logs" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Exportar registros" @@ -21268,16 +21292,16 @@ "value": "로그 내보내기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Export Logs" + "value": "Eksporter logger" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Eksporter logger" + "value": "Export Logs" } }, "pl": { @@ -21286,7 +21310,7 @@ "value": "Eksportuj dzienniki" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Exportar Registros" @@ -21364,7 +21388,7 @@ "value": "Extensions" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Extensiones" @@ -21400,16 +21424,16 @@ "value": "확장자" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Extensions" + "value": "Utvidelser" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Utvidelser" + "value": "Extensions" } }, "pl": { @@ -21418,7 +21442,7 @@ "value": "Rozszerzenia" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Extensões" @@ -21496,7 +21520,7 @@ "value": "External volumes" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Volúmenes externos" @@ -21532,16 +21556,16 @@ "value": "외장 디스크" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Verwijderbare volumes" + "value": "Eksterne volumer" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Eksterne volumer" + "value": "Verwijderbare volumes" } }, "pl": { @@ -21550,7 +21574,7 @@ "value": "Dyski zewnętrzne" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Volumes externos" @@ -21628,7 +21652,7 @@ "value": "Covers USB drives, memory cards and network shares, which appear in /Volumes." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Incluye unidades USB, tarjetas de memoria y recursos compartidos de red que aparecen en /Volumes." @@ -21664,16 +21688,16 @@ "value": "Covers USB drives, memory cards and network shares, which appear in /Volumes." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Covers USB drives, memory cards and network shares, which appear in /Volumes." + "value": "Dekker USB-stasjoner, minnekort og nettverksressurser, som vises i /Volumes." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Dekker USB-stasjoner, minnekort og nettverksressurser, som vises i /Volumes." + "value": "Covers USB drives, memory cards and network shares, which appear in /Volumes." } }, "pl": { @@ -21682,7 +21706,7 @@ "value": "Zawiera dyski USB, karty pamięci i udziały, ktore pojawiają się w /Volumes." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Covers USB drives, memory cards and network shares, which appear in /Volumes." @@ -21760,7 +21784,7 @@ "value": "Extract To…" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Extraer en…" @@ -21796,16 +21820,16 @@ "value": "풀기(E)…" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Uitpakken naar…" + "value": "Utdrag til…" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Utdrag til…" + "value": "Uitpakken naar…" } }, "pl": { @@ -21814,7 +21838,7 @@ "value": "Rozpakuj do…" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Extrair para…" @@ -21892,7 +21916,7 @@ "value": "Extract to folder" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Extraer en carpeta" @@ -21928,16 +21952,16 @@ "value": "Extract to folder" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Extract to folder" + "value": "Pakk ut til mappe" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Pakk ut til mappe" + "value": "Extract to folder" } }, "pl": { @@ -21946,7 +21970,7 @@ "value": "Rozpakuj do folderu" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Extract to folder" @@ -22024,7 +22048,7 @@ "value": "File Format" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Formato de archivo" @@ -22060,16 +22084,16 @@ "value": "파일 형식" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Bestandsformaat" + "value": "Filformat" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Filformat" + "value": "Bestandsformaat" } }, "pl": { @@ -22078,7 +22102,7 @@ "value": "Format pliku" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Formato do arquivo" @@ -22156,7 +22180,7 @@ "value": "File provider extension" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Extensión de proveedor de archivos" @@ -22192,16 +22216,16 @@ "value": "파일 제공자 확장 프로그램" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "File provider extension" + "value": "Filleverandørens utvidelse" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Filleverandørens utvidelse" + "value": "File provider extension" } }, "pl": { @@ -22210,7 +22234,7 @@ "value": "Rozszerzenie typu pliku" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Extensão do File Provider" @@ -22288,7 +22312,7 @@ "value": "macOS lets %@ open and write files only where you allow it, which is why a folder-access panel shows up now and then. A grant covers everything inside the folder you pick, so allowing these two puts an end to the asking." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "macOS permite que %@ acceda a archivos solo en las ubicaciones que autorices. Por eso, ocasionalmente te pedirá acceso a una carpeta. El permiso se aplica a todo su contenido, así que autorizar estas dos ubicaciones evitará futuras solicitudes." @@ -22324,16 +22348,16 @@ "value": "macOS lets %@ open and write files only where you allow it, which is why a folder-access panel shows up now and then. A grant covers everything inside the folder you pick, so allowing these two puts an end to the asking." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "macOS lets %@ open and write files only where you allow it, which is why a folder-access panel shows up now and then. A grant covers everything inside the folder you pick, so allowing these two puts an end to the asking." + "value": "macOS lar %@ bare åpne og skrive filer der du tillater det, og det er derfor et mappetilgangspanel dukker opp nå og da. En tillatelse dekker alt i mappen du velger, så å tillate disse to setter en stopper for forespørselen." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "macOS lar %@ bare åpne og skrive filer der du tillater det, og det er derfor et mappetilgangspanel dukker opp nå og da. En tillatelse dekker alt i mappen du velger, så å tillate disse to setter en stopper for forespørselen." + "value": "macOS lets %@ open and write files only where you allow it, which is why a folder-access panel shows up now and then. A grant covers everything inside the folder you pick, so allowing these two puts an end to the asking." } }, "pl": { @@ -22342,7 +22366,7 @@ "value": "macOS pozwala %@ otwierać i zapisywać pliki tylko tam, gdzie na to pozwolisz, dlatego czasami pojawia sie okno dostępu do folderów. Nadanie dostępu uwzględni wszystko w wybranym folderze i kolejne prośby nie będą sie pojawiać." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "macOS lets %@ open and write files only where you allow it, which is why a folder-access panel shows up now and then. A grant covers everything inside the folder you pick, so allowing these two puts an end to the asking." @@ -22420,7 +22444,7 @@ "value": "General" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "General" @@ -22456,16 +22480,16 @@ "value": "일반" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "General" + "value": "Generelt" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Generelt" + "value": "General" } }, "pl": { @@ -22474,7 +22498,7 @@ "value": "Ogólne" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Geral" @@ -22552,7 +22576,7 @@ "value": "Home folder" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Carpeta de inicio" @@ -22588,16 +22612,16 @@ "value": "홈 폴더" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Thuismap" + "value": "Hjemmappe" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Hjemmappe" + "value": "Thuismap" } }, "pl": { @@ -22606,7 +22630,7 @@ "value": "Folder domowy" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Pasta pessoal" @@ -22684,7 +22708,7 @@ "value": "Covers the Desktop, Documents, Downloads and everything else in your home folder." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Incluye el Escritorio, Documentos, Descargas y todo lo demás en tu carpeta de inicio." @@ -22720,16 +22744,16 @@ "value": "Covers the Desktop, Documents, Downloads and everything else in your home folder." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Covers the Desktop, Documents, Downloads and everything else in your home folder." + "value": "Dekker skrivebordet, dokumenter, nedlastinger og alt annet i hjemmemappen din." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Dekker skrivebordet, dokumenter, nedlastinger og alt annet i hjemmemappen din." + "value": "Covers the Desktop, Documents, Downloads and everything else in your home folder." } }, "pl": { @@ -22738,7 +22762,7 @@ "value": "Zawiera Pulpit, Dokumenty, Pobrane i wszystko inne w Twoim foldere domowym." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Covers the Desktop, Documents, Downloads and everything else in your home folder." @@ -22816,7 +22840,7 @@ "value": "How to set %@ as default?" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "¿Cómo establecer %@ como predeterminado?" @@ -22852,16 +22876,16 @@ "value": "%@을(를) 기본 앱으로 설정하는 방법" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "How to set %@ as default?" + "value": "Hvordan setter man %@ som standard?" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Hvordan setter man %@ som standard?" + "value": "How to set %@ as default?" } }, "pl": { @@ -22870,7 +22894,7 @@ "value": "Jak ustawić %@ jako domyślny?" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Como tornar %@ padrão" @@ -22948,7 +22972,7 @@ "value": "Include Beta updates" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Incluir actualizaciones beta" @@ -22984,16 +23008,16 @@ "value": "Include Beta updates" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Include Beta updates" + "value": "Inkluder betaoppdateringer" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Inkluder betaoppdateringer" + "value": "Include Beta updates" } }, "pl": { @@ -23002,7 +23026,7 @@ "value": "Dodaj wersje beta" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Include Beta updates" @@ -23080,7 +23104,7 @@ "value": "Info on Engines" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Información de motores de compresión" @@ -23116,16 +23140,16 @@ "value": "엔진 정보" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Info on Engines" + "value": "Informasjon om motorer" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Informasjon om motorer" + "value": "Info on Engines" } }, "pl": { @@ -23134,7 +23158,7 @@ "value": "Informacje o silnikach" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Informações" @@ -23212,7 +23236,7 @@ "value": "Logs" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Registros" @@ -23248,16 +23272,16 @@ "value": "로그" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Logs" + "value": "Logger" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Logger" + "value": "Logs" } }, "pl": { @@ -23266,7 +23290,7 @@ "value": "Dzienniki" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Registros" @@ -23344,7 +23368,7 @@ "value": "Set MacPacker as the default app" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Establece MacPacker como la aplicación por defecto" @@ -23380,16 +23404,16 @@ "value": "Set MacPacker as the default app" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Set MacPacker as the default app" + "value": "Angi MacPacker som standard-appen" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Angi MacPacker som standard-appen" + "value": "Set MacPacker as the default app" } }, "pl": { @@ -23398,7 +23422,7 @@ "value": "Ustaw MacPacker jako domyślną aplikację" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Set MacPacker as the default app" @@ -23476,7 +23500,7 @@ "value": "Manage in System Settings" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Administra en la Configuración del Sistema" @@ -23512,16 +23536,16 @@ "value": "시스템 설정에서 관리" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Manage in System Settings" + "value": "Administrer i systeminnstillinger" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Administrer i systeminnstillinger" + "value": "Manage in System Settings" } }, "pl": { @@ -23530,7 +23554,7 @@ "value": "Zarządzaj w Ustawieniach systemowych" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Gerir em configurações do sistema" @@ -23608,7 +23632,7 @@ "value": "Nest actions in a submenu" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Agrupar acciones en un submenú" @@ -23644,16 +23668,16 @@ "value": "Nest actions in a submenu" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Nest actions in a submenu" + "value": "Neste handlinger i en undermeny" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Neste handlinger i en undermeny" + "value": "Nest actions in a submenu" } }, "pl": { @@ -23662,7 +23686,7 @@ "value": "Zagnieżdżaj akcje w podmenu" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Nest actions in a submenu" @@ -23740,7 +23764,7 @@ "value": "Open cache directory" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Abrir directorio del caché" @@ -23776,16 +23800,16 @@ "value": "캐시 폴더 열기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Open cache directory" + "value": "Åpne hurtigbufferkatalogen" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Åpne hurtigbufferkatalogen" + "value": "Open cache directory" } }, "pl": { @@ -23794,7 +23818,7 @@ "value": "Otwórz katalog pamięci podręcznej" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Abrir diretório de cachê" @@ -23872,7 +23896,7 @@ "value": "Quit on last window closed" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Salir al cerrar la última ventana" @@ -23908,16 +23932,16 @@ "value": "Quit on last window closed" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Quit on last window closed" + "value": "Avslutt ved siste lukkede vindu" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Avslutt ved siste lukkede vindu" + "value": "Quit on last window closed" } }, "pl": { @@ -23926,7 +23950,7 @@ "value": "Zakończ po zamknięciu ostatniego okna" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Quit on last window closed" @@ -24004,7 +24028,7 @@ "value": "Remember recent archives" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Recordar archivos comprimidos recientes" @@ -24040,16 +24064,16 @@ "value": "Remember recent archives" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Remember recent archives" + "value": "Husk nylige arkiver" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Husk nylige arkiver" + "value": "Remember recent archives" } }, "pl": { @@ -24058,7 +24082,7 @@ "value": "Zapamiętaj ostatnie archiwa" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Remember recent archives" @@ -24136,7 +24160,7 @@ "value": "Show application support folder" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Mostrar el folder the soporte de la aplicación" @@ -24172,16 +24196,16 @@ "value": "응용 프로그램 지원 폴더 열기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Show application support folder" + "value": "Vis mappe for programstøtte" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Vis mappe for programstøtte" + "value": "Show application support folder" } }, "pl": { @@ -24190,7 +24214,7 @@ "value": "Pokaż folder pomocy technicznej aplikacji" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Mostrar pasta de suporte de aplicação" @@ -24268,7 +24292,7 @@ "value": "Show in Menu Bar" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Mostrar en la barra de menús" @@ -24304,16 +24328,16 @@ "value": "메뉴 막대에서 보기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Toon in menubalk" + "value": "Vis i menylinjen" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Vis i menylinjen" + "value": "Toon in menubalk" } }, "pl": { @@ -24322,7 +24346,7 @@ "value": "Pokazuj na pasku menu" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Mostrar na Barra de Menus" @@ -24400,7 +24424,7 @@ "value": "Show parent folder entry (“..”)" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Mostrar la carpeta superior (“..”)" @@ -24436,16 +24460,16 @@ "value": "Show parent folder entry (“..”)" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Show parent folder entry (“..”)" + "value": "Vis oppføring i overordnet mappe (“..”)" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Vis oppføring i overordnet mappe (“..”)" + "value": "Show parent folder entry (“..”)" } }, "pl": { @@ -24454,7 +24478,7 @@ "value": "Pokaż wpis folderu nadrzędnego (“..”)" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Show parent folder entry (“..”)" @@ -24532,7 +24556,7 @@ "value": "Smart extraction" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Extracción inteligente" @@ -24568,16 +24592,16 @@ "value": "Smart extraction" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Smart extraction" + "value": "Smart utvinning" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Smart utvinning" + "value": "Smart extraction" } }, "pl": { @@ -24586,7 +24610,7 @@ "value": "Sprytne rozpakowywanie" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Smart extraction" @@ -24664,7 +24688,7 @@ "value": "Check for Updates…" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Buscar actualizaciones…" @@ -24700,16 +24724,16 @@ "value": "업데이트 확인..." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Check for Updates…" + "value": "Se etter oppdateringer …" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Se etter oppdateringer …" + "value": "Check for Updates…" } }, "pl": { @@ -24718,7 +24742,7 @@ "value": "Sprawdź aktualizacje…" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Verificar Atualizações" @@ -24796,7 +24820,7 @@ "value": "Changelog" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Registro de cambios" @@ -24832,16 +24856,16 @@ "value": "Changelog" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Changelog" + "value": "Endringslogg" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Endringslogg" + "value": "Changelog" } }, "pl": { @@ -24850,7 +24874,7 @@ "value": "Dziennik zmian" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Changelog" @@ -24928,7 +24952,7 @@ "value": "Coming next" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Próximamente" @@ -24964,16 +24988,16 @@ "value": "Coming next" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Coming next" + "value": "Kommer snart" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Kommer snart" + "value": "Coming next" } }, "pl": { @@ -24982,7 +25006,7 @@ "value": "Nadchodzące zmiany" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Coming next" @@ -25060,7 +25084,7 @@ "value": "Release highlights" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Novedades destacadas" @@ -25096,16 +25120,16 @@ "value": "주요 업데이트" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Belangrijkste vernieuwingen" + "value": "Høydepunkter fra utgivelsen" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Høydepunkter fra utgivelsen" + "value": "Belangrijkste vernieuwingen" } }, "pl": { @@ -25114,7 +25138,7 @@ "value": "Najważniejsze nowości" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Destaques da versão" @@ -25192,7 +25216,7 @@ "value": "Support %@" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Apoya a %@" @@ -25228,16 +25252,16 @@ "value": "%@ 후원하기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Steun %@" + "value": "Støtt %@" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Støtt %@" + "value": "Steun %@" } }, "pl": { @@ -25246,7 +25270,7 @@ "value": "Wesprzyj %@" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Apoie o %@" @@ -25324,7 +25348,7 @@ "value": "Your donation supports ongoing development." } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Tu donación apoya el desarrollo continuo." @@ -25360,16 +25384,16 @@ "value": "여러분의 후원이 지속적인 개발에 힘이 됩니다." } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Je donatie ondersteunt de verdere ontwikkeling." + "value": "Din donasjon støtter kontinuerlig utvikling." } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Din donasjon støtter kontinuerlig utvikling." + "value": "Je donatie ondersteunt de verdere ontwikkeling." } }, "pl": { @@ -25378,7 +25402,7 @@ "value": "Twoja darowizna wspiera dalszy rozwój." } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Sua doação apoia o desenvolvimento contínuo." @@ -25456,7 +25480,7 @@ "value": "Help keep %@ growing" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Ayuda a que %@ siga creciendo" @@ -25492,16 +25516,16 @@ "value": "%@의 성장을 도와주세요" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Help %@ verder te groeien" + "value": "Hjelp %@ med å holde veksten oppe" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Hjelp %@ med å holde veksten oppe" + "value": "Help %@ verder te groeien" } }, "pl": { @@ -25510,7 +25534,7 @@ "value": "Pomóż rozwijać %@" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Ajude o %@ a crescer" @@ -25588,7 +25612,7 @@ "value": "Welcome to %@" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Bienvenido a %@" @@ -25624,16 +25648,16 @@ "value": "%@에 오신 것을 환영합니다" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Welcome to %@" + "value": "Velkommen til %@" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Velkommen til %@" + "value": "Welcome to %@" } }, "pl": { @@ -25642,7 +25666,7 @@ "value": "Witaj w aplikacji %@" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Bem-vindo ao %@" @@ -25720,7 +25744,7 @@ "value": "View all changes" } }, - "es-mx": { + "es-MX": { "stringUnit": { "state": "translated", "value": "Ver todos los cambios" @@ -25756,16 +25780,16 @@ "value": "모든 변경 사항 보기" } }, - "nl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Bekijk alle wijzigingen" + "value": "Se alle endringer" } }, - "no": { + "nl": { "stringUnit": { "state": "translated", - "value": "Se alle endringer" + "value": "Bekijk alle wijzigingen" } }, "pl": { @@ -25774,7 +25798,7 @@ "value": "Zobacz wszystkie zmiany" } }, - "pt-br": { + "pt-BR": { "stringUnit": { "state": "translated", "value": "Ver todas as alterações" diff --git a/MacPackerUITests/MacPackerUITests.swift b/MacPackerUITests/MacPackerUITests.swift index a307cacf..ef93a0c2 100644 --- a/MacPackerUITests/MacPackerUITests.swift +++ b/MacPackerUITests/MacPackerUITests.swift @@ -103,6 +103,111 @@ final class MacPackerUITests: XCTestCase { // MARK: - Tests + /// Use the existing archive fixture rather than generating a new archive. + private func copyOneClickFixture(into directory: URL) throws -> URL { + let source = URL(fileURLWithPath: #filePath) + .deletingLastPathComponent().deletingLastPathComponent() + .appendingPathComponent("Modules/Tests/CoreTests/TestArchives/defaultArchives/defaultArchive.zip") + let archive = directory.appendingPathComponent("Photos.zip") + try FileManager.default.copyItem(at: source, to: archive) + return archive + } + + private func openForOneClickExtraction(_ archive: URL, destination: String, enabled: Bool = true) -> XCUIApplication { + let app = XCUIApplication() + app.terminate() + app.launchArguments = [ + "-DisableUpdateChecks", "YES", + "-oneClickExtraction", enabled ? "YES" : "NO", + "-oneClickExtractionDestination", destination, + "-\(quitOnLastWindowClosedKey)", "YES", + ] + app.open(archive) + return app + } + + func testCaptureGeneralSettings() { + let app = launchApp(arguments: ["-AppleLanguages", "(en)", "-AppleLocale", "en_US", + "-oneClickExtraction", "YES", "-\(quitOnLastWindowClosedKey)", "NO"]) + defer { app.terminate() } + app.typeKey(",", modifierFlags: .command) + let general = app.buttons["General"].firstMatch + if general.waitForExistence(timeout: 5) { general.click() } + let screenshot = XCTAttachment(screenshot: app.screenshot()) + screenshot.name = "General Settings" + screenshot.lifetime = .keepAlways + add(screenshot) + } + + func testOneClickExtractsBesideArchive() throws { + let directory = try makeWorkDir("one-click-here") + defer { try? FileManager.default.removeItem(at: directory) } + let archive = try copyOneClickFixture(into: directory) + let app = openForOneClickExtraction(archive, destination: "sameFolder") + defer { app.terminate() } + confirmAccessPanel(app, button: "Grant Access") + + XCTAssertTrue(waitForFile(directory.appendingPathComponent("hello world.txt"))) + XCTAssertFalse(FileManager.default.fileExists(atPath: directory.appendingPathComponent("Photos").path)) + XCTAssertTrue(app.wait(for: .notRunning, timeout: 10), "Extraction should finish without leaving an archive window") + } + + func testOneClickExtractsIntoArchiveNamedFolder() throws { + let directory = try makeWorkDir("one-click-folder") + defer { try? FileManager.default.removeItem(at: directory) } + let archive = try copyOneClickFixture(into: directory) + let app = openForOneClickExtraction(archive, destination: "archiveFolder") + defer { app.terminate() } + confirmAccessPanel(app, button: "Grant Access") + + XCTAssertTrue(waitForFile(directory.appendingPathComponent("Photos/hello world.txt"))) + XCTAssertFalse(FileManager.default.fileExists(atPath: directory.appendingPathComponent("hello world.txt").path)) + XCTAssertTrue(app.wait(for: .notRunning, timeout: 10)) + } + + func testOneClickAsksForDestination() throws { + let directory = try makeWorkDir("one-click-choose") + defer { try? FileManager.default.removeItem(at: directory) } + let archive = try copyOneClickFixture(into: directory) + let app = openForOneClickExtraction(archive, destination: "chooseFolder") + defer { app.terminate() } + let extract = app.windows.buttons["Extract"].firstMatch + XCTAssertTrue(extract.waitForExistence(timeout: 10)) + XCTAssertFalse(FileManager.default.fileExists(atPath: directory.appendingPathComponent("hello world.txt").path)) + // The panel starts in the source folder. Picking it is also the grant; + // no second permissions panel should be needed before extraction. + app.typeKey(.return, modifierFlags: []) + XCTAssertTrue(waitForFile(directory.appendingPathComponent("hello world.txt"))) + XCTAssertTrue(app.wait(for: .notRunning, timeout: 10)) + } + + func testCancellingOneClickDestinationLeavesArchiveUntouched() throws { + let directory = try makeWorkDir("one-click-cancel") + defer { try? FileManager.default.removeItem(at: directory) } + let archive = try copyOneClickFixture(into: directory) + let original = try Data(contentsOf: archive) + let app = openForOneClickExtraction(archive, destination: "chooseFolder") + defer { app.terminate() } + let cancel = app.windows.buttons["Cancel"].firstMatch + XCTAssertTrue(cancel.waitForExistence(timeout: 10)) + cancel.click() + + XCTAssertTrue(app.wait(for: .notRunning, timeout: 10)) + XCTAssertEqual(try FileManager.default.contentsOfDirectory(atPath: directory.path), ["Photos.zip"]) + XCTAssertEqual(try Data(contentsOf: archive), original) + } + + func testOneClickDisabledOpensArchiveBrowser() throws { + let directory = try makeWorkDir("one-click-disabled") + defer { try? FileManager.default.removeItem(at: directory) } + let archive = try copyOneClickFixture(into: directory) + let app = openForOneClickExtraction(archive, destination: "sameFolder", enabled: false) + defer { app.terminate() } + + XCTAssertTrue(app.staticTexts["hello world.txt"].firstMatch.waitForExistence(timeout: 15)) + XCTAssertFalse(FileManager.default.fileExists(atPath: directory.appendingPathComponent("hello world.txt").path)) + } + /// A file can be deleted from an existing zip through the UI: /// select row → toolbar Delete → ⌘S Save → zip on disk updated. func testDeleteFileFromZip() throws { diff --git a/Modules/Sources/Core/AppStorageKeys.swift b/Modules/Sources/Core/AppStorageKeys.swift index de564b58..4af647f2 100644 --- a/Modules/Sources/Core/AppStorageKeys.swift +++ b/Modules/Sources/Core/AppStorageKeys.swift @@ -19,6 +19,10 @@ public enum Keys { /// Whether extraction decides on its own that the result needs a container /// folder named after the archive. On by default. public static let smartExtraction = "smartExtraction" + /// Extract archives opened from Finder instead of showing their contents. + /// Off by default; the destination is remembered independently of the toggle. + public static let oneClickExtraction = "oneClickExtraction" + public static let oneClickExtractionDestination = "oneClickExtractionDestination" /// `smartExtraction`, read from the app group so the Quick Look extension — /// a separate process with its own `.standard` — sees what the app wrote. diff --git a/Modules/Sources/Core/ArchiveExtractor.swift b/Modules/Sources/Core/ArchiveExtractor.swift index 6244807c..ddb7069e 100644 --- a/Modules/Sources/Core/ArchiveExtractor.swift +++ b/Modules/Sources/Core/ArchiveExtractor.swift @@ -207,10 +207,12 @@ final actor ArchiveExtractor { /// - url: archive to extract /// - archiveEngineType: type of engine /// - destination: destination directory + /// - preservingExistingFiles: keep existing items and number conflicting output names public func extractAll( _ url: URL, archiveTypeId: String, to destination: URL, + preservingExistingFiles: Bool = false, onProgress: ArchiveExtractionProgress? = nil ) async throws { _ = destination.startAccessingSecurityScopedResource() @@ -220,8 +222,55 @@ final actor ArchiveExtractor { throw ArchiveError.extractionFailed("Could not determine archive engine for \(archiveTypeId).") } - try await Sandbox.access(url: url) { - try await engine.extract(url, to: destination, passwordResolver: passwordResolver, onProgress: onProgress) + if preservingExistingFiles { + // Decode away from the user's files: direct extraction can truncate + // a matching file, or fail when a file and directory share a name. + // Move whole top-level items afterwards so bundles and nested trees + // stay intact, and never merge into an existing directory. + // Keep staging on the destination volume so the final moves do not + // copy large archives through the system's temporary disk. + let staging = destination.appendingPathComponent(".MacPacker-extract-\(UUID().uuidString)", isDirectory: true) + try FileManager.default.createDirectory(at: staging, withIntermediateDirectories: true) + defer { try? FileManager.default.removeItem(at: staging) } + try await Sandbox.access(url: url) { + try await engine.extract(url, to: staging, passwordResolver: passwordResolver, onProgress: onProgress) + } + for item in try FileManager.default.contentsOfDirectory( + at: staging, includingPropertiesForKeys: [.isDirectoryKey, .isPackageKey] + ).sorted(by: { $0.lastPathComponent < $1.lastPathComponent }) { + try Task.checkCancellation() + try movePreservingExistingItem(item, to: destination) + } + } else { + try await Sandbox.access(url: url) { + try await engine.extract(url, to: destination, passwordResolver: passwordResolver, onProgress: onProgress) + } + } + } + + private func movePreservingExistingItem(_ item: URL, to destination: URL) throws { + let fm = FileManager.default + let values = try item.resourceValues(forKeys: [.isDirectoryKey, .isPackageKey]) + let isFolder = values.isDirectory == true && values.isPackage != true + let ext = isFolder ? "" : item.pathExtension + let stem = ext.isEmpty ? item.lastPathComponent : item.deletingPathExtension().lastPathComponent + let suffix = ext.isEmpty ? "" : ".\(ext)" + var number = 1 + while true { + let name = number == 1 ? item.lastPathComponent : "\(stem) (\(number))\(suffix)" + let target = destination.appendingPathComponent(name) + // Unlike fileExists, attributesOfItem also sees dangling symlinks. + if (try? fm.attributesOfItem(atPath: target.path)) != nil { + number += 1 + continue + } + do { + try fm.moveItem(at: item, to: target) + return + } catch let error as NSError where error.domain == NSCocoaErrorDomain && error.code == NSFileWriteFileExistsError { + // Another extraction may have taken this name since the probe. + number += 1 + } } } } diff --git a/Modules/Sources/Core/ArchiveState.swift b/Modules/Sources/Core/ArchiveState.swift index bdb85f87..cbc9e203 100644 --- a/Modules/Sources/Core/ArchiveState.swift +++ b/Modules/Sources/Core/ArchiveState.swift @@ -1735,7 +1735,8 @@ extension ArchiveState { /// - Parameters: /// - destination: destination folder /// - smart: see `extract(items:to:smart:)` - public func extract(to destination: URL, smart: Bool) { + /// - preservingExistingFiles: stage output, then number conflicting top-level names + public func extract(to destination: URL, smart: Bool, preservingExistingFiles: Bool = false) { isBusy = true updateStatus(.processing) @@ -1786,6 +1787,7 @@ extension ArchiveState { archiveUrl, archiveTypeId: archiveTypeId, to: target, + preservingExistingFiles: preservingExistingFiles, onProgress: makeEngineProgress(jobId: jobId, cancelFlag: cancelFlag) ) progressCenter.finish(jobId, .done) diff --git a/Modules/Sources/Core/Launch.swift b/Modules/Sources/Core/Launch.swift index 6b58af4f..83ecaf5b 100644 --- a/Modules/Sources/Core/Launch.swift +++ b/Modules/Sources/Core/Launch.swift @@ -31,6 +31,8 @@ public struct Launch: Sendable { case openWith /// A request from the Finder extension, for an entry of its menu. case finderExtension + /// An archive opened from Finder with automatic extraction enabled. + case oneClickExtraction } /// What the launch was started for, once that is known. @@ -49,7 +51,7 @@ public struct Launch: Sendable { return true // A Finder action extracts or compresses and leaves the screen as it // was, or opens the one window it is about (#279). - case .launchParameters, .finderExtension: + case .launchParameters, .finderExtension, .oneClickExtraction: return false } } @@ -63,7 +65,7 @@ public struct Launch: Sendable { switch reason { case .app, .launchParameters, .openWith: true - case .finderExtension: + case .finderExtension, .oneClickExtraction: usedAsApp // not known yet: the url of a Finder action can still be on its way case nil: @@ -82,6 +84,7 @@ public struct Launch: Sendable { /// - somethingOnScreen: a window is up, or about to be: progress, an /// error, a question public func isOver(usedAsApp: Bool, actionUnderWay: Bool, somethingOnScreen: Bool) -> Bool { - reason == .finderExtension && !usedAsApp && !actionUnderWay && !somethingOnScreen + (reason == .finderExtension || reason == .oneClickExtraction) + && !usedAsApp && !actionUnderWay && !somethingOnScreen } } diff --git a/Modules/Sources/Core/OneClickExtractionDestination.swift b/Modules/Sources/Core/OneClickExtractionDestination.swift new file mode 100644 index 00000000..daa95ab5 --- /dev/null +++ b/Modules/Sources/Core/OneClickExtractionDestination.swift @@ -0,0 +1,39 @@ +import Foundation + +/// An explicit destination choice, independent of Smart Extraction's container rule. +public enum OneClickExtractionDestination: String, CaseIterable, Sendable { + case sameFolder + case archiveFolder + case chooseFolder + + public static func saved(in defaults: UserDefaults = .standard) -> Self { + defaults.string(forKey: Keys.oneClickExtractionDestination) + .flatMap(Self.init(rawValue:)) ?? .archiveFolder + } + + /// `nil` means the caller must ask for a destination before extracting. + public func directory(for archive: URL, detector: ArchiveTypeDetector) -> URL? { + switch self { + case .sameFolder: + return archive.deletingLastPathComponent() + case .archiveFolder: + // Keep an existing extraction (or an extensionless source archive) + // intact by creating a new sibling, as Smart Extraction does. + let parent = archive.deletingLastPathComponent() + let stripped = detector.getNameWithoutExtension(for: archive) + let name = stripped.isEmpty || stripped == "." || stripped == ".." + ? archive.lastPathComponent : stripped + return Sandbox.accessSync(url: parent) { + var folder = parent.appendingPathComponent(name, isDirectory: true) + var suffix = 2 + while FileManager.default.fileExists(atPath: folder.path) { + folder = parent.appendingPathComponent("\(name) (\(suffix))", isDirectory: true) + suffix += 1 + } + return folder + } + case .chooseFolder: + return nil + } + } +} diff --git a/Modules/Tests/CoreTests/LaunchTests.swift b/Modules/Tests/CoreTests/LaunchTests.swift index 06f0ebaa..9e5ae0ad 100644 --- a/Modules/Tests/CoreTests/LaunchTests.swift +++ b/Modules/Tests/CoreTests/LaunchTests.swift @@ -24,6 +24,18 @@ extension AllCoreTests { #expect(!shown) } + @Test func oneClickExtractionHasNoLaunchWindowsAndQuitsWhenDone() { + var launch = Launch() + let shown = launch.started(for: .oneClickExtraction) + #expect(!shown) + #expect(!launch.checksForUpdates(usedAsApp: false)) + #expect(launch.checksForUpdates(usedAsApp: true)) + #expect(launch.isOver(usedAsApp: false, actionUnderWay: false, somethingOnScreen: false)) + #expect(!launch.isOver(usedAsApp: false, actionUnderWay: true, somethingOnScreen: false)) + #expect(!launch.isOver(usedAsApp: false, actionUnderWay: false, somethingOnScreen: true)) + #expect(!launch.isOver(usedAsApp: true, actionUnderWay: false, somethingOnScreen: false)) + } + @Test func openingTheAppShowsTheLaunchWindows() { var launch = Launch() let shown = launch.started(for: .app) @@ -47,7 +59,7 @@ extension AllCoreTests { /// Only the launch decides. A Finder action sent to the running app /// does not bring the launch windows up a second time, and an archive /// opened after a Finder launch does not bring them up at all. - @Test(arguments: [Launch.Reason.app, .openWith, .finderExtension, .launchParameters]) + @Test(arguments: [Launch.Reason.app, .openWith, .finderExtension, .launchParameters, .oneClickExtraction]) func whatComesAfterTheLaunchShowsNoLaunchWindows(first: Launch.Reason) { var launch = Launch() _ = launch.started(for: first) diff --git a/Modules/Tests/CoreTests/OneClickExtractionTests.swift b/Modules/Tests/CoreTests/OneClickExtractionTests.swift new file mode 100644 index 00000000..6cb37bff --- /dev/null +++ b/Modules/Tests/CoreTests/OneClickExtractionTests.swift @@ -0,0 +1,108 @@ +import Foundation +import Testing +@testable import Core + +extension AllCoreTests { + struct OneClickExtractionTests { + @Test func missingOrUnknownDestinationUsesArchiveFolder() throws { + let suite = "OneClickExtractionTests.\(UUID().uuidString)" + let defaults = try #require(UserDefaults(suiteName: suite)) + defer { defaults.removePersistentDomain(forName: suite) } + + #expect(OneClickExtractionDestination.saved(in: defaults) == .archiveFolder) + defaults.set("unknown", forKey: Keys.oneClickExtractionDestination) + #expect(OneClickExtractionDestination.saved(in: defaults) == .archiveFolder) + + defaults.set(OneClickExtractionDestination.chooseFolder.rawValue, + forKey: Keys.oneClickExtractionDestination) + defaults.set(false, forKey: Keys.oneClickExtraction) + #expect(OneClickExtractionDestination.saved(in: defaults) == .chooseFolder) + } + + @Test func explicitDestinationsAndCompoundNames() throws { + let parent = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString) + let archive = parent.appendingPathComponent("Photos.TAR.GZ") + let detector = ArchiveTypeDetector(catalog: ArchiveTypeCatalog()) + + #expect(OneClickExtractionDestination.sameFolder.directory(for: archive, detector: detector)?.path == parent.path) + #expect(OneClickExtractionDestination.archiveFolder.directory(for: archive, detector: detector)?.lastPathComponent == "Photos") + #expect(OneClickExtractionDestination.chooseFolder.directory(for: archive, detector: detector) == nil) + #expect(!FileManager.default.fileExists(atPath: parent.path), "Resolving a destination must not create it") + } + + @Test func namedFolderPreservesExistingOutput() throws { + let parent = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString) + try FileManager.default.createDirectory(at: parent.appendingPathComponent("Photos (2)"), withIntermediateDirectories: true) + defer { try? FileManager.default.removeItem(at: parent) } + // A file as well as a directory can occupy the desired folder name. + try Data("keep me".utf8).write(to: parent.appendingPathComponent("Photos")) + + let destination = OneClickExtractionDestination.archiveFolder.directory( + for: parent.appendingPathComponent("Photos.ZIP"), + detector: ArchiveTypeDetector(catalog: ArchiveTypeCatalog())) + + #expect(destination?.lastPathComponent == "Photos (3)") + #expect(try Data(contentsOf: parent.appendingPathComponent("Photos")) == Data("keep me".utf8)) + } + + @Test func extensionlessArchiveGetsItsOwnFolder() throws { + let parent = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString) + try FileManager.default.createDirectory(at: parent, withIntermediateDirectories: true) + defer { try? FileManager.default.removeItem(at: parent) } + let fixture = try #require(Bundle.module.url(forResource: "defaultArchives", withExtension: nil)) + .appendingPathComponent("defaultArchive.zip") + let archive = parent.appendingPathComponent("Photos") + try FileManager.default.copyItem(at: fixture, to: archive) + let detector = ArchiveTypeDetector(catalog: ArchiveTypeCatalog()) + + #expect(detector.detect(for: archive) != nil) + #expect(OneClickExtractionDestination.archiveFolder.directory(for: archive, detector: detector)?.lastPathComponent == "Photos (2)") + } + + @MainActor @Test(arguments: ZipReader.allCases, [false, true]) + func extractionPreservesExistingOutput(reader: ZipReader, fileBlockedByDirectory: Bool) async throws { + let fm = FileManager.default + let destination = fm.temporaryDirectory.appendingPathComponent(UUID().uuidString) + try fm.createDirectory(at: destination, withIntermediateDirectories: true) + defer { try? fm.removeItem(at: destination) } + + let marker = Data("keep existing output".utf8) + let existing = destination.appendingPathComponent("hello world.txt") + if fileBlockedByDirectory { + try fm.createDirectory(at: existing, withIntermediateDirectories: true) + try marker.write(to: existing.appendingPathComponent("keep.txt")) + } else { + try marker.write(to: existing) + } + try marker.write(to: destination.appendingPathComponent("hello world (2).txt")) + let danglingLink = destination.appendingPathComponent("hello world (3).txt") + try fm.createSymbolicLink(atPath: danglingLink.path, withDestinationPath: "missing.txt") + // An archive directory can also be blocked by an existing file. + try marker.write(to: destination.appendingPathComponent("folder")) + + let fixture = try #require(Bundle.module.url(forResource: "defaultArchives", withExtension: nil)) + .appendingPathComponent("defaultArchive.zip") + let content = try #require(Bundle.module.url(forResource: "defaultArchiveContent", withExtension: nil)) + let state = ArchiveState(catalog: ArchiveTypeCatalog(), engineSelector: reader.selector) + state.progressCenter = ExtractionProgressCenter() + state.open(url: fixture) + try await state.openTask?.value + await withCheckedContinuation { continuation in + state.onStatusChange = { status in + if status == .done { continuation.resume() } + } + state.extract(to: destination, smart: false, preservingExistingFiles: true) + } + try #require(state.error == nil, "Extraction failed: \(state.error ?? "")") + + #expect(try Data(contentsOf: fileBlockedByDirectory ? existing.appendingPathComponent("keep.txt") : existing) == marker) + #expect(try Data(contentsOf: destination.appendingPathComponent("hello world (2).txt")) == marker) + #expect(try fm.destinationOfSymbolicLink(atPath: danglingLink.path) == "missing.txt") + #expect(try Data(contentsOf: destination.appendingPathComponent("folder")) == marker) + #expect(try Data(contentsOf: destination.appendingPathComponent("hello world (4).txt")) == Data(contentsOf: content.appendingPathComponent("hello world.txt"))) + #expect(try Data(contentsOf: destination.appendingPathComponent("folder (2)/README.md")) == Data(contentsOf: content.appendingPathComponent("folder/README.md"))) + #expect(try Data(contentsOf: destination.appendingPathComponent("folder (2)/NestedArchive.zip")) == Data(contentsOf: content.appendingPathComponent("folder/NestedArchive.zip"))) + #expect(try fm.contentsOfDirectory(atPath: destination.path).allSatisfy { !$0.hasPrefix(".MacPacker-extract-") }) + } + } +} diff --git a/scripts/sync-localizations.sh b/scripts/sync-localizations.sh new file mode 100644 index 00000000..1837e19e --- /dev/null +++ b/scripts/sync-localizations.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# A command-line build emits .stringsdata; the Xcode IDE normally performs +# this final sync itself. Let Apple's tool own catalog keys and metadata. +set -euo pipefail + +derived_data=${1:?usage: sync-localizations.sh /path/to/DerivedData} +stringsdata=() +while IFS= read -r -d '' file; do + stringsdata+=("$file") +done < <(find "$derived_data/Build/Intermediates.noindex" -type f \ + \( -path '*/MacPacker.build/Objects-normal/arm64/*' \ + -o -path '*/FinderExtension.build/Objects-normal/arm64/*' \) \ + -name '*.stringsdata' -print0) + +if [ "${#stringsdata[@]}" -eq 0 ]; then + echo "No app localization data found; build the universal app first." >&2 + exit 1 +fi + +# The Finder extension shares the app's catalog. Include both targets so +# their existing keys stay active; use one architecture to avoid duplicates. +for catalog in MacPacker/Localizable.xcstrings MacPacker/LeanBytes.xcstrings; do + xcrun xcstringstool sync "$catalog" --stringsdata "${stringsdata[@]}" +done