feat: translation support
All checks were successful
continuous-integration/drone/push Build is passing

See #483
This commit is contained in:
2025-08-19 11:22:52 +02:00
parent 5cf6048ecb
commit 4e205cf13e
108 changed files with 11217 additions and 1645 deletions

View File

@ -5,13 +5,14 @@ import (
"fmt"
"os/exec"
"coopcloud.tech/abra/pkg/i18n"
"coopcloud.tech/abra/pkg/log"
)
// PassInsertSecret inserts a secret into a pass store.
func PassInsertSecret(secretValue, secretName, appName, server string) error {
if _, err := exec.LookPath("pass"); err != nil {
return errors.New("pass command not found on $PATH, is it installed?")
return errors.New(i18n.G("pass command not found on $PATH, is it installed?"))
}
cmd := fmt.Sprintf(
@ -19,13 +20,13 @@ func PassInsertSecret(secretValue, secretName, appName, server string) error {
secretValue, server, appName, secretName,
)
log.Debugf("attempting to run %s", cmd)
log.Debug(i18n.G("attempting to run %s", cmd))
if err := exec.Command("bash", "-c", cmd).Run(); err != nil {
return err
}
log.Infof("%s inserted into pass store", secretName)
log.Info(i18n.G("%s inserted into pass store", secretName))
return nil
}
@ -33,7 +34,7 @@ func PassInsertSecret(secretValue, secretName, appName, server string) error {
// PassRmSecret deletes a secret from a pass store.
func PassRmSecret(secretName, appName, server string) error {
if _, err := exec.LookPath("pass"); err != nil {
return errors.New("pass command not found on $PATH, is it installed?")
return errors.New(i18n.G("pass command not found on $PATH, is it installed?"))
}
cmd := fmt.Sprintf(
@ -41,13 +42,13 @@ func PassRmSecret(secretName, appName, server string) error {
server, appName, secretName,
)
log.Debugf("attempting to run %s", cmd)
log.Debug(i18n.G("attempting to run %s", cmd))
if err := exec.Command("bash", "-c", cmd).Run(); err != nil {
return err
}
log.Infof("%s removed from pass store", secretName)
log.Info(i18n.G("%s removed from pass store", secretName))
return nil
}

View File

@ -5,6 +5,7 @@ package secret
import (
"context"
"errors"
"fmt"
"slices"
"strconv"
@ -15,6 +16,7 @@ import (
"coopcloud.tech/abra/pkg/client"
"coopcloud.tech/abra/pkg/config"
"coopcloud.tech/abra/pkg/envfile"
"coopcloud.tech/abra/pkg/i18n"
"coopcloud.tech/abra/pkg/log"
"coopcloud.tech/abra/pkg/upstream/stack"
loader "coopcloud.tech/abra/pkg/upstream/stack"
@ -57,7 +59,7 @@ func GeneratePassword(length uint, charset string) (string, error) {
return "", err
}
log.Debugf("generated %s", strings.Join(passwords, ", "))
log.Debug(i18n.G("generated %s", strings.Join(passwords, ", ")))
return passwords[0], nil
}
@ -75,7 +77,7 @@ func GeneratePassphrase() (string, error) {
return "", err
}
log.Debugf("generated %s", strings.Join(passphrases, ", "))
log.Debug(i18n.G("generated %s", strings.Join(passphrases, ", ")))
return passphrases[0], nil
}
@ -114,18 +116,18 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin
}
if len(enabledSecrets) == 0 {
log.Debugf("not generating app secrets, none enabled in recipe config")
log.Debug(i18n.G("not generating app secrets, none enabled in recipe config"))
return nil, nil
}
secretValues := map[string]Secret{}
for secretId, secretConfig := range composeConfig.Secrets {
if string(secretConfig.Name[len(secretConfig.Name)-1]) == "_" {
return nil, fmt.Errorf("missing version for secret? (%s)", secretId)
return nil, errors.New(i18n.G("missing version for secret? (%s)", secretId))
}
if !(slices.Contains(enabledSecrets, secretId)) {
log.Warnf("%s not enabled in recipe config, skipping", secretId)
log.Warnf(i18n.G("%s not enabled in recipe config, skipping", secretId))
continue
}
@ -134,7 +136,7 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin
value := Secret{Version: secretVersion, RemoteName: secretConfig.Name}
if len(value.RemoteName) > config.MAX_DOCKER_SECRET_LENGTH {
return nil, fmt.Errorf("secret %s is > %d chars when combined with %s", secretId, config.MAX_DOCKER_SECRET_LENGTH, stackName)
return nil, errors.New(i18n.G("secret %s is > %d chars when combined with %s", secretId, config.MAX_DOCKER_SECRET_LENGTH, stackName))
}
// Check if the length modifier is set for this secret.
@ -202,12 +204,12 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server
defer wg.Done()
if secret.SkipGenerate {
log.Debugf("skipping generation of %s (generate=false)", secretName)
log.Debug(i18n.G("skipping generation of %s (generate=false)", secretName))
ch <- nil
return
}
log.Debugf("attempting to generate and store %s on %s", secret.RemoteName, server)
log.Debug(i18n.G("attempting to generate and store %s on %s", secret.RemoteName, server))
if secret.Length > 0 {
password, err := GeneratePassword(uint(secret.Length), secret.Charset)
@ -218,7 +220,7 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server
if err := client.StoreSecret(cl, secret.RemoteName, password, server); err != nil {
if strings.Contains(err.Error(), "AlreadyExists") {
log.Warnf("%s already exists", secret.RemoteName)
log.Warnf(i18n.G("%s already exists", secret.RemoteName))
ch <- nil
} else {
ch <- err
@ -238,7 +240,7 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server
if err := client.StoreSecret(cl, secret.RemoteName, passphrase, server); err != nil {
if strings.Contains(err.Error(), "AlreadyExists") {
log.Warnf("%s already exists", secret.RemoteName)
log.Warnf(i18n.G("%s already exists", secret.RemoteName))
ch <- nil
} else {
ch <- err
@ -263,7 +265,7 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server
}
}
log.Debugf("generated and stored %v on %s", secrets, server)
log.Debug(i18n.G("generated and stored %v on %s", secrets, server))
return secretsGenerated, nil
}