Skip to content

Conversation

@sreehari-ss
Copy link
Contributor

@sreehari-ss sreehari-ss commented Dec 3, 2025

Summary by CodeRabbit

  • New Features

    • CLI: Added a "translation" subcommand with list/pull/push actions, interactive directory prompts/flags, progress spinner, and per-locale success/failure summaries.
    • Workflow: Translation pull/push automatically integrated into category sync, commit, and push flows.
  • New APIs

    • Management client: endpoints to list locales, fetch locale translations, and push locale translations.
  • Chores

    • .gitignore: Ignore Go debugger binaries (__debug_bin*).

✏️ Tip: You can customize this high-level summary in your review settings.

- Introduced new commands for managing preference category translations: `list`, `pull`, and `push`.
- Implemented helper functions for prompting output directories and ensuring directory existence.
- Added a command structure for handling translations, including the ability to list available locales and manage translation files.
- Updated the `.gitignore` to exclude debug binaries.
- Created necessary management functions for fetching and pushing translations to the workspace.
- Updated the default output directory for translation commands to use a shared variable, improving consistency across the `pull` and `push` commands.
- Simplified the logic for determining the translations directory in the `push` command.
- Removed unused flag for specifying a file path in the `push` command, clarifying the command's usage.
…to streamline preference translation handling.
- Updated variable usage in promptForOutputDirectory function to improve clarity and maintainability.
- Ensured consistent reference to the default directory variable for user prompts.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 3, 2025

Walkthrough

Adds a new translation CLI subcommand with list/pull/push actions and helpers, a management client for preference translations, integrates translation steps into category sync/commit/pull/push flows, and updates .gitignore to ignore Go debugger binaries.

Changes

Cohort / File(s) Summary
Configuration
/.gitignore
Added ignore pattern for Go debugger binaries (__debug_bin*).
CLI registration
internal/commands/category/category.go
Registers the translation subcommand by adding translation.TranslationCmd to CategoryCmd.
Translation scaffold & helpers
internal/commands/category/translation/translation.go, internal/commands/category/translation/helpers.go
Adds TranslationCmd base command and unexported helpers promptForOutputDirectory / ensureOutputDirectory with defaultDir = suprsend/category/translation.
Translation subcommands (list/pull/push)
internal/commands/category/translation/translation_list.go, internal/commands/category/translation/translation_pull.go, internal/commands/category/translation/translation_push.go
Implements list (calls mgmnt API to list locales), pull (resolve/create output dir, fetch per-locale translations, write JSON files, aggregate errors), and push (read local JSON files, parse to DTOs, push to workspace; skips en.json, supports locale filter) with flags and summaries.
Management API
mgmnt/preference_translation.go
New DTOs (PreferenceTranslation, PreferenceTranslationContent, ListPreferenceTranslation) and SS_MgmntClient methods: ListPreferenceTranslations, GetPreferenceTranslationsForLocale, PushPreferenceTranslation — HTTP calls with auth header, error parsing, and logging.
Category integration
internal/commands/sync.go, internal/commands/category/category_commit.go, internal/commands/category/category_pull.go, internal/commands/category/category_push.go
Integrates translation push/pull steps into category sync/commit/pull/push flows; adds dir flag handling and computes translation subdirectory for operations.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI as Translation CLI
    participant MgmtAPI as Management API
    participant FS as File System

    rect rgba(200,220,240,0.6)
    Note over CLI,MgmtAPI: List / Pull flow
    User->>CLI: translation list --workspace W
    CLI->>MgmtAPI: ListPreferenceTranslations(W)
    MgmtAPI-->>CLI: locales[]
    User->>CLI: translation pull --workspace W --dir ./dir
    CLI->>CLI: prompt/ensure output directory
    loop for each locale in locales
        CLI->>MgmtAPI: GetPreferenceTranslationsForLocale(W, locale)
        MgmtAPI-->>CLI: translation content
        CLI->>FS: write ./dir/{locale}.json
        FS-->>CLI: success/error
    end
    CLI-->>User: summary (success/fail)
    end

    rect rgba(240,220,200,0.6)
    Note over CLI,FS: Push flow
    User->>CLI: translation push --workspace W --dir ./dir [--locale L]
    CLI->>FS: list ./dir/*.json (filter)
    FS-->>CLI: files[]
    loop for each file in files (skip en.json)
        CLI->>CLI: parse file -> content
        CLI->>MgmtAPI: PushPreferenceTranslation(W, locale, content)
        alt success
            MgmtAPI-->>CLI: OK
        else failure
            MgmtAPI-->>CLI: error
        end
    end
    CLI-->>User: summary (success/fail & errors)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus areas:
    • mgmnt/preference_translation.go: URL construction, HTTP client usage, Authorization header handling, error parsing and logging.
    • internal/commands/category/translation/*: spinner lifecycle, file I/O, JSON (de)serialization, per-locale error aggregation, CLI flag wiring.
    • Integration edits in sync.go, category_commit.go, category_pull.go, category_push.go: ordering of side effects, flag propagation, and default directory computation.

Possibly related PRs

  • feat: pref categories. #22 — Introduced CategoryCmd and is directly related to registering the new translation subcommand.
  • fix: bugs #23 — Modifies category command package and may overlap with category integration changes.

Suggested reviewers

  • zokhcat
  • gauravverma

Poem

🐰 I hopped through folders, small and spry,
added commands so locales can fly.
JSONs tucked in neat little nests,
push and pull — translation quests.
A carrot for tests, and a joyful hop 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title "Preferences tr" is vague and incomplete, failing to clearly describe the changeset which introduces preference translation management functionality. Use a more descriptive title like "Add preference translation management commands" that clearly conveys the main feature being introduced.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch preferences-tr

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
internal/commands/category/category_translation/translation_push.go (1)

62-67: Filter en.json earlier to avoid adding it to localeFiles only to skip it later.

en.json is added to localeFiles at line 66, then skipped at lines 95-97. Filtering it here avoids the inconsistency.

 				if fileLocale == "categories_preferences" {
 					continue
 				}
+				// Skip English translations
+				if fileLocale == "en" {
+					continue
+				}
 				localeFiles = append(localeFiles, name)

Then remove lines 95-97.

internal/commands/category/category_translation/translation_pull.go (1)

33-36: Unreachable code: promptForOutputDirectory() always returns a non-empty value.

The helper function returns dd (defaultDir) when input is empty, so outputDir can never be empty here. This check is defensive but dead code.

Consider removing this check or adding a comment explaining it's defensive:

-			if outputDir == "" {
-				fmt.Fprintf(os.Stdout, "No output directory specified. Exiting.\n")
-				return
-			}
mgmnt/preference_translation.go (1)

31-31: Consider URL-encoding the workspace parameter.

If workspace contains special characters (spaces, slashes, etc.), the URL could be malformed. This also applies to the locale parameter in other methods.

+import "net/url"
+
 func (c *SS_MgmntClient) ListPreferenceTranslations(workspace string) (*ListPreferenceTranslation, error) {
 	client := client.NewHTTPClient()
 	defer client.Close()

-	url := fmt.Sprintf("%sv1/%s/preference_category/translation/locale", c.mgmnt_base_URL, workspace)
+	url := fmt.Sprintf("%sv1/%s/preference_category/translation/locale", c.mgmnt_base_URL, url.PathEscape(workspace))

Apply similar escaping in GetPreferenceTranslationsForLocale and PushPreferenceTranslation for both workspace and locale.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 08b0847 and 924dfc4.

📒 Files selected for processing (8)
  • .gitignore (1 hunks)
  • internal/commands/category/category.go (2 hunks)
  • internal/commands/category/category_translation/helpers.go (1 hunks)
  • internal/commands/category/category_translation/translation.go (1 hunks)
  • internal/commands/category/category_translation/translation_list.go (1 hunks)
  • internal/commands/category/category_translation/translation_pull.go (1 hunks)
  • internal/commands/category/category_translation/translation_push.go (1 hunks)
  • mgmnt/preference_translation.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/category/category_translation/translation.go
  • internal/commands/category/category_translation/helpers.go
  • internal/commands/category/category.go
  • internal/commands/category/category_translation/translation_list.go
  • internal/commands/category/category_translation/translation_push.go
  • internal/commands/category/category_translation/translation_pull.go
mgmnt/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/cli-structure.mdc)

Place management and client-related Go code under the mgmnt/ directory

Files:

  • mgmnt/preference_translation.go
🧠 Learnings (3)
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/

Applied to files:

  • internal/commands/category/category_translation/translation.go
  • internal/commands/category/category.go
  • internal/commands/category/category_translation/translation_list.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to internal/commands/**/!(root).go : Register each subcommand by calling `rootCmd.AddCommand(...)` in the subcommand’s own `init()` function

