WIP: feat: translation support
Some checks failed
continuous-integration/drone/push Build is failing

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

View File

@ -1,6 +1,7 @@
package app
import (
"errors"
"fmt"
"coopcloud.tech/abra/cli/internal"
@ -10,6 +11,7 @@ import (
"coopcloud.tech/abra/pkg/client"
"coopcloud.tech/abra/pkg/config"
"coopcloud.tech/abra/pkg/formatter"
"coopcloud.tech/abra/pkg/i18n"
"coopcloud.tech/abra/pkg/log"
recipePkg "coopcloud.tech/abra/pkg/recipe"
"coopcloud.tech/abra/pkg/secret"
@ -19,7 +21,7 @@ import (
"github.com/spf13/cobra"
)
var appNewDescription = `Creates a new app from a default recipe.
var appNewDescription = i18n.G(`Creates a new app from a default recipe.
This new app configuration is stored in your $ABRA_DIR directory under the
appropriate server.
@ -39,12 +41,12 @@ store them somewhere safe.
You can use the "--pass/-P" to store these generated passwords locally in a
pass store (see passwordstore.org for more). The pass command must be available
on your $PATH.`
on your $PATH.`)
var AppNewCommand = &cobra.Command{
Use: "new [recipe] [version] [flags]",
Aliases: []string{"n"},
Short: "Create a new app",
Use: i18n.G("new [recipe] [version] [flags]"),
Aliases: []string{i18n.G("n")},
Short: i18n.G("Create a new app"),
Long: appNewDescription,
Args: cobra.RangeArgs(0, 2),
ValidArgsFunction: func(
@ -65,7 +67,7 @@ var AppNewCommand = &cobra.Command{
recipe := internal.ValidateRecipe(args, cmd.Name())
if len(args) == 2 && internal.Chaos {
log.Fatal("cannot use [version] and --chaos together")
log.Fatal(i18n.G("cannot use [version] and --chaos together"))
}
var recipeVersion string
@ -113,7 +115,7 @@ var AppNewCommand = &cobra.Command{
if recipeVersion == "" {
head, err := recipe.Head()
if err != nil {
log.Fatalf("failed to retrieve latest commit for %s: %s", recipe.Name, err)
log.Fatal(i18n.G("failed to retrieve latest commit for %s: %s", recipe.Name, err))
}
recipeVersion = formatter.SmallSHA(head.String())
@ -130,7 +132,7 @@ var AppNewCommand = &cobra.Command{
}
sanitisedAppName := appPkg.SanitiseAppName(appDomain)
log.Debugf("%s sanitised as %s for new app", appDomain, sanitisedAppName)
log.Debug(i18n.G("%s sanitised as %s for new app", appDomain, sanitisedAppName))
if err := appPkg.TemplateAppEnvSample(
recipe,
@ -182,7 +184,7 @@ var AppNewCommand = &cobra.Command{
log.Fatal(err)
}
headers := []string{"NAME", "VALUE"}
headers := []string{i18n.G("NAME"), i18n.G("VALUE")}
secretsTable.Headers(headers...)
for name, val := range appSecrets {
@ -194,7 +196,7 @@ var AppNewCommand = &cobra.Command{
newAppServer = "local"
}
log.Infof("%s created (version: %s)", appDomain, recipeVersion)
log.Info(i18n.G("%s created (version: %s)", appDomain, recipeVersion))
if len(appSecrets) > 0 {
rows := [][]string{}
@ -202,15 +204,15 @@ var AppNewCommand = &cobra.Command{
rows = append(rows, []string{k, v})
}
overview := formatter.CreateOverview("SECRETS OVERVIEW", rows)
overview := formatter.CreateOverview(i18n.G("SECRETS OVERVIEW"), rows)
fmt.Println(overview)
log.Warnf(
log.Warn(i18n.G(
"secrets are %s shown again, please save them %s",
formatter.BoldUnderlineStyle.Render("NOT"),
formatter.BoldUnderlineStyle.Render("NOW"),
)
))
}
app, err := app.Get(appDomain)
@ -219,7 +221,7 @@ var AppNewCommand = &cobra.Command{
}
if err := app.WriteRecipeVersion(recipeVersion, false); err != nil {
log.Fatalf("writing recipe version failed: %s", err)
log.Fatal(i18n.G("writing recipe version failed: %s", err))
}
},
}
@ -231,7 +233,7 @@ type AppSecrets map[string]string
func createSecrets(cl *dockerClient.Client, secretsConfig map[string]secret.Secret, sanitisedAppName string) (AppSecrets, error) {
// NOTE(d1): trim to match app.StackName() implementation
if len(sanitisedAppName) > config.MAX_SANITISED_APP_NAME_LENGTH {
log.Debugf("trimming %s to %s to avoid runtime limits", sanitisedAppName, sanitisedAppName[:config.MAX_SANITISED_APP_NAME_LENGTH])
log.Debug(i18n.G("trimming %s to %s to avoid runtime limits", sanitisedAppName, sanitisedAppName[:config.MAX_SANITISED_APP_NAME_LENGTH]))
sanitisedAppName = sanitisedAppName[:config.MAX_SANITISED_APP_NAME_LENGTH]
}
@ -261,7 +263,7 @@ func createSecrets(cl *dockerClient.Client, secretsConfig map[string]secret.Secr
func ensureDomainFlag(recipe recipePkg.Recipe, server string) error {
if appDomain == "" && !internal.NoInput {
prompt := &survey.Input{
Message: "Specify app domain",
Message: i18n.G("Specify app domain"),
Default: fmt.Sprintf("%s.%s", recipe.Name, server),
}
if err := survey.AskOne(prompt, &appDomain); err != nil {
@ -270,7 +272,7 @@ func ensureDomainFlag(recipe recipePkg.Recipe, server string) error {
}
if appDomain == "" {
return fmt.Errorf("no domain provided")
return fmt.Errorf(i18n.G("no domain provided"))
}
return nil
@ -279,13 +281,13 @@ func ensureDomainFlag(recipe recipePkg.Recipe, server string) error {
// promptForSecrets asks if we should generate secrets for a new app.
func promptForSecrets(recipeName string, secretsConfig map[string]secret.Secret) error {
if len(secretsConfig) == 0 {
log.Debugf("%s has no secrets to generate, skipping...", recipeName)
log.Debug(i18n.G("%s has no secrets to generate, skipping...", recipeName))
return nil
}
if !generateSecrets && !internal.NoInput {
prompt := &survey.Confirm{
Message: "Generate app secrets?",
Message: i18n.G("Generate app secrets?"),
}
if err := survey.AskOne(prompt, &generateSecrets); err != nil {
return err
@ -304,13 +306,13 @@ func ensureServerFlag() error {
if len(servers) == 1 {
newAppServer = servers[0]
log.Infof("single server detected, choosing %s automatically", newAppServer)
log.Info(i18n.G("single server detected, choosing %s automatically", newAppServer))
return nil
}
if newAppServer == "" && !internal.NoInput {
prompt := &survey.Select{
Message: "Select app server:",
Message: i18n.G("Select app server:"),
Options: servers,
}
if err := survey.AskOne(prompt, &newAppServer); err != nil {
@ -319,7 +321,7 @@ func ensureServerFlag() error {
}
if newAppServer == "" {
return fmt.Errorf("no server provided")
return errors.New(i18n.G("no server provided"))
}
return nil
@ -335,14 +337,14 @@ var (
func init() {
AppNewCommand.Flags().StringVarP(
&newAppServer,
"server",
"s",
i18n.G("server"),
i18n.G("s"),
"",
"specify server for new app",
i18n.G("specify server for new app"),
)
AppNewCommand.RegisterFlagCompletionFunc(
"server",
i18n.G("server"),
func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return autocomplete.ServerNameComplete()
},
@ -350,34 +352,34 @@ func init() {
AppNewCommand.Flags().StringVarP(
&appDomain,
"domain",
"D",
i18n.G("domain"),
i18n.G("D"),
"",
"domain name for app",
i18n.G("domain name for app"),
)
AppNewCommand.Flags().BoolVarP(
&saveInPass,
"pass",
"p",
i18n.G("pass"),
i18n.G("p"),
false,
"store secrets in a local pass store",
i18n.G("store secrets in a local pass store"),
)
AppNewCommand.Flags().BoolVarP(
&generateSecrets,
"secrets",
"S",
i18n.G("secrets"),
i18n.G("S"),
false,
"automatically generate secrets",
i18n.G("automatically generate secrets"),
)
AppNewCommand.Flags().BoolVarP(
&internal.Chaos,
"chaos",
"C",
i18n.G("chaos"),
i18n.G("C"),
false,
"ignore uncommitted recipes changes",
i18n.G("ignore uncommitted recipes changes"),
)
}