feat(i18n, gui): add PullProject functionality and translations for multiple languages

- Implement PullProject command in the GUI.
- Add translations for PullProject in German, French, Spanish, Dutch, Polish, Portuguese, Turkish, and Chinese.
- Update keybindings to support pulling projects and images.
This commit is contained in:
Alesc0 2026-04-25 23:25:28 +01:00
parent 7e7aadc207
commit aeb19e9308
23 changed files with 96 additions and 0 deletions

View file

@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>b</kbd>: view bulk commands
<kbd>E</kbd>: exec shell
<kbd>w</kbd>: open in browser (first port is http)
<kbd>P</kbd>: Projekt pullen
<kbd>enter</kbd>: fokussieren aufs Hauptpanel
<kbd>[</kbd>: vorheriges Tab
<kbd>]</kbd>: nächstes Tab
@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>c</kbd>: führe vordefinierten benutzerdefinierten Befehl aus
<kbd>d</kbd>: entferne Image
<kbd>b</kbd>: view bulk commands
<kbd>p</kbd>: pull image
<kbd>enter</kbd>: fokussieren aufs Hauptpanel
<kbd>[</kbd>: vorheriges Tab
<kbd>]</kbd>: nächstes Tab

View file

@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>b</kbd>: view bulk commands
<kbd>E</kbd>: exec shell
<kbd>w</kbd>: open in browser (first port is http)
<kbd>P</kbd>: pull project
<kbd>enter</kbd>: focus main panel
<kbd>[</kbd>: previous tab
<kbd>]</kbd>: next tab
@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>c</kbd>: run predefined custom command
<kbd>d</kbd>: remove image
<kbd>b</kbd>: view bulk commands
<kbd>p</kbd>: pull image
<kbd>enter</kbd>: focus main panel
<kbd>[</kbd>: previous tab
<kbd>]</kbd>: next tab

View file

@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>b</kbd>: ver comandos masivos
<kbd>E</kbd>: ejecutar shell
<kbd>w</kbd>: abrir en navegador (first port is http)
<kbd>P</kbd>: jalar el proyecto
<kbd>enter</kbd>: enfocar panel principal
<kbd>[</kbd>: anterior pestaña
<kbd>]</kbd>: siguiente pestaña
@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>c</kbd>: ejecutar comando personalizado
<kbd>d</kbd>: limpiar imagen
<kbd>b</kbd>: ver comandos masivos
<kbd>p</kbd>: pull image
<kbd>enter</kbd>: enfocar panel principal
<kbd>[</kbd>: anterior pestaña
<kbd>]</kbd>: siguiente pestaña

View file

@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>b</kbd>: voir les commandes groupées
<kbd>E</kbd>: exécuter le shell
<kbd>w</kbd>: ouvrir dans le navigateur (le premier port est http)
<kbd>P</kbd>: tirer le projet
<kbd>enter</kbd>: focus panneau principal
<kbd>[</kbd>: onglet précédent
<kbd>]</kbd>: onglet suivant
@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>c</kbd>: exécuter une commande prédéfinie
<kbd>d</kbd>: supprimer l'image
<kbd>b</kbd>: voir les commandes groupées
<kbd>p</kbd>: pull image
<kbd>enter</kbd>: focus panneau principal
<kbd>[</kbd>: onglet précédent
<kbd>]</kbd>: onglet suivant

View file

@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>b</kbd>: view bulk commands
<kbd>E</kbd>: exec shell
<kbd>w</kbd>: open in browser (first port is http)
<kbd>P</kbd>: project ophalen
<kbd>enter</kbd>: focus hoofdpaneel
<kbd>[</kbd>: vorige tab
<kbd>]</kbd>: volgende tab
@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>c</kbd>: draai een vooraf bedacht aangepaste opdracht
<kbd>d</kbd>: verwijder image
<kbd>b</kbd>: view bulk commands
<kbd>p</kbd>: pull image
<kbd>enter</kbd>: focus hoofdpaneel
<kbd>[</kbd>: vorige tab
<kbd>]</kbd>: volgende tab

View file

@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>b</kbd>: view bulk commands
<kbd>E</kbd>: exec shell
<kbd>w</kbd>: open in browser (first port is http)
<kbd>P</kbd>: pobierz projekt
<kbd>enter</kbd>: skup na głównym panelu
<kbd>[</kbd>: poprzednia zakładka
<kbd>]</kbd>: następna zakładka
@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>c</kbd>: wykonaj predefiniowaną własną komende
<kbd>d</kbd>: usuń obraz
<kbd>b</kbd>: view bulk commands
<kbd>p</kbd>: pull image
<kbd>enter</kbd>: skup na głównym panelu
<kbd>[</kbd>: poprzednia zakładka
<kbd>]</kbd>: następna zakładka

View file