Applied to files:

  • internal/commands/category/category.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to mgmnt/**/*.go : Place management and client-related Go code under the mgmnt/ directory

Applied to files:

  • mgmnt/preference_translation.go
🧬 Code graph analysis (3)
internal/commands/category/category.go (1)
internal/commands/category/category_translation/translation.go (1)
  • TranslationCmd (7-14)
internal/commands/category/category_translation/translation_list.go (3)
internal/utils/outpututil.go (2)
  • IsOutputPiped (25-38)
  • OutputData (55-65)
internal/utils/sdk_instance.go (1)
  • GetSuprSendMgmntClient (23-25)
internal/commands/category/category_translation/translation.go (1)
  • TranslationCmd (7-14)
internal/commands/category/category_translation/translation_pull.go (3)
internal/utils/outpututil.go (1)
  • IsOutputPiped (25-38)
internal/utils/sdk_instance.go (1)
  • GetSuprSendMgmntClient (23-25)
internal/commands/category/category_translation/translation.go (1)
  • TranslationCmd (7-14)
🔇 Additional comments (9)
.gitignore (1)

14-15: LGTM!

Good addition to ignore Go debugger binaries. This prevents accidental commits of debug artifacts generated by tools like Delve.

internal/commands/category/category_translation/helpers.go (1)

27-32: LGTM!

Proper error wrapping and appropriate permissions (0755) for the output directory.

internal/commands/category/category_translation/translation.go (1)

7-14: LGTM!

The TranslationCmd is correctly structured as a parent command with help displayed when no subcommand is provided. The subcommands (list, pull, push) properly register themselves via their own init() functions, following the project conventions from learnings.

internal/commands/category/category.go (1)

14-17: LGTM!

The TranslationCmd is correctly registered as a subcommand of CategoryCmd in the init() function. This follows the project's command registration pattern. Based on learnings, subcommands should be registered via init() functions.

internal/commands/category/category_translation/translation_list.go (1)

13-45: LGTM!

The list command is well-structured with:

  • Proper spinner UX for interactive mode
  • Appropriate error handling and logging
  • Good scripting support (empty array output when piped with no results)
  • Correct subcommand registration via init()
internal/commands/category/category_translation/translation_push.go (1)

150-154: LGTM!

Flags are well-defined with appropriate defaults and descriptions. The command is correctly registered with TranslationCmd in init().

internal/commands/category/category_translation/translation_pull.go (1)

64-90: LGTM!

The locale iteration logic is well-structured with proper error handling, JSON marshaling with indentation, and comprehensive error tracking for the summary.

mgmnt/preference_translation.go (2)

11-25: LGTM!

Well-structured type definitions with appropriate JSON tags. The nested anonymous struct in ListPreferenceTranslation is acceptable for this simple response structure.


83-105: LGTM!

The PushPreferenceTranslation method correctly sets Content-Type: application/json for the POST request and follows the same error handling pattern as the other methods. As per coding guidelines, management-related code is properly placed under the mgmnt/ directory.

…d clarity

- Added error handling in promptForOutputDirectory to fallback to the default directory if input reading fails.
- Updated the translation list command description for better clarity on its purpose.
- Modified the output directory flag description in translation pull command to reference the shared default directory variable.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
internal/commands/category/category_translation/helpers.go (1)

13-30: Consider expanding tilde (~) in user paths.

If a user enters a path like ~/translations, the tilde won't expand to the home directory since os.MkdirAll doesn't handle this. You could add filepath.Clean and check for a leading tilde, then expand it using os.UserHomeDir().

Example enhancement:

input = strings.TrimSpace(input)
if input == "" {
    return dd
}
// Expand tilde if present
if strings.HasPrefix(input, "~") {
    homeDir, err := os.UserHomeDir()
    if err == nil {
        input = filepath.Join(homeDir, strings.TrimPrefix(input, "~"))
    }
}
return input
internal/commands/category/category_translation/translation_list.go (2)

17-33: Handle flag errors and empty workspace more explicitly

GetString("workspace") ignores its error and allows an empty workspace to flow into ListPreferenceTranslations, which can make flag wiring issues or missing workspace hard to diagnose at runtime. Consider checking the error and validating that workspace is non-empty before calling the client, logging a clear user-facing message if either check fails.

-		workspace, _ := cmd.Flags().GetString("workspace")
+		workspace, err := cmd.Flags().GetString("workspace")
+		if err != nil {
+			log.WithError(err).Error("Failed to read --workspace flag")
+			return
+		}
+		if workspace == "" {
+			log.Error("workspace is required; please set --workspace")
+			return
+		}

