lang for toolchain

This commit is contained in:
FalsePattern 2025-04-09 00:48:08 +02:00
parent ee5a2463b9
commit b485c1e48c
Signed by: falsepattern
GPG key ID: E930CDEC50C50E23
10 changed files with 85 additions and 93 deletions

View file

@ -22,6 +22,7 @@
package com.falsepattern.zigbrains.project.toolchain.base package com.falsepattern.zigbrains.project.toolchain.base
import com.falsepattern.zigbrains.ZigBrainsBundle
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.ui.components.JBTextField import com.intellij.ui.components.JBTextField
import com.intellij.ui.dsl.builder.AlignX import com.intellij.ui.dsl.builder.AlignX
@ -35,7 +36,7 @@ abstract class ZigToolchainPanel<T: ZigToolchain>: Disposable {
set(value) {nameField.text = value ?: ""} set(value) {nameField.text = value ?: ""}
open fun attach(p: Panel): Unit = with(p) { open fun attach(p: Panel): Unit = with(p) {
row("Name") { row(ZigBrainsBundle.message("settings.toolchain.base.name.label")) {
cell(nameField).resizableColumn().align(AlignX.FILL) cell(nameField).resizableColumn().align(AlignX.FILL)
} }
separator() separator()

View file

@ -53,12 +53,11 @@ import javax.swing.DefaultComboBoxModel
import javax.swing.JList import javax.swing.JList
import javax.swing.event.DocumentEvent import javax.swing.event.DocumentEvent
//TODO lang
object Downloader { object Downloader {
suspend fun downloadToolchain(component: Component): ZigToolchain? { suspend fun downloadToolchain(component: Component): ZigToolchain? {
val info = withModalProgress( val info = withModalProgress(
ModalTaskOwner.component(component), ModalTaskOwner.component(component),
"Fetching zig version information", ZigBrainsBundle.message("settings.toolchain.downloader.progress.fetch"),
TaskCancellation.cancellable() TaskCancellation.cancellable()
) { ) {
ZigVersionInfo.downloadVersionList() ZigVersionInfo.downloadVersionList()
@ -68,7 +67,7 @@ object Downloader {
} ?: return null } ?: return null
withModalProgress( withModalProgress(
ModalTaskOwner.component(component), ModalTaskOwner.component(component),
"Installing Zig ${version.version}", ZigBrainsBundle.message("settings.toolchain.downloader.progress.install", version.version.rawVersion),
TaskCancellation.cancellable() TaskCancellation.cancellable()
) { ) {
version.downloadAndUnpack(downloadPath) version.downloadAndUnpack(downloadPath)
@ -94,7 +93,7 @@ object Downloader {
val outputPath = textFieldWithBrowseButton( val outputPath = textFieldWithBrowseButton(
null, null,
FileChooserDescriptorFactory.createSingleFolderDescriptor() FileChooserDescriptorFactory.createSingleFolderDescriptor()
.withTitle(ZigBrainsBundle.message("dialog.title.zig-toolchain")) .withTitle(ZigBrainsBundle.message("settings.toolchain.downloader.chooser.title"))
) )
Disposer.register(dialog, outputPath) Disposer.register(dialog, outputPath)
outputPath.textField.columns = 50 outputPath.textField.columns = 50
@ -110,14 +109,14 @@ object Downloader {
errorMessageBox.icon = AllIcons.General.Error errorMessageBox.icon = AllIcons.General.Error
dialog.setOkActionEnabled(false) dialog.setOkActionEnabled(false)
} }
errorMessageBox.text = when(state) { errorMessageBox.text = ZigBrainsBundle.message(when(state) {
DirectoryState.Invalid -> "Invalid path" DirectoryState.Invalid -> "settings.toolchain.downloader.state.invalid"
DirectoryState.NotAbsolute -> "Must be an absolute path" DirectoryState.NotAbsolute -> "settings.toolchain.downloader.state.not-absolute"
DirectoryState.NotDirectory -> "Path is not a directory" DirectoryState.NotDirectory -> "settings.toolchain.downloader.state.not-directory"
DirectoryState.NotEmpty -> "Directory is not empty" DirectoryState.NotEmpty -> "settings.toolchain.downloader.state.not-empty"
DirectoryState.CreateNew -> "Directory will be created" DirectoryState.CreateNew -> "settings.toolchain.downloader.state.create-new"
DirectoryState.Ok -> "Directory OK" DirectoryState.Ok -> "settings.toolchain.downloader.state.ok"
} })
dialog.window.repaint() dialog.window.repaint()
} }
outputPath.whenFocusGained { outputPath.whenFocusGained {
@ -133,16 +132,16 @@ object Downloader {
outputPath.text = System.getProperty("user.home") + "/.zig/" + item.version outputPath.text = System.getProperty("user.home") + "/.zig/" + item.version
val size = item.dist.size val size = item.dist.size
val sizeMb = size / (1024f * 1024f) val sizeMb = size / (1024f * 1024f)
archiveSizeCell?.comment?.text = "Archive size: %.2fMB".format(sizeMb) archiveSizeCell?.comment?.text = ZigBrainsBundle.message("settings.toolchain.downloader.archive-size.text", "%.2fMB".format(sizeMb))
} }
theList.addItemListener { theList.addItemListener {
detect(it.item as ZigVersionInfo) detect(it.item as ZigVersionInfo)
} }
val center = panel { val center = panel {
row("Version:") { row(ZigBrainsBundle.message("settings.toolchain.downloader.version.label")) {
cell(theList).resizableColumn().align(AlignX.FILL) cell(theList).resizableColumn().align(AlignX.FILL)
} }
row("Location:") { row(ZigBrainsBundle.message("settings.toolchain.downloader.location.label")) {
cell(outputPath).resizableColumn().align(AlignX.FILL).apply { archiveSizeCell = comment("") } cell(outputPath).resizableColumn().align(AlignX.FILL).apply { archiveSizeCell = comment("") }
} }
row { row {
@ -152,9 +151,9 @@ object Downloader {
} }
detect(info[0]) detect(info[0])
dialog.centerPanel(center) dialog.centerPanel(center)
dialog.setTitle("Zig Downloader") dialog.setTitle(ZigBrainsBundle.message("settings.toolchain.downloader.title"))
dialog.addCancelAction() dialog.addCancelAction()
dialog.addOkAction().also { it.setText("Download") } dialog.addOkAction().also { it.setText(ZigBrainsBundle.message("settings.toolchain.downloader.ok-action")) }
if (!dialog.showAndGet()) { if (!dialog.showAndGet()) {
return null return null
} }

View file

@ -55,7 +55,7 @@ object LocalSelector {
val path = textFieldWithBrowseButton( val path = textFieldWithBrowseButton(
null, null,
FileChooserDescriptorFactory.createSingleFolderDescriptor() FileChooserDescriptorFactory.createSingleFolderDescriptor()
.withTitle(ZigBrainsBundle.message("dialog.title.zig-toolchain")) .withTitle(ZigBrainsBundle.message("settings.toolchain.local-selector.chooser.title"))
) )
Disposer.register(dialog, path) Disposer.register(dialog, path)
path.textField.columns = 50 path.textField.columns = 50
@ -65,7 +65,7 @@ object LocalSelector {
val tc = LocalZigToolchain.tryFromPathString(path.text) val tc = LocalZigToolchain.tryFromPathString(path.text)
if (tc == null) { if (tc == null) {
errorMessageBox.icon = AllIcons.General.Error errorMessageBox.icon = AllIcons.General.Error
errorMessageBox.text = "Invalid toolchain path" errorMessageBox.text = ZigBrainsBundle.message("settings.toolchain.local-selector.state.invalid")
dialog.setOkActionEnabled(false) dialog.setOkActionEnabled(false)
} else if (ZigToolchainListService } else if (ZigToolchainListService
.getInstance() .getInstance()
@ -74,17 +74,18 @@ object LocalSelector {
.any { it.location == tc.location } .any { it.location == tc.location }
) { ) {
errorMessageBox.icon = AllIcons.General.Warning errorMessageBox.icon = AllIcons.General.Warning
errorMessageBox.text = tc.name?.let { "Toolchain already exists as \"$it\"" } ?: "Toolchain already exists" errorMessageBox.text = tc.name?.let { ZigBrainsBundle.message("settings.toolchain.local-selector.state.already-exists-named", it) }
?: ZigBrainsBundle.message("settings.toolchain.local-selector.state.already-exists-unnamed")
dialog.setOkActionEnabled(true) dialog.setOkActionEnabled(true)
} else { } else {
errorMessageBox.icon = Icons.Zig errorMessageBox.icon = Icons.Zig
errorMessageBox.text = tc.name ?: "OK" errorMessageBox.text = tc.name ?: ZigBrainsBundle.message("settings.toolchain.local-selector.state.ok")
dialog.setOkActionEnabled(true) dialog.setOkActionEnabled(true)
} }
} }
}) })
val center = panel { val center = panel {
row("Path:") { row(ZigBrainsBundle.message("settings.toolchain.local-selector.path.label")) {
cell(path).resizableColumn().align(AlignX.FILL) cell(path).resizableColumn().align(AlignX.FILL)
} }
row { row {
@ -93,9 +94,9 @@ object LocalSelector {
} }
} }
dialog.centerPanel(center) dialog.centerPanel(center)
dialog.setTitle("Zig Browser") dialog.setTitle(ZigBrainsBundle.message("settings.toolchain.local-selector.title"))
dialog.addCancelAction() dialog.addCancelAction()
dialog.addOkAction().also { it.setText("Add") } dialog.addOkAction().also { it.setText(ZigBrainsBundle.message("settings.toolchain.local-selector.ok-action")) }
if (!dialog.showAndGet()) { if (!dialog.showAndGet()) {
return null return null
} }

View file

@ -22,6 +22,7 @@
package com.falsepattern.zigbrains.project.toolchain.downloader package com.falsepattern.zigbrains.project.toolchain.downloader
import com.falsepattern.zigbrains.ZigBrainsBundle
import com.falsepattern.zigbrains.shared.Unarchiver import com.falsepattern.zigbrains.shared.Unarchiver
import com.intellij.openapi.application.PathManager import com.intellij.openapi.application.PathManager
import com.intellij.openapi.progress.EmptyProgressIndicator import com.intellij.openapi.progress.EmptyProgressIndicator
@ -85,7 +86,7 @@ data class ZigVersionInfo(
val service = DownloadableFileService.getInstance() val service = DownloadableFileService.getInstance()
val tempFile = FileUtil.createTempFile(tempPluginDir, "index", ".json", false, false) val tempFile = FileUtil.createTempFile(tempPluginDir, "index", ".json", false, false)
val desc = service.createFileDescription("https://ziglang.org/download/index.json", tempFile.name) val desc = service.createFileDescription("https://ziglang.org/download/index.json", tempFile.name)
val downloader = service.createDownloader(listOf(desc), "Zig version information") val downloader = service.createDownloader(listOf(desc), ZigBrainsBundle.message("settings.toolchain.downloader.service.index"))
val downloadResults = coroutineToIndicator { val downloadResults = coroutineToIndicator {
downloader.download(tempPluginDir) downloader.download(tempPluginDir)
} }
@ -110,7 +111,7 @@ private suspend fun downloadTarball(dist: ZigVersionInfo.Tarball, into: Path, re
val fileName = dist.tarball.substringAfterLast('/') val fileName = dist.tarball.substringAfterLast('/')
val tempFile = FileUtil.createTempFile(into.toFile(), "tarball", fileName, false, false) val tempFile = FileUtil.createTempFile(into.toFile(), "tarball", fileName, false, false)
val desc = service.createFileDescription(dist.tarball, tempFile.name) val desc = service.createFileDescription(dist.tarball, tempFile.name)
val downloader = service.createDownloader(listOf(desc), "Zig tarball") val downloader = service.createDownloader(listOf(desc), ZigBrainsBundle.message("settings.toolchain.downloader.service.tarball"))
val downloadResults = reporter.sizedStep(100) { val downloadResults = reporter.sizedStep(100) {
coroutineToIndicator { coroutineToIndicator {
downloader.download(into.toFile()) downloader.download(into.toFile())
@ -131,7 +132,7 @@ private suspend fun flattenDownloadDir(dir: Path, reporter: ProgressReporter) {
coroutineToIndicator { coroutineToIndicator {
val indicator = ProgressManager.getInstance().progressIndicator ?: EmptyProgressIndicator() val indicator = ProgressManager.getInstance().progressIndicator ?: EmptyProgressIndicator()
indicator.isIndeterminate = true indicator.isIndeterminate = true
indicator.text = "Flattening directory" indicator.text = ZigBrainsBundle.message("settings.toolchain.downloader.progress.flatten")
Files.newDirectoryStream(src).use { stream -> Files.newDirectoryStream(src).use { stream ->
stream.forEach { stream.forEach {
indicator.text2 = it.name indicator.text2 = it.name

View file

@ -77,13 +77,13 @@ class LocalZigToolchainPanel() : ZigToolchainPanel<LocalZigToolchain>() {
override fun attach(p: Panel): Unit = with(p) { override fun attach(p: Panel): Unit = with(p) {
super.attach(p) super.attach(p)
row(ZigBrainsBundle.message("settings.project.label.toolchain")) { row(ZigBrainsBundle.message("settings.toolchain.local.path.label")) {
cell(pathToToolchain).resizableColumn().align(AlignX.FILL) cell(pathToToolchain).resizableColumn().align(AlignX.FILL)
} }
row(ZigBrainsBundle.message("settings.project.label.toolchain-version")) { row(ZigBrainsBundle.message("settings.toolchain.local.version.label")) {
cell(toolchainVersion) cell(toolchainVersion)
} }
row(ZigBrainsBundle.message("settings.project.label.std-location")) { row(ZigBrainsBundle.message("settings.toolchain.local.std.label")) {
cell(pathToStd).resizableColumn().align(AlignX.FILL) cell(pathToStd).resizableColumn().align(AlignX.FILL)
cell(stdFieldOverride) cell(stdFieldOverride)
} }

View file

@ -22,6 +22,7 @@
package com.falsepattern.zigbrains.project.toolchain.ui package com.falsepattern.zigbrains.project.toolchain.ui
import com.falsepattern.zigbrains.ZigBrainsBundle
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainListService import com.falsepattern.zigbrains.project.toolchain.ZigToolchainListService
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainService import com.falsepattern.zigbrains.project.toolchain.ZigToolchainService
import com.falsepattern.zigbrains.project.toolchain.base.suggestZigToolchains import com.falsepattern.zigbrains.project.toolchain.base.suggestZigToolchains
@ -58,7 +59,7 @@ import kotlin.collections.addAll
class ZigToolchainEditor(private val project: Project): Configurable { class ZigToolchainEditor(private val project: Project): Configurable {
private var myUi: UI? = null private var myUi: UI? = null
override fun getDisplayName(): @NlsContexts.ConfigurableName String? { override fun getDisplayName(): @NlsContexts.ConfigurableName String? {
return "Zig" return ZigBrainsBundle.message("settings.toolchain.editor.display-name")
} }
override fun createComponent(): JComponent? { override fun createComponent(): JComponent? {
@ -150,9 +151,9 @@ class ZigToolchainEditor(private val project: Project): Configurable {
} }
fun attach(p: Panel): Unit = with(p) { fun attach(p: Panel): Unit = with(p) {
row("Toolchain") { row(ZigBrainsBundle.message("settings.toolchain.editor.toolchain.label")) {
cell(toolchainBox).resizableColumn().align(AlignX.FILL) cell(toolchainBox).resizableColumn().align(AlignX.FILL)
button("Funny") { e -> button(ZigBrainsBundle.message("settings.toolchain.editor.toolchain.edit-button.name")) { e ->
zigCoroutineScope.launchWithEDT(toolchainBox.asContextElement()) { zigCoroutineScope.launchWithEDT(toolchainBox.asContextElement()) {
val config = ZigToolchainListEditor() val config = ZigToolchainListEditor()
var inited = false var inited = false
@ -211,7 +212,7 @@ private fun getModelList(): List<TCListElemIn> {
modelList.addAll(ZigToolchainListService.getInstance().toolchains.map { it.asActual() }) modelList.addAll(ZigToolchainListService.getInstance().toolchains.map { it.asActual() })
modelList.add(Separator("", true)) modelList.add(Separator("", true))
modelList.addAll(TCListElem.fetchGroup) modelList.addAll(TCListElem.fetchGroup)
modelList.add(Separator("Detected toolchains", true)) modelList.add(Separator(ZigBrainsBundle.message("settings.toolchain.model.detected.separator"), true))
modelList.addAll(suggestZigToolchains().map { it.asSuggested() }) modelList.addAll(suggestZigToolchains().map { it.asSuggested() })
return modelList return modelList
} }

View file

@ -86,11 +86,11 @@ class ZigToolchainListEditor : MasterDetailsComponent(), ZigToolchainListService
} }
override fun createActions(fromPopup: Boolean): List<AnAction> { override fun createActions(fromPopup: Boolean): List<AnAction> {
val add = object : DumbAwareAction({ "lmaoo" }, Presentation.NULL_STRING, IconUtil.addIcon) { val add = object : DumbAwareAction({ ZigBrainsBundle.message("settings.toolchain.list.add-action.name") }, Presentation.NULL_STRING, IconUtil.addIcon) {
override fun actionPerformed(e: AnActionEvent) { override fun actionPerformed(e: AnActionEvent) {
val modelList = ArrayList<TCListElemIn>() val modelList = ArrayList<TCListElemIn>()
modelList.addAll(TCListElem.fetchGroup) modelList.addAll(TCListElem.fetchGroup)
modelList.add(Separator("Detected toolchains", true)) modelList.add(Separator(ZigBrainsBundle.message("settings.toolchain.model.detected.separator"), true))
modelList.addAll(suggestZigToolchains().map { it.asSuggested() }) modelList.addAll(suggestZigToolchains().map { it.asSuggested() })
val model = TCModel.Companion(modelList) val model = TCModel.Companion(modelList)
val context = TCContext(null, model) val context = TCContext(null, model)
@ -134,9 +134,9 @@ class ZigToolchainListEditor : MasterDetailsComponent(), ZigToolchainListService
super.reset() super.reset()
} }
override fun getEmptySelectionString() = ZigBrainsBundle.message("settings.toolchains.empty") override fun getEmptySelectionString() = ZigBrainsBundle.message("settings.toolchain.list.empty")
override fun getDisplayName() = ZigBrainsBundle.message("settings.toolchains.title") override fun getDisplayName() = ZigBrainsBundle.message("settings.toolchain.list.title")
private fun addToolchain(uuid: UUID, toolchain: ZigToolchain) { private fun addToolchain(uuid: UUID, toolchain: ZigToolchain) {
val node = MyNode(toolchain.createNamedConfigurable(uuid)) val node = MyNode(toolchain.createNamedConfigurable(uuid))

View file

@ -24,6 +24,7 @@ package com.falsepattern.zigbrains.project.toolchain.ui
import ai.grazie.utils.attributes.value import ai.grazie.utils.attributes.value
import com.falsepattern.zigbrains.Icons import com.falsepattern.zigbrains.Icons
import com.falsepattern.zigbrains.ZigBrainsBundle
import com.falsepattern.zigbrains.project.toolchain.base.render import com.falsepattern.zigbrains.project.toolchain.base.render
import com.intellij.icons.AllIcons import com.intellij.icons.AllIcons
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
@ -208,17 +209,17 @@ internal class TCCellRenderer(val getModel: () -> TCModel) : ColoredListCellRend
is TCListElem.Download -> { is TCListElem.Download -> {
icon = AllIcons.Actions.Download icon = AllIcons.Actions.Download
append("Download Zig\u2026") append(ZigBrainsBundle.message("settings.toolchain.model.download.text"))
} }
is TCListElem.FromDisk -> { is TCListElem.FromDisk -> {
icon = AllIcons.General.OpenDisk icon = AllIcons.General.OpenDisk
append("Add Zig from disk\u2026") append(ZigBrainsBundle.message("settings.toolchain.model.from-disk.text"))
} }
is TCListElem.None, null -> { is TCListElem.None, null -> {
icon = AllIcons.General.BalloonError icon = AllIcons.General.BalloonError
append("<No Toolchain>", SimpleTextAttributes.ERROR_ATTRIBUTES) append(ZigBrainsBundle.message("settings.toolchain.model.none.text"), SimpleTextAttributes.ERROR_ATTRIBUTES)
} }
} }
} }

View file

@ -1,49 +0,0 @@
/*
* This file is part of ZigBrains.
*
* Copyright (C) 2023-2025 FalsePattern
* All Rights Reserved
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* ZigBrains is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, only version 3 of the License.
*
* ZigBrains is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
*/
package com.falsepattern.zigbrains.project.toolchain.ui.popup
import com.falsepattern.zigbrains.Icons
import com.falsepattern.zigbrains.project.toolchain.base.render
import com.falsepattern.zigbrains.project.toolchain.ui.Separator
import com.falsepattern.zigbrains.project.toolchain.ui.TCListElem
import com.falsepattern.zigbrains.project.toolchain.ui.TCListElemIn
import com.intellij.icons.AllIcons
import com.intellij.openapi.project.Project
import com.intellij.ui.CellRendererPanel
import com.intellij.ui.CollectionListModel
import com.intellij.ui.ColoredListCellRenderer
import com.intellij.ui.GroupHeaderSeparator
import com.intellij.ui.SimpleColoredComponent
import com.intellij.ui.components.panels.OpaquePanel
import com.intellij.ui.popup.list.ComboBoxPopup
import com.intellij.util.Consumer
import com.intellij.util.ui.EmptyIcon
import com.intellij.util.ui.JBUI
import com.intellij.util.ui.UIUtil
import java.awt.BorderLayout
import java.awt.Component
import java.util.IdentityHashMap
import javax.accessibility.AccessibleContext
import javax.swing.JList
import javax.swing.border.Border

View file

@ -98,8 +98,6 @@ settings.project.label.toolchain=Toolchain location
settings.project.label.toolchain-version=Detected zig version settings.project.label.toolchain-version=Detected zig version
settings.project.label.override-std=Override standard library settings.project.label.override-std=Override standard library
settings.project.label.std-location=Standard library location settings.project.label.std-location=Standard library location
settings.toolchains.empty=Select a toolchain to view or edit its details here
settings.toolchains.title=Toolchains
toolwindow.stripe.zigbrains.build=Zig toolwindow.stripe.zigbrains.build=Zig
build.tool.window.tree.steps.label=Steps build.tool.window.tree.steps.label=Steps
build.tool.window.tree.build.label=Active builds build.tool.window.tree.build.label=Active builds
@ -112,3 +110,42 @@ build.tool.window.status.error.general=Error while running zig build -l
build.tool.window.status.no-builds=No builds currently in progress build.tool.window.status.no-builds=No builds currently in progress
build.tool.window.status.timeout=zig build -l timed out after {0} seconds. build.tool.window.status.timeout=zig build -l timed out after {0} seconds.
zig=Zig zig=Zig
settings.toolchain.base.name.label=Name
settings.toolchain.local.path.label=Toolchain location
settings.toolchain.local.version.label=Detected zig version
settings.toolchain.local.std.label=Override standard library
settings.toolchain.editor.display-name=Zig
settings.toolchain.editor.toolchain.label=Toolchain
settings.toolchain.editor.toolchain.edit-button.name=Edit
settings.toolchain.model.detected.separator=Detected toolchains
settings.toolchain.model.none.text=<No Toolchain>
settings.toolchain.model.from-disk.text=Add Zig from disk\u2026
settings.toolchain.model.download.text=Download Zig\u2026
settings.toolchain.list.title=Toolchains
settings.toolchain.list.add-action.name=Add New
settings.toolchain.list.empty=Select a toolchain to view or edit its details here
settings.toolchain.downloader.title=Install Zig
settings.toolchain.downloader.version.label=Version:
settings.toolchain.downloader.location.label=Location:
settings.toolchain.downloader.ok-action=Download
settings.toolchain.downloader.progress.fetch=Fetching zig version information
settings.toolchain.downloader.progress.install=Installing Zig {0}
settings.toolchain.downloader.progress.flatten=Flattening unpacked archive
settings.toolchain.downloader.chooser.title=Zig Install Directory
settings.toolchain.downloader.state.invalid=Invalid path
settings.toolchain.downloader.state.not-absolute=Must be an absolute path
settings.toolchain.downloader.state.not-directory=Path is not a directory
settings.toolchain.downloader.state.not-empty=Directory is not empty
settings.toolchain.downloader.state.create-new=Directory will be created
settings.toolchain.downloader.state.ok=Directory OK
settings.toolchain.downloader.archive-size.text=Archive size: {0}
settings.toolchain.downloader.service.index=Zig version information
settings.toolchain.downloader.service.tarball=Zig archive
settings.toolchain.local-selector.title=Select Zig From Disk
settings.toolchain.local-selector.path.label=Path:
settings.toolchain.local-selector.ok-action=Add
settings.toolchain.local-selector.chooser.title=Existing Zig Install Directory
settings.toolchain.local-selector.state.invalid=Invalid toolchain path
settings.toolchain.local-selector.state.already-exists-unnamed=Toolchain already exists
settings.toolchain.local-selector.state.already-exists-named=Toolchain already exists as "{0}"
settings.toolchain.local-selector.state.ok=OK