@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>b</kbd>: ver comandos em massa
<kbd>E</kbd>: executar shell
<kbd>w</kbd>: abrir no navegador (primeira porta é http)
<kbd>P</kbd>: puxar projeto
<kbd>enter</kbd>: focar no painel principal
<kbd>[</kbd>: aba anterior
<kbd>]</kbd>: próxima aba
@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>c</kbd>: executar comando personalizado predefinido
<kbd>d</kbd>: remover imagem
<kbd>b</kbd>: ver comandos em massa
<kbd>p</kbd>: pull image
<kbd>enter</kbd>: focar no painel principal
<kbd>[</kbd>: aba anterior
<kbd>]</kbd>: próxima aba

View file

@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>b</kbd>: view bulk commands
<kbd>E</kbd>: exec shell
<kbd>w</kbd>: open in browser (first port is http)
<kbd>P</kbd>: projeyi çek
<kbd>enter</kbd>: ana panele odaklan
<kbd>[</kbd>: önceki sekme
<kbd>]</kbd>: sonraki sekme
@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>c</kbd>: önceden tanımlanmış özel komutu çalıştır
<kbd>d</kbd>: imajı kaldır
<kbd>b</kbd>: view bulk commands
<kbd>p</kbd>: pull image
<kbd>enter</kbd>: ana panele odaklan
<kbd>[</kbd>: önceki sekme
<kbd>]</kbd>: sonraki sekme

View file

@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>b</kbd>: 查看批量命令
<kbd>E</kbd>: 执行shell
<kbd>w</kbd>: 在浏览器中打开(第一个端口为http)
<kbd>P</kbd>: 拉取项目
<kbd>enter</kbd>: 聚焦主面板
<kbd>[</kbd>: 上一个选项卡
<kbd>]</kbd>: 下一个选项卡
@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
<kbd>c</kbd>: 运行预定义的自定义命令
<kbd>d</kbd>: 移除镜像
<kbd>b</kbd>: 查看批量命令
<kbd>p</kbd>: pull image
<kbd>enter</kbd>: 聚焦主面板
<kbd>[</kbd>: 上一个选项卡
<kbd>]</kbd>: 下一个选项卡

View file

@ -25,6 +25,14 @@ type Image struct {
DockerCommand LimitedDockerCommand
}
func (i *Image) Pull(options image.PullOptions) error {
if _, err := i.Client.ImagePull(context.Background(), i.Name+":"+i.Tag, options); err != nil {
return err
}
return nil
}
// Remove removes the image
func (i *Image) Remove(options image.RemoveOptions) error {
if _, err := i.Client.ImageRemove(context.Background(), i.ID, options); err != nil {

View file

@ -166,6 +166,9 @@ type CommandTemplatesConfig struct {
// downs and removes volumes
DownWithVolumes string `yaml:"downWithVolumes,omitempty"`
// pulls all the latest images for the services
Pull string `yaml:"pull,omitempty"`
// DockerCompose is for your docker-compose command. You may want to combine a
// few different docker-compose.yml files together, in which case you can set
// this to "docker compose -f foo/docker-compose.yml -f
@ -391,6 +394,7 @@ func GetDefaultConfig() UserConfig {
Up: "{{ .DockerCompose }} up -d",
Down: "{{ .DockerCompose }} down",
DownWithVolumes: "{{ .DockerCompose }} down --volumes",
Pull: "{{ .DockerCompose }} pull",
UpService: "{{ .DockerCompose }} up -d {{ .Service.Name }}",
RebuildService: "{{ .DockerCompose }} up -d --build {{ .Service.Name }}",
RecreateService: "{{ .DockerCompose }} up -d --force-recreate {{ .Service.Name }}",

View file

@ -179,6 +179,26 @@ func (gui *Gui) handleImagesRemoveMenu(g *gocui.Gui, v *gocui.View) error {
})
}
func (gui *Gui) handleImagePull(g *gocui.Gui, v *gocui.View) error {
type pullImageOption struct {
description string
command string
}
img, err := gui.Panels.Images.GetSelectedItem()
if err != nil {
return nil
}
return gui.WithWaitingStatus(gui.Tr.PullImage, func() error {
err := img.Pull(image.PullOptions{})
if err != nil {
return gui.createErrorPanel(err.Error())
}
return gui.reloadImages()
})
}
func (gui *Gui) handlePruneImages() error {
return gui.createConfirmationPanel(gui.Tr.Confirm, gui.Tr.ConfirmPruneImages, func(g *gocui.Gui, v *gocui.View) error {
return gui.WithWaitingStatus(gui.Tr.PruningStatus, func() error {

View file

@ -509,6 +509,20 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: wrappedHandler(gui.prevScreenMode),
Description: gui.Tr.LcPrevScreenMode,
},
{
ViewName: "services",
Key: 'P',
Modifier: gocui.ModNone,
Handler: gui.handleProjectPull,
Description: gui.Tr.PullProject,
},
{
ViewName: "images",
Key: 'p',
Modifier: gocui.ModNone,
Handler: gui.handleImagePull,
Description: gui.Tr.PullImage,
},
}
for _, panel := range gui.allSidePanels() {

View file

@ -353,6 +353,24 @@ func (gui *Gui) handleProjectUp(g *gocui.Gui, v *gocui.View) error {
}, nil)
}
func (gui *Gui) handleProjectPull(g *gocui.Gui, v *gocui.View) error {
project, _ := gui.Panels.Projects.GetSelectedItem()
if project != nil && project.Name != gui.DockerCommand.LocalProjectName {
return gui.createErrorPanel(gui.Tr.CannotManageNonLocalService)
}
return gui.WithWaitingStatus(gui.Tr.PullProject, func() error {
cmdStr := utils.ApplyTemplate(
gui.Config.UserConfig.CommandTemplates.Pull,
gui.DockerCommand.NewCommandObject(commands.CommandObject{Project: project}),
)
if err := gui.OSCommand.RunCommand(cmdStr); err != nil {
return gui.createErrorPanel(err.Error())
}
return nil
})
}
func (gui *Gui) handleProjectDown(g *gocui.Gui, v *gocui.View) error {
project, _ := gui.Panels.Projects.GetSelectedItem()
if project != nil && project.Name != gui.DockerCommand.LocalProjectName {

View file

@ -60,6 +60,7 @@ func chineseSet() TranslationSet {
ViewLogs: "查看日志",
UpProject: "创建并启动容器",
DownProject: "停止并移除容器",
PullProject: "拉取项目",
RemoveImage: "移除镜像",
RemoveVolume: "移除卷",
RemoveNetwork: "移除网络",

View file

@ -43,6 +43,7 @@ func dutchSet() TranslationSet {
NextContext: "volgende tab",
Attach: "verbinden",
ViewLogs: "bekijk logs",
PullProject: "project ophalen",
RemoveImage: "verwijder image",
RemoveVolume: "verwijder volume",
RemoveNetwork: "verwijder network",

View file

@ -81,6 +81,9 @@ type TranslationSet struct {
NoNetworks string
NoServices string
RemoveImage string
Pull string
PullImage string
PullProject string
RemoveVolume string
RemoveNetwork string
RemoveWithoutPrune string
@ -199,6 +202,9 @@ func englishSet() TranslationSet {
UpProject: "up project",
DownProject: "down project",
RemoveImage: "remove image",
Pull: "pull",
PullImage: "pull image",
PullProject: "pull project",
RemoveVolume: "remove volume",
RemoveNetwork: "remove network",
RemoveWithoutPrune: "remove without deleting untagged parents",

View file

@ -51,6 +51,7 @@ func frenchSet() TranslationSet {
NextContext: "onglet suivant",
Attach: "attacher",
ViewLogs: "voir les enregistrements",
PullProject: "tirer le projet",
RemoveImage: "supprimer l'image",
RemoveVolume: "supprimer le volume",
RemoveNetwork: "supprimer le réseau",

View file

@ -42,6 +42,7 @@ func germanSet() TranslationSet {
NextContext: "nächstes Tab",
Attach: "anbinden",
ViewLogs: "zeige Protokolle",
PullProject: "Projekt pullen",
RemoveImage: "entferne Image",
RemoveVolume: "entferne Volume",
RemoveNetwork: "entferne Netzwerk",

View file

@ -42,6 +42,7 @@ func polishSet() TranslationSet {
NextContext: "następna zakładka",
Attach: "przyczep",
ViewLogs: "pokaż logi",
PullProject: "pobierz projekt",
RemoveImage: "usuń obraz",
RemoveVolume: "usuń wolumen",
RemoveNetwork: "usuń sieci",

View file

@ -60,6 +60,7 @@ func portugueseSet() TranslationSet {
ViewLogs: "ver logs",
UpProject: "subir projeto",
DownProject: "derrubar projeto",
PullProject: "puxar projeto",
RemoveImage: "remover imagem",
RemoveVolume: "remover volume",
RemoveNetwork: "remover rede",

View file

@ -55,6 +55,7 @@ func spanishSet() TranslationSet {
ViewLogs: "ver logs",
UpProject: "levantar proyecto",
DownProject: "dar de baja el proyecto",
PullProject: "jalar el proyecto",
RemoveImage: "limpiar imagen",
RemoveVolume: "limpiar volúmen",
RemoveNetwork: "limpiar red",

View file

@ -42,6 +42,7 @@ func turkishSet() TranslationSet {
NextContext: "sonraki sekme",
Attach: "bağlan/iliştir",
ViewLogs: "kayıt defterini görüntüle",
PullProject: "projeyi çek",
RemoveImage: "imajı kaldır",
RemoveVolume: "alanı kaldır",
RemoveNetwork: "ağı kaldır",