34-43: Preserve the typed result slice when emitting empty piped output

For the len(translations.Results) == 0 && utils.IsOutputPiped() case, passing []interface{}{} to OutputData discards the concrete element type, which can lead to inconsistent schema (especially for table output, and potentially for tools introspecting struct fields). Reusing translations.Results here keeps the output shape consistent while still representing “no results”.

-		if len(translations.Results) == 0 && utils.IsOutputPiped() {
-			utils.OutputData([]interface{}{}, outputType)
-			return
-		}
-		utils.OutputData(translations.Results, outputType)
+		if len(translations.Results) == 0 && utils.IsOutputPiped() {
+			// Preserve the concrete element type for consistent schema, even when empty.
+			utils.OutputData(translations.Results, outputType)
+			return
+		}
+		utils.OutputData(translations.Results, outputType)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 924dfc4 and a48ea75.

📒 Files selected for processing (3)
  • internal/commands/category/category_translation/helpers.go (1 hunks)
  • internal/commands/category/category_translation/translation_list.go (1 hunks)
  • internal/commands/category/category_translation/translation_pull.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/commands/category/category_translation/translation_pull.go
🧰 Additional context used
📓 Path-based instructions (1)
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/category/category_translation/helpers.go
  • internal/commands/category/category_translation/translation_list.go
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/
🧬 Code graph analysis (1)
internal/commands/category/category_translation/translation_list.go (3)
internal/utils/outpututil.go (2)
  • IsOutputPiped (25-38)
  • OutputData (55-65)
internal/utils/sdk_instance.go (1)
  • GetSuprSendMgmntClient (23-25)
internal/commands/category/category_translation/translation.go (1)
  • TranslationCmd (7-14)
🔇 Additional comments (3)
internal/commands/category/category_translation/helpers.go (2)

19-24: Good error handling improvement.

The error from ReadString is now properly handled with logging to stderr and a fallback to the default directory. This addresses the concern from the previous review about silently ignoring read errors.


32-37: LGTM!

The directory creation logic is clean and idiomatic. MkdirAll handles existing directories gracefully, and the 0755 permissions are appropriate for user-created directories.

internal/commands/category/category_translation/translation_list.go (1)

47-49: Subcommand registration via init aligns with CLI structure

Registering translationListCmd on TranslationCmd inside this file’s init() follows the internal internal/commands/** convention of wiring subcommands locally rather than in a central registry. This matches the documented pattern and keeps command wiring cohesive.

Based on learnings, this is consistent with the expected init-based registration style.

- Moved workspace and management client initialization to the beginning of the command execution for better readability.
- Enhanced the loading message to provide feedback on the number of listed translation locales.
- Maintained existing error handling for fetching translations while ensuring consistent command flow.
- Updated error messages for JSON serialization failures to enhance clarity and consistency.
- Changed log messages to provide more informative feedback when translation marshalling fails.
- Changed the flag for the `force` option in the translation pull command to use the standard flag set instead of persistent flags.
- Updated the default directory description in the translation push command to reference the shared default directory variable for improved clarity.
- Renamed `PreferenceTranslationResponse` to `PreferenceTranslationContent` for clarity and consistency across the codebase.
- Updated related function signatures and variable types in the translation push command to reflect the new naming convention.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
internal/commands/category/category_translation/translation_push.go (1)

52-73: Consider extracting file filtering logic into a helper function.

The file filtering logic is correct but involves multiple conditions (JSON suffix check, locale filtering, exclusions). Extracting this into a helper function would improve testability and readability.

Example helper function:

// getTranslationFiles filters and returns translation files from the directory
func getTranslationFiles(files []os.DirEntry, locale string) []string {
	var localeFiles []string
	for _, file := range files {
		if file.IsDir() {
			continue
		}
		name := file.Name()
		if strings.HasSuffix(name, ".json") {
			fileLocale := strings.TrimSuffix(name, ".json")
			if locale != "" && fileLocale != locale {
				continue
			}
			if fileLocale == "categories_preferences" {
				continue
			}
			localeFiles = append(localeFiles, name)
		}
	}
	return localeFiles
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b0ecd7 and 12d264d.

📒 Files selected for processing (2)
  • internal/commands/category/category_translation/translation_pull.go (1 hunks)
  • internal/commands/category/category_translation/translation_push.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/commands/category/category_translation/translation_pull.go
🧰 Additional context used
📓 Path-based instructions (1)
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/category/category_translation/translation_push.go
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/
🔇 Additional comments (3)
internal/commands/category/category_translation/translation_push.go (3)

27-38: LGTM!

The directory resolution logic correctly falls back to the default directory when no custom directory is provided, and properly validates directory existence before proceeding.


80-88: LGTM!

The spinner initialization correctly checks if output is piped and uses proper context management with deferred cleanup.


155-159: LGTM!

The command registration correctly follows the coding guidelines by registering the subcommand via init() function. The flags are properly defined with appropriate short forms and helpful descriptions.

As per coding guidelines, subcommands are registered in their own init() functions.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
internal/commands/category/category_translation/translation_push.go (2)

107-151: Avoid double-reporting the same errors (per-file log + final summary)

Each failure is both logged (log.WithError(...).Errorf(...)) and appended to errors, which are then printed at the end (Lines 145‑151). This leads to duplicated error output for the same condition.

Consider relying on the aggregated errors slice for user-facing output and downgrading/removing the per-iteration error logs, for example:

-			data, err := os.ReadFile(filePath)
-			if err != nil {
-				log.WithError(err).Errorf("Couldn't read translations from file %s", filePath)
-				failedCount++
-				errors = append(errors, fmt.Sprintf("Failed to read %s: %v", fileName, err))
-				continue
-			}
+			data, err := os.ReadFile(filePath)
+			if err != nil {
+				failedCount++
+				errors = append(errors, fmt.Sprintf("Failed to read %s: %v", fileName, err))
+				continue
+			}

Apply the same pattern to the JSON parse and push failures so each error is reported once in the final summary.


22-38: Validate the workspace flag before making API calls

workspace is read (Line 23) but never checked. If omitted/empty, the API call will use an empty workspace segment and fail with a generic HTTP error instead of a clear CLI message. Add an early guard that errors out with helpful usage.

Example:

-		workspace, _ := cmd.Flags().GetString("workspace")
+		workspace, _ := cmd.Flags().GetString("workspace")
+		workspace = strings.TrimSpace(workspace)
+		if workspace == "" {
+			cmd.PrintErrln("workspace flag is required")
+			_ = cmd.Usage()
+			return
+		}

This keeps failures local and consistent with other commands that require --workspace.

🧹 Nitpick comments (1)
mgmnt/preference_translation.go (1)

27-105: Consolidate repeated HTTP error-handling logic across translation methods

ListPreferenceTranslations, GetPreferenceTranslationsForLocale, and PushPreferenceTranslation all use the same pattern:

  • build URL
  • execute request
  • on transport error: log and return
  • on res.IsError(): try to unmarshal ErrorResponse, else fall back to status

This is correct but quite duplicated. Consider extracting a small helper in mgmnt to decode management errors (e.g., taking a *resty.Response and returning an error), and possibly another helper to construct a configured HTTP client for mgmnt calls. That would reduce repetition and keep future changes to error formatting in one place.

You could also avoid the extra allocation in:

json.Unmarshal([]byte(res.String()), &errorResp)

by using the raw body instead (e.g., res.Body() or a similar accessor), depending on the resty version in use.

Overall behavior is sound; this is just for maintainability and small efficiency gains.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 12d264d and f4d0a60.

📒 Files selected for processing (2)
  • internal/commands/category/category_translation/translation_push.go (1 hunks)
  • mgmnt/preference_translation.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
mgmnt/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/cli-structure.mdc)

Place management and client-related Go code under the mgmnt/ directory

Files:

  • mgmnt/preference_translation.go
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/category/category_translation/translation_push.go
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to mgmnt/**/*.go : Place management and client-related Go code under the mgmnt/ directory

