From aeb19e9308666b195b6c0bc92538d7d1f76260b4 Mon Sep 17 00:00:00 2001 From: Alesc0 Date: Sat, 25 Apr 2026 23:25:28 +0100 Subject: [PATCH] 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. --- docs/keybindings/Keybindings_de.md | 2 ++ docs/keybindings/Keybindings_en.md | 2 ++ docs/keybindings/Keybindings_es.md | 2 ++ docs/keybindings/Keybindings_fr.md | 2 ++ docs/keybindings/Keybindings_nl.md | 2 ++ docs/keybindings/Keybindings_pl.md | 2 ++ docs/keybindings/Keybindings_pt.md | 2 ++ docs/keybindings/Keybindings_tr.md | 2 ++ docs/keybindings/Keybindings_zh.md | 2 ++ pkg/commands/image.go | 8 ++++++++ pkg/config/app_config.go | 4 ++++ pkg/gui/images_panel.go | 20 ++++++++++++++++++++ pkg/gui/keybindings.go | 14 ++++++++++++++ pkg/gui/services_panel.go | 18 ++++++++++++++++++ pkg/i18n/chinese.go | 1 + pkg/i18n/dutch.go | 1 + pkg/i18n/english.go | 6 ++++++ pkg/i18n/french.go | 1 + pkg/i18n/german.go | 1 + pkg/i18n/polish.go | 1 + pkg/i18n/portuguese.go | 1 + pkg/i18n/spanish.go | 1 + pkg/i18n/turkish.go | 1 + 23 files changed, 96 insertions(+) diff --git a/docs/keybindings/Keybindings_de.md b/docs/keybindings/Keybindings_de.md index dc9dd08e8..7ad41048b 100644 --- a/docs/keybindings/Keybindings_de.md +++ b/docs/keybindings/Keybindings_de.md @@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct b: view bulk commands E: exec shell w: open in browser (first port is http) + P: Projekt pullen enter: fokussieren aufs Hauptpanel [: vorheriges Tab ]: nächstes Tab @@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct c: führe vordefinierten benutzerdefinierten Befehl aus d: entferne Image b: view bulk commands + p: pull image enter: fokussieren aufs Hauptpanel [: vorheriges Tab ]: nächstes Tab diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md index ae21c4dcd..bf7af69e4 100644 --- a/docs/keybindings/Keybindings_en.md +++ b/docs/keybindings/Keybindings_en.md @@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct b: view bulk commands E: exec shell w: open in browser (first port is http) + P: pull project enter: focus main panel [: previous tab ]: next tab @@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct c: run predefined custom command d: remove image b: view bulk commands + p: pull image enter: focus main panel [: previous tab ]: next tab diff --git a/docs/keybindings/Keybindings_es.md b/docs/keybindings/Keybindings_es.md index 6b4eb9210..ccbbb36e3 100644 --- a/docs/keybindings/Keybindings_es.md +++ b/docs/keybindings/Keybindings_es.md @@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct b: ver comandos masivos E: ejecutar shell w: abrir en navegador (first port is http) + P: jalar el proyecto enter: enfocar panel principal [: anterior pestaña ]: siguiente pestaña @@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct c: ejecutar comando personalizado d: limpiar imagen b: ver comandos masivos + p: pull image enter: enfocar panel principal [: anterior pestaña ]: siguiente pestaña diff --git a/docs/keybindings/Keybindings_fr.md b/docs/keybindings/Keybindings_fr.md index 109078b23..ca11a431b 100644 --- a/docs/keybindings/Keybindings_fr.md +++ b/docs/keybindings/Keybindings_fr.md @@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct b: voir les commandes groupées E: exécuter le shell w: ouvrir dans le navigateur (le premier port est http) + P: tirer le projet enter: focus panneau principal [: onglet précédent ]: onglet suivant @@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct c: exécuter une commande prédéfinie d: supprimer l'image b: voir les commandes groupées + p: pull image enter: focus panneau principal [: onglet précédent ]: onglet suivant diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md index 24477006a..16ad86040 100644 --- a/docs/keybindings/Keybindings_nl.md +++ b/docs/keybindings/Keybindings_nl.md @@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct b: view bulk commands E: exec shell w: open in browser (first port is http) + P: project ophalen enter: focus hoofdpaneel [: vorige tab ]: volgende tab @@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct c: draai een vooraf bedacht aangepaste opdracht d: verwijder image b: view bulk commands + p: pull image enter: focus hoofdpaneel [: vorige tab ]: volgende tab diff --git a/docs/keybindings/Keybindings_pl.md b/docs/keybindings/Keybindings_pl.md index 2f4cb93f9..7966f2b96 100644 --- a/docs/keybindings/Keybindings_pl.md +++ b/docs/keybindings/Keybindings_pl.md @@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct b: view bulk commands E: exec shell w: open in browser (first port is http) + P: pobierz projekt enter: skup na głównym panelu [: poprzednia zakładka ]: następna zakładka @@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct c: wykonaj predefiniowaną własną komende d: usuń obraz b: view bulk commands + p: pull image enter: skup na głównym panelu [: poprzednia zakładka ]: następna zakładka diff --git a/docs/keybindings/Keybindings_pt.md b/docs/keybindings/Keybindings_pt.md index 32a557b53..ef669dc09 100644 --- a/docs/keybindings/Keybindings_pt.md +++ b/docs/keybindings/Keybindings_pt.md @@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct b: ver comandos em massa E: executar shell w: abrir no navegador (primeira porta é http) + P: puxar projeto enter: focar no painel principal [: aba anterior ]: próxima aba @@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct c: executar comando personalizado predefinido d: remover imagem b: ver comandos em massa + p: pull image enter: focar no painel principal [: aba anterior ]: próxima aba diff --git a/docs/keybindings/Keybindings_tr.md b/docs/keybindings/Keybindings_tr.md index 3192a7c20..0596bf2aa 100644 --- a/docs/keybindings/Keybindings_tr.md +++ b/docs/keybindings/Keybindings_tr.md @@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct b: view bulk commands E: exec shell w: open in browser (first port is http) + P: projeyi çek enter: ana panele odaklan [: önceki sekme ]: sonraki sekme @@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct c: önceden tanımlanmış özel komutu çalıştır d: imajı kaldır b: view bulk commands + p: pull image enter: ana panele odaklan [: önceki sekme ]: sonraki sekme diff --git a/docs/keybindings/Keybindings_zh.md b/docs/keybindings/Keybindings_zh.md index 0c75fbcb9..c7c071bff 100644 --- a/docs/keybindings/Keybindings_zh.md +++ b/docs/keybindings/Keybindings_zh.md @@ -52,6 +52,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct b: 查看批量命令 E: 执行shell w: 在浏览器中打开(第一个端口为http) + P: 拉取项目 enter: 聚焦主面板 [: 上一个选项卡 ]: 下一个选项卡 @@ -64,6 +65,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct c: 运行预定义的自定义命令 d: 移除镜像 b: 查看批量命令 + p: pull image enter: 聚焦主面板 [: 上一个选项卡 ]: 下一个选项卡 diff --git a/pkg/commands/image.go b/pkg/commands/image.go index 789733d0e..73fd580f1 100644 --- a/pkg/commands/image.go +++ b/pkg/commands/image.go @@ -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 { diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index 0ebc17969..0190bd4f7 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -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 }}", diff --git a/pkg/gui/images_panel.go b/pkg/gui/images_panel.go index 7b0d56437..45cdbd5f6 100644 --- a/pkg/gui/images_panel.go +++ b/pkg/gui/images_panel.go @@ -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 { diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index df7060241..7f005820f 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -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() { diff --git a/pkg/gui/services_panel.go b/pkg/gui/services_panel.go index edc894e9e..51ed7e322 100644 --- a/pkg/gui/services_panel.go +++ b/pkg/gui/services_panel.go @@ -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 { diff --git a/pkg/i18n/chinese.go b/pkg/i18n/chinese.go index aa125f0b4..036e030c1 100644 --- a/pkg/i18n/chinese.go +++ b/pkg/i18n/chinese.go @@ -60,6 +60,7 @@ func chineseSet() TranslationSet { ViewLogs: "查看日志", UpProject: "创建并启动容器", DownProject: "停止并移除容器", + PullProject: "拉取项目", RemoveImage: "移除镜像", RemoveVolume: "移除卷", RemoveNetwork: "移除网络", diff --git a/pkg/i18n/dutch.go b/pkg/i18n/dutch.go index 8a8601c23..aa4f77eaf 100644 --- a/pkg/i18n/dutch.go +++ b/pkg/i18n/dutch.go @@ -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", diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index d86b0c84f..a2aa9cc30 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -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", diff --git a/pkg/i18n/french.go b/pkg/i18n/french.go index 29ab5be27..bf72d7db5 100644 --- a/pkg/i18n/french.go +++ b/pkg/i18n/french.go @@ -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", diff --git a/pkg/i18n/german.go b/pkg/i18n/german.go index ac23d6b19..9bc37c928 100644 --- a/pkg/i18n/german.go +++ b/pkg/i18n/german.go @@ -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", diff --git a/pkg/i18n/polish.go b/pkg/i18n/polish.go index 1025bf47c..449e9c45e 100644 --- a/pkg/i18n/polish.go +++ b/pkg/i18n/polish.go @@ -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", diff --git a/pkg/i18n/portuguese.go b/pkg/i18n/portuguese.go index 36d9bcfdb..98b810153 100644 --- a/pkg/i18n/portuguese.go +++ b/pkg/i18n/portuguese.go @@ -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", diff --git a/pkg/i18n/spanish.go b/pkg/i18n/spanish.go index b9148c3ae..8645d7fc2 100644 --- a/pkg/i18n/spanish.go +++ b/pkg/i18n/spanish.go @@ -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", diff --git a/pkg/i18n/turkish.go b/pkg/i18n/turkish.go index fccb3d911..9f243efd7 100644 --- a/pkg/i18n/turkish.go +++ b/pkg/i18n/turkish.go @@ -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",