Applied to files:

  • mgmnt/preference_translation.go
🧬 Code graph analysis (1)
mgmnt/preference_translation.go (4)
mgmnt/client.go (1)
  • SS_MgmntClient (26-32)
internal/client/httpclient.go (1)
  • NewHTTPClient (11-27)
internal/commands/schema/helpers.go (1)
  • R (227-227)
mgmnt/category.go (1)
  • ErrorResponse (52-55)
🔇 Additional comments (2)
internal/commands/category/category_translation/translation_push.go (1)

155-159: Command registration via init matches CLI structure guidelines

Registering translationPushCmd onto TranslationCmd inside init() is consistent with the internal/commands convention for wiring subcommands and matches the documented structure for this repo. No changes needed here. Based on learnings, this follows the expected CLI registration pattern.

mgmnt/preference_translation.go (1)

11-25: Translation model types and placement in mgmnt/ look correct

PreferenceTranslation, PreferenceTranslationContent, and ListPreferenceTranslation are minimal, JSON-tagged DTOs and are correctly placed under mgmnt/ alongside other management client types. This aligns with the mgmnt layout guideline. Based on learnings, the structure and location look appropriate.

…ed error logging

- Added a check to ensure the workspace flag is provided, enhancing command usability.
- Changed error logging for file read failures from error to debug level for better log management.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
internal/commands/category/category_translation/translation_push.go (2)

23-31: Workspace validation is good; consider signaling failure via exit code/usage.

You’ve addressed the earlier concern by validating workspace for emptiness, which is good. Right now, though, the command just logs an error and returns, which likely still exits with code 0 and shows no usage hint. For better CLI UX and scriptability, consider returning a non‑zero exit status and/or invoking cmd.Usage() or cmd.PrintErrf here so callers immediately see what went wrong.


111-140: Still a mix of per‑item error logging and aggregated reporting.

You’ve downgraded the file‑read failure to Debugf, which avoids duplicate user‑visible noise, but JSON parse and push failures still log at Errorf and get added to errors, which are then printed again at the end. This can result in each failure being shown twice.

To keep output concise and consistent, consider aligning all three sites:

  • Either rely solely on the aggregated errors slice for user‑facing messages and keep per‑item logs at Debugf, or
  • Keep Errorf logging and drop the errors slice + final printing.

For example, if you keep aggregation:

- if err := json.Unmarshal(data, &translation); err != nil {
-     log.WithError(err).Errorf("Couldn't parse translations JSON from %s", filePath)
+ if err := json.Unmarshal(data, &translation); err != nil {
+     log.WithError(err).Debugf("Couldn't parse translations JSON from %s", filePath)
      failedCount++
      errors = append(errors, fmt.Sprintf("Failed to parse JSON from %s: %v", fileName, err))
      continue
 }

- err = mgmntClient.PushPreferenceTranslation(workspace, fileLocale, translation)
- if err != nil {
-     log.WithError(err).Errorf("Couldn't push translations for locale %s", fileLocale)
+ err = mgmntClient.PushPreferenceTranslation(workspace, fileLocale, translation)
+ if err != nil {
+     log.WithError(err).Debugf("Couldn't push translations for locale %s", fileLocale)
      failedCount++
      errors = append(errors, fmt.Sprintf("Failed to push %s: %v", fileName, err))
      continue
 }

Also applies to: 150-156

🧹 Nitpick comments (1)
internal/commands/category/category_translation/translation_push.go (1)

150-156: Consider writing aggregated errors to stderr instead of stdout.

The final error summary is printed to os.Stdout. For CLI tools, it’s often preferable to send errors to stderr so that scripts can safely pipe or capture normal output separately from failures (and detect presence of errors by checking stderr). Switching these Fprintf calls to os.Stderr would better follow that convention.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f4d0a60 and b758a7a.

📒 Files selected for processing (1)
  • internal/commands/category/category_translation/translation_push.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/category/category_translation/translation_push.go
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/
🔇 Additional comments (1)
internal/commands/category/category_translation/translation_push.go (1)

160-164: Command registration pattern looks consistent with guidelines.

Registering translationPushCmd with TranslationCmd inside this file’s init() matches the “register subcommands via init under internal/commands” pattern and keeps wiring nicely localized. No issues here.

- Introduced a new `translation` command to manage preference category translations, including subcommands for listing, pulling, and pushing translations.
- Implemented helper functions for handling output directories and ensuring their existence.
- Enhanced error handling and logging for improved user feedback during translation operations.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
internal/commands/category/translation/translation_push.go (1)

112-139: Inconsistent error logging levels.

The error logging uses different levels: Debugf at line 114, but Errorf at lines 123 and 132. Since all three error cases follow the same pattern (individual log + accumulated error), they should use consistent log levels.

Apply this diff to make logging consistent:

 			// Parse the JSON
 			var translation mgmnt.PreferenceTranslationContent
 			if err := json.Unmarshal(data, &translation); err != nil {
-				log.WithError(err).Errorf("Couldn't parse translations JSON from %s", filePath)
+				log.WithError(err).Debugf("Couldn't parse translations JSON from %s", filePath)
 				failedCount++
 				errors = append(errors, fmt.Sprintf("Failed to parse JSON from %s: %v", fileName, err))
 				continue
 			}
 
 			// Push translations for this locale
 			err = mgmntClient.PushPreferenceTranslation(workspace, fileLocale, translation)
 			if err != nil {
-				log.WithError(err).Errorf("Couldn't push translations for locale %s", fileLocale)
+				log.WithError(err).Debugf("Couldn't push translations for locale %s", fileLocale)
 				failedCount++
 				errors = append(errors, fmt.Sprintf("Failed to push %s: %v", fileName, err))
 				continue

This aligns with the pattern started at line 114 and avoids duplicate error output (since errors are accumulated and printed at lines 151-156).

🧹 Nitpick comments (3)
internal/commands/category/translation/translation_list.go (1)

32-36: Ensure non-zero exit status on error.

The command logs the error and returns, which exits with status 0. For CLI automation and scripting, errors should signal failure to the shell.

Consider using os.Exit(1) after logging the error:

 		translations, err := mgmntClient.ListPreferenceTranslations(workspace)
 		if err != nil {
 			log.WithError(err).Error("Couldn't fetch translations")
+			os.Exit(1)
-			return
 		}
internal/commands/category/translation/translation_pull.go (1)

54-58: Ensure non-zero exit status on error.

The command logs the error and returns, which exits with status 0. For CLI automation and scripting, errors should signal failure to the shell.

Consider using os.Exit(1) after logging the error:

 		locales, err := mgmntClient.ListPreferenceTranslations(workspace)
 		if err != nil {
 			log.WithError(err).Errorf("Couldn't fetch translation locales from workspace '%s'", workspace)
+			os.Exit(1)
-			return
 		}

Apply the same pattern to other error cases in this function (lines 38-41).

internal/commands/category/translation/translation_push.go (1)

27-30: Good validation, but consider exit status.

The workspace validation is correctly implemented. For consistency with CLI best practices, consider exiting with a non-zero status:

 		if workspace == "" {
 			log.Error("workspace flag is required")
+			os.Exit(1)
-			return
 		}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b758a7a and 0b727a8.

📒 Files selected for processing (6)
  • internal/commands/category/category.go (2 hunks)
  • internal/commands/category/translation/helpers.go (1 hunks)
  • internal/commands/category/translation/translation.go (1 hunks)
  • internal/commands/category/translation/translation_list.go (1 hunks)
  • internal/commands/category/translation/translation_pull.go (1 hunks)
  • internal/commands/category/translation/translation_push.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/commands/category/category.go
🧰 Additional context used
📓 Path-based instructions (1)
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/category/translation/translation.go
  • internal/commands/category/translation/translation_list.go
  • internal/commands/category/translation/helpers.go
  • internal/commands/category/translation/translation_pull.go
  • internal/commands/category/translation/translation_push.go
🧬 Code graph analysis (3)
internal/commands/category/translation/translation_list.go (3)
internal/utils/sdk_instance.go (1)
  • GetSuprSendMgmntClient (23-25)
internal/utils/outpututil.go (2)
  • IsOutputPiped (25-38)
  • OutputData (55-65)
internal/commands/category/translation/translation.go (1)
  • TranslationCmd (7-14)
internal/commands/category/translation/translation_pull.go (3)
internal/utils/outpututil.go (1)
  • IsOutputPiped (25-38)
internal/utils/sdk_instance.go (1)
  • GetSuprSendMgmntClient (23-25)
internal/commands/category/translation/translation.go (1)
  • TranslationCmd (7-14)
internal/commands/category/translation/translation_push.go (3)
internal/utils/outpututil.go (1)
  • IsOutputPiped (25-38)
internal/utils/sdk_instance.go (1)
  • GetSuprSendMgmntClient (23-25)
mgmnt/preference_translation.go (1)
  • PreferenceTranslationContent (16-19)
🔇 Additional comments (5)
internal/commands/category/translation/translation_list.go (1)

52-54: LGTM!

The command registration follows the coding guideline by registering the subcommand in its own init() function.

internal/commands/category/translation/helpers.go (2)

13-30: LGTM!

The function properly handles user input with appropriate fallback to the default directory on error and empty input.


32-37: LGTM!

The directory creation logic is correct with appropriate permissions (0755) and proper error wrapping.

internal/commands/category/translation/translation_pull.go (1)

109-113: LGTM!

The command registration follows the coding guideline by registering the subcommand in its own init() function, and the flag definitions are appropriate.

internal/commands/category/translation/translation_push.go (1)

160-164: LGTM!

The command registration follows the coding guideline by registering the subcommand in its own init() function, and the flag definitions are appropriate.

…g and user feedback

- Added detailed error messages for translation command failures to improve user experience.
- Implemented additional checks for input validation in translation commands to prevent runtime errors.
- Updated command descriptions for clarity and consistency across the translation command suite.
- Added functionality to sync category translations between workspaces, including fetching, writing, and pushing translations for non-English locales.
- Enhanced error handling and logging for translation operations to provide better feedback on failures.
- Improved user experience by reporting the number of successfully pushed translations.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
internal/commands/sync.go (2)

291-352: Consider organizing translation files in a subdirectory.

The function correctly implements the sync logic with appropriate error handling. However, translation files (e.g., fr.json, es.json) are written to the same directory as categories_preferences.json. While unlikely to cause conflicts, consider organizing them in a subdirectory like translations/ for better separation of concerns.

For example, update line 317:

-		filename := filepath.Join(dirPath, fmt.Sprintf("%s.json", locale))
+		translationDir := filepath.Join(dirPath, "translations")
+		os.MkdirAll(translationDir, 0755)
+		filename := filepath.Join(translationDir, fmt.Sprintf("%s.json", locale))

Otherwise, the implementation is solid with good error collection and logging.


304-307: Verify the hardcoded English locale skip is intentional.

The function skips "en" translations without explanation. If English is the default locale that doesn't require separate translation files, consider adding a comment to clarify this behavior.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f89a39 and a2c953e.

📒 Files selected for processing (1)
  • internal/commands/sync.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
internal/commands/*.go

📄 CodeRabbit inference engine (.cursor/rules/cli-structure.mdc)

Register subcommands via init() functions in files under internal/commands/

Files:

  • internal/commands/sync.go
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/sync.go
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to mgmnt/**/*.go : Place management and client-related Go code under the mgmnt/ directory
🧬 Code graph analysis (1)
internal/commands/sync.go (1)
mgmnt/client.go (1)
  • SS_MgmntClient (26-32)
🔇 Additional comments (2)
internal/commands/sync.go (2)

282-286: LGTM! Well-integrated translation sync.

The call to syncCategoryTranslations is appropriately placed after pushing categories, ensuring that category translations are synced alongside their related categories. Error propagation is handled correctly.


293-293: All three management client methods exist and are properly implemented:

  • ListPreferenceTranslations(workspace string) (*ListPreferenceTranslation, error) in mgmnt/preference_translation.go
  • GetPreferenceTranslationsForLocale(workspace, locale string) (*PreferenceTranslationContent, error) in mgmnt/preference_translation.go
  • PushPreferenceTranslation(workspace, locale string, translation PreferenceTranslationContent) error in mgmnt/preference_translation.go

The methods are correctly defined on *SS_MgmntClient and their usage at lines 293, 309, and 332 is appropriate.

…roved functionality

- Added a `dir` flag to specify the output directory for category translations, defaulting to `./suprsend/category`.
- Updated the translation push and pull commands to utilize the new directory handling logic.
- Refactored translation command functions for better clarity and structure, including error handling improvements.
- Enhanced logging to provide clearer feedback during translation operations.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
internal/commands/category/translation/translation_pull.go (1)

75-101: Consider using consistent log levels to avoid duplicate error output.

The loop logs errors at Errorf level (lines 79, 88, 95) while also accumulating them in the errors slice for the summary. When the log level includes errors, users will see duplicate messages.

For consistency with translation_push.go line 119 (which uses Debugf), consider using Debugf for per-iteration logging and reserving the aggregated summary for user-facing output.

 		translations, err := mgmntClient.GetPreferenceTranslationsForLocale(workspace, locale)
 		if err != nil {
-			log.WithError(err).Errorf("Couldn't fetch translations for locale '%s' from workspace '%s'", locale, workspace)
+			log.WithError(err).Debugf("Couldn't fetch translations for locale '%s' from workspace '%s'", locale, workspace)
 			failedCount++
 			errors = append(errors, fmt.Sprintf("Locale '%s': Failed to fetch translations from workspace '%s' - %v", locale, workspace, err))
 			continue
internal/commands/category/translation/translation_push.go (1)

125-141: Inconsistent log levels within the error handling loop.

Line 119 uses Debugf (as addressed from prior review), but lines 128 and 137 still use Errorf. This results in inconsistent behavior where some errors are logged twice (via log and the accumulated summary) while others are not.

For consistency, consider using Debugf for all per-iteration errors:

 		var translation mgmnt.PreferenceTranslationContent
 		if err := json.Unmarshal(data, &translation); err != nil {
-			log.WithError(err).Errorf("Couldn't parse translations JSON from %s", filePath)
+			log.WithError(err).Debugf("Couldn't parse translations JSON from %s", filePath)
 			failedCount++
 			errors = append(errors, fmt.Sprintf("Failed to parse JSON from %s: %v", fileName, err))
 			continue
 		}

 		// Push translations for this locale
 		err = mgmntClient.PushPreferenceTranslation(workspace, fileLocale, translation)
 		if err != nil {
-			log.WithError(err).Errorf("Couldn't push translations for locale %s", fileLocale)
+			log.WithError(err).Debugf("Couldn't push translations for locale %s", fileLocale)
 			failedCount++
 			errors = append(errors, fmt.Sprintf("Failed to push %s: %v", fileName, err))
 			continue
 		}
internal/commands/category/category_commit.go (1)

52-54: Consider clarifying the --dir flag semantics and handling missing translations gracefully.

Two observations:

  1. Flag description mismatch: The --dir flag is described as "Output directory for categories" (line 59), but here it's used as an input directory to read translations from. Consider updating the description to reflect its dual purpose, e.g., "Directory for categories (used for reading translations during commit)".

  2. Silent failure on missing translations: If the translation directory doesn't exist (e.g., user commits without prior pull), PushTranslations logs an error and returns, but the category commit still succeeds. This may surprise users who expect translations to be pushed.

Consider adding a check or user feedback:

 		// Push translations after committing categories
+		if _, err := os.Stat(translationDir); os.IsNotExist(err) {
+			log.Warnf("Translation directory %s does not exist, skipping translation push", translationDir)
+		} else {
 			translation.PushTranslations(workspace, "", translationDir)
+		}

And update the flag description:

-	categoryCommitCmd.Flags().StringP("dir", "d", "", "Output directory for categories (default: ./suprsend/category)")
+	categoryCommitCmd.Flags().StringP("dir", "d", "", "Category directory (default: ./suprsend/category)")

Also applies to: 59-59

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2c953e and 7b21a81.

📒 Files selected for processing (6)
  • internal/commands/category/category_commit.go (3 hunks)
  • internal/commands/category/category_pull.go (2 hunks)
  • internal/commands/category/translation/helpers.go (1 hunks)
  • internal/commands/category/translation/translation_list.go (1 hunks)
  • internal/commands/category/translation/translation_pull.go (1 hunks)
  • internal/commands/category/translation/translation_push.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/commands/category/translation/translation_list.go
  • internal/commands/category/translation/helpers.go
🧰 Additional context used
📓 Path-based instructions (1)
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/category/category_commit.go
  • internal/commands/category/translation/translation_pull.go
  • internal/commands/category/category_pull.go
  • internal/commands/category/translation/translation_push.go
🧠 Learnings (7)
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/root.go : Define the root command and global flags in internal/commands/root.go

Applied to files:

  • internal/commands/category/category_commit.go
  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to cmd/suprsend/main.go : The CLI entry point is cmd/suprsend/main.go and should invoke commands.Execute()

Applied to files:

  • internal/commands/category/category_commit.go
  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/

Applied to files:

  • internal/commands/category/category_commit.go
  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/utils/banner.go : Print the CLI banner from internal/utils/banner.go

Applied to files:

  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to cmd/suprsend/main.go : Ensure the main entry point calls `commands.Execute()` to run the CLI

Applied to files:

  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to internal/commands/root.go : Define the CLI root command as `rootCmd` in internal/commands/root.go

Applied to files:

  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to internal/commands/**/!(root).go : Register each subcommand by calling `rootCmd.AddCommand(...)` in the subcommand’s own `init()` function

Applied to files:

  • internal/commands/category/category_pull.go
🧬 Code graph analysis (4)
internal/commands/category/category_commit.go (1)
internal/commands/category/translation/translation_push.go (1)
  • PushTranslations (31-162)
internal/commands/category/translation/translation_pull.go (3)
internal/utils/outpututil.go (1)
  • IsOutputPiped (25-38)
internal/utils/sdk_instance.go (1)
  • GetSuprSendMgmntClient (23-25)
internal/commands/category/translation/translation.go (1)
  • TranslationCmd (7-14)
internal/commands/category/category_pull.go (1)
internal/commands/category/translation/translation_pull.go (1)
  • PullTranslations (29-117)
internal/commands/category/translation/translation_push.go (4)
internal/utils/outpututil.go (1)
  • IsOutputPiped (25-38)
internal/utils/sdk_instance.go (1)
  • GetSuprSendMgmntClient (23-25)
mgmnt/preference_translation.go (1)
  • PreferenceTranslationContent (16-19)
internal/commands/category/translation/translation.go (1)
  • TranslationCmd (7-14)
🔇 Additional comments (11)
internal/commands/category/translation/translation_pull.go (3)

1-14: LGTM - Package and imports are appropriate.

The imports are properly organized and all are utilized within the file.


16-27: LGTM - Command definition properly delegates to the exported function.

The command wiring is clean, and validation is correctly deferred to PullTranslations.


119-123: LGTM - Command registration follows coding guidelines.

The subcommand is properly registered via init() using TranslationCmd.AddCommand(translationPullCmd), as per the coding guidelines.

internal/commands/category/translation/translation_push.go (4)

1-16: LGTM - Package and imports are appropriate.

All imports are utilized within the file.


18-29: LGTM - Command definition properly delegates to the exported function.

Workspace validation is correctly handled inside PushTranslations.


31-60: LGTM - Validation and directory handling are correct.

The workspace validation is properly implemented. The early return for locale == "en" correctly prevents explicit English translation pushes.


164-168: LGTM - Command registration follows coding guidelines.

The subcommand is properly registered via init() using TranslationCmd.AddCommand(translationPushCmd).

internal/commands/category/category_pull.go (2)

11-11: LGTM - Import added for translation subpackage.

The import is correctly added and utilized.


68-71: LGTM - Translation pull integration is well-structured.

The translation pull is correctly chained after the category pull, using a derived translation subdirectory. The force flag is appropriately passed through.

internal/commands/category/category_commit.go (2)

6-10: LGTM - Imports added for filepath and translation subpackage.

Both imports are utilized in the new translation push integration.


58-62: LGTM - Command registration follows coding guidelines.

The subcommand is properly registered via init() using CategoryCmd.AddCommand(categoryCommitCmd).

- Removed duplicate translation push call after finalizing categories.
- Ensured translations are pushed immediately after committing categories for improved workflow efficiency.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b21a81 and bb1d4f5.

📒 Files selected for processing (1)
  • internal/commands/category/category_commit.go (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/category/category_commit.go
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/root.go : Define the root command and global flags in internal/commands/root.go

Applied to files:

  • internal/commands/category/category_commit.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to cmd/suprsend/main.go : The CLI entry point is cmd/suprsend/main.go and should invoke commands.Execute()

Applied to files:

  • internal/commands/category/category_commit.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/

Applied to files:

  • internal/commands/category/category_commit.go
🧬 Code graph analysis (1)
internal/commands/category/category_commit.go (1)
internal/commands/category/translation/translation_push.go (1)
  • PushTranslations (31-162)
🔇 Additional comments (2)
internal/commands/category/category_commit.go (2)

6-6: LGTM!

The new imports for path/filepath and the translation package are necessary for the directory handling and translation push functionality introduced in this change.

Also applies to: 10-10


60-62: LGTM!

The flag definition is clear and consistent with the directory resolution logic. The command registration in init() follows the coding guidelines.

Comment on lines 43 to 44
// Push translations after committing categories
translation.PushTranslations(workspace, "", translationDir)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n internal/commands/category/category_commit.go

Repository: suprsend/cli

Length of output: 2246


🏁 Script executed:

find . -name "*.go" -path "*/translation*" -type f | head -20

Repository: suprsend/cli

Length of output: 669


🏁 Script executed:

cat -n ./internal/commands/category/translation/translation_push.go

Repository: suprsend/cli

Length of output: 5763


🏁 Script executed:

cat -n ./internal/commands/category/translation/translation.go | head -50

Repository: suprsend/cli

Length of output: 582


Fix misleading comment about translation push sequence.

The comment states "Push translations after committing categories" but translations are actually pushed before FinalizeCategories is called on line 47. Additionally, PushTranslations does not return an error—all failures are logged internally and the category commit proceeds regardless of translation push success or failure.

Apply this diff to correct the comment:

-		// Push translations after committing categories
+		// Push translations before finalizing categories
 		translation.PushTranslations(workspace, "", translationDir)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Push translations after committing categories
translation.PushTranslations(workspace, "", translationDir)
// Push translations before finalizing categories
translation.PushTranslations(workspace, "", translationDir)
🤖 Prompt for AI Agents
internal/commands/category/category_commit.go around lines 43-44: the existing
comment "Push translations after committing categories" is misleading because
PushTranslations is invoked before FinalizeCategories (line 47) and it does not
return an error (it logs failures internally), so update the comment to state
that translations are pushed before finalization and that any translation
failures are logged and do not block the category commit.

…ndling

- Added logic to determine the translation directory, defaulting to './suprsend/category/translation' if not specified.
- Ensured translations are pushed immediately after committing categories for improved workflow efficiency.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
internal/commands/category/category_push.go (1)

27-31: Translation directory setup is correct.

The logic appropriately defaults to ./suprsend/category/translation when no directory is specified and correctly uses the provided path when available.

Note: Similar translationDir computation logic exists in category_commit.go (lines 24-31). Consider extracting to a helper function if this pattern repeats in additional files.

internal/commands/category/category_commit.go (1)

22-31: Translation directory computation is correct.

The logic correctly defaults to ./suprsend/category/translation and properly handles the custom directory flag.

Note: This logic duplicates the translationDir computation in category_push.go (lines 27-31). Consider extracting to a shared helper if this pattern expands to additional commands.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb1d4f5 and 8615f37.

📒 Files selected for processing (2)
  • internal/commands/category/category_commit.go (4 hunks)
  • internal/commands/category/category_push.go (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/category/category_push.go
  • internal/commands/category/category_commit.go
🧠 Learnings (7)
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to cmd/suprsend/main.go : The CLI entry point is cmd/suprsend/main.go and should invoke commands.Execute()

Applied to files:

  • internal/commands/category/category_push.go
  • internal/commands/category/category_commit.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/utils/banner.go : Print the CLI banner from internal/utils/banner.go

Applied to files:

  • internal/commands/category/category_push.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/

Applied to files:

  • internal/commands/category/category_push.go
  • internal/commands/category/category_commit.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/root.go : Define the root command and global flags in internal/commands/root.go

Applied to files:

  • internal/commands/category/category_push.go
  • internal/commands/category/category_commit.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to cmd/suprsend/main.go : Ensure the main entry point calls `commands.Execute()` to run the CLI

Applied to files:

  • internal/commands/category/category_push.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to internal/commands/root.go : Define the CLI root command as `rootCmd` in internal/commands/root.go

Applied to files:

  • internal/commands/category/category_push.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to internal/commands/**/!(root).go : Register each subcommand by calling `rootCmd.AddCommand(...)` in the subcommand’s own `init()` function

Applied to files:

  • internal/commands/category/category_push.go
🧬 Code graph analysis (2)
internal/commands/category/category_push.go (1)
internal/commands/category/translation/translation_push.go (1)
  • PushTranslations (31-162)
internal/commands/category/category_commit.go (1)
internal/commands/category/translation/translation_push.go (1)
  • PushTranslations (31-162)
🔇 Additional comments (5)
internal/commands/category/category_push.go (2)

12-12: LGTM: Translation package import.

The import is correctly placed and necessary for the translation integration.


60-61: No changes neededPushTranslations is designed to log failures internally without blocking the category push operation. This is an intentional pattern in the codebase.

The call at line 60 correctly invokes translation push before category push. Since PushTranslations does not propagate errors and handles all failure cases with logging, translation push failures will not prevent category operations from proceeding, which is acceptable by design.

internal/commands/category/category_commit.go (3)

6-6: LGTM: Import additions.

Both filepath and translation imports are necessary for the new directory handling and translation integration functionality.

Also applies to: 10-10


43-44: Translation push correctly placed before category finalization.

The translation push occurs before FinalizeCategories, which is appropriate. As with category_push.go, PushTranslations does not return errors—failures are logged internally, allowing the category commit to proceed regardless of translation push success.

Confirm this silent failure behavior is acceptable for your workflow.


59-59: LGTM: Flag definition is clear.

The --dir/-d flag is well-defined with an appropriate description that matches the implementation.

- Added a check to only push translations if the commit flag is set to "true", enhancing control over translation operations.
- This change improves the flexibility of the category push command by allowing users to decide when to push translations.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
internal/commands/category/category_push.go (1)

50-62: Spinner and translation push sequencing could be cleaned up

translation.PushTranslations likely shows its own progress/output, while this command’s spinner ("Pushing categories...") is already running when translations are pushed. That can (a) produce overlapping spinner output and (b) slightly mislabel the phase, since translations are being pushed before categories. Consider either starting p only after PushTranslations returns, or updating the message / reusing a single progress indicator for both steps.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8615f37 and 2b75530.

📒 Files selected for processing (1)
  • internal/commands/category/category_push.go (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/category/category_push.go
🧠 Learnings (7)
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to cmd/suprsend/main.go : The CLI entry point is cmd/suprsend/main.go and should invoke commands.Execute()

Applied to files:

  • internal/commands/category/category_push.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/utils/banner.go : Print the CLI banner from internal/utils/banner.go

Applied to files:

  • internal/commands/category/category_push.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/

Applied to files:

  • internal/commands/category/category_push.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/root.go : Define the root command and global flags in internal/commands/root.go

Applied to files:

  • internal/commands/category/category_push.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to cmd/suprsend/main.go : Ensure the main entry point calls `commands.Execute()` to run the CLI

Applied to files:

  • internal/commands/category/category_push.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to internal/commands/root.go : Define the CLI root command as `rootCmd` in internal/commands/root.go

Applied to files:

  • internal/commands/category/category_push.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to internal/commands/**/!(root).go : Register each subcommand by calling `rootCmd.AddCommand(...)` in the subcommand’s own `init()` function

Applied to files:

  • internal/commands/category/category_push.go
🧬 Code graph analysis (1)
internal/commands/category/category_push.go (1)
internal/commands/category/translation/translation_push.go (1)
  • PushTranslations (31-162)
🔇 Additional comments (1)
internal/commands/category/category_push.go (1)

12-32: Translation directory resolution and integration look sound

The new import and translationDir computation correctly derive ./suprsend/category/translation by default and respect the --dir flag so translations live under <dir>/translation while categories remain in <dir>/categories_preferences.json. I don’t see functional issues with this path logic.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
internal/commands/category/category_pull.go (1)

68-70: Good sequencing of translation pull after categories write

Calling translation.PullTranslations only after a successful category fetch/write, and scoping it under outputDir/translation, is a sensible integration and keeps translation artifacts organized alongside categories. Behavior and error handling remain clear and localized to the translation helper.

If you ever want stricter failure semantics, consider having PullTranslations return an error so this command can decide whether a translation failure should affect the overall exit status; not necessary for this PR but could tighten observability later.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b75530 and a6100c9.

📒 Files selected for processing (1)
  • internal/commands/category/category_pull.go (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
internal/commands/**/!(root).go

📄 CodeRabbit inference engine (.cursor/rules/command-registration.mdc)

Register each subcommand by calling rootCmd.AddCommand(...) in the subcommand’s own init() function

Files:

  • internal/commands/category/category_pull.go
🧠 Learnings (7)
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to cmd/suprsend/main.go : The CLI entry point is cmd/suprsend/main.go and should invoke commands.Execute()

Applied to files:

  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/utils/banner.go : Print the CLI banner from internal/utils/banner.go

Applied to files:

  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/*.go : Register subcommands via init() functions in files under internal/commands/

Applied to files:

  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:18.379Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/cli-structure.mdc:0-0
Timestamp: 2025-08-25T08:53:18.379Z
Learning: Applies to internal/commands/root.go : Define the root command and global flags in internal/commands/root.go

Applied to files:

  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to cmd/suprsend/main.go : Ensure the main entry point calls `commands.Execute()` to run the CLI

Applied to files:

  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to internal/commands/root.go : Define the CLI root command as `rootCmd` in internal/commands/root.go

Applied to files:

  • internal/commands/category/category_pull.go
📚 Learning: 2025-08-25T08:53:44.887Z
Learnt from: CR
Repo: suprsend/cli PR: 0
File: .cursor/rules/command-registration.mdc:0-0
Timestamp: 2025-08-25T08:53:44.887Z
Learning: Applies to internal/commands/**/!(root).go : Register each subcommand by calling `rootCmd.AddCommand(...)` in the subcommand’s own `init()` function

Applied to files:

  • internal/commands/category/category_pull.go
🧬 Code graph analysis (1)
internal/commands/category/category_pull.go (1)
internal/commands/category/translation/translation_pull.go (1)
  • PullTranslations (29-117)
🔇 Additional comments (1)
internal/commands/category/category_pull.go (1)

11-11: Translation package import wiring looks correct

The new translation import is used below and follows the existing internal package pattern for category subcommands. No issues here.

@gauravverma gauravverma merged commit efda25e into main Dec 12, 2025
1 check passed
@gauravverma gauravverma deleted the preferences-tr branch December 12, 2025 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants