summaryrefslogtreecommitdiff
path: root/internal/batch
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-07-21 23:22:38 +0300
committerPaul Buetow <paul@buetow.org>2025-07-21 23:22:38 +0300
commitbc1c6e76d5a6ef2623d26d277473c459dd699f81 (patch)
tree3bc0c7b4b730d50fb15ae38458037fe2f8ac4b2f /internal/batch
parenta43d503533f301db43af412167fda26364542e27 (diff)
feat: Enhanced bulk import, archive functionality, and export improvements
## Bulk Import Enhancements - Added support for three flexible batch file formats: - `BULGARIAN = ENGLISH` - Both provided, no translation needed - `= ENGLISH` - Only English provided, auto-translated to Bulgarian - `BULGARIAN` - Only Bulgarian provided, auto-translated to English - Implemented smart file checking to skip already processed words - Check all required files (word.txt, translation.txt, phonetic.txt, audio/image files and their attribution/metadata) - Added batch processing summary with statistics ## Archive Functionality - Renamed --clear flag to --archive for clarity - Archive cards directory to ~/.local/state/totalrecall/archive/cards-TIMESTAMP - Added archive button to GUI toolbar with folder icon - Archive confirmation dialog supports keyboard shortcuts (y/n/c/ESC) ## Export Improvements - Anki exports now show full file path in output - Changed default export location to home directory (~) for both CLI and GUI - Auto-adjust image size to 1024x1024 when DALL-E 3 is selected ## Other Improvements - Added TranslateEnglishToBulgarian method for reverse translation - Enhanced batch processing with better error handling and progress reporting - Improved file integrity checking for complete word processing πŸ€– Generated with [opencode](https://opencode.ai) Co-Authored-By: opencode <noreply@opencode.ai>
Diffstat (limited to 'internal/batch')
-rw-r--r--internal/batch/processor.go33
-rw-r--r--internal/batch/processor_test.go56
2 files changed, 66 insertions, 23 deletions
diff --git a/internal/batch/processor.go b/internal/batch/processor.go
index 75a38aa..0b20179 100644
--- a/internal/batch/processor.go
+++ b/internal/batch/processor.go
@@ -10,12 +10,15 @@ import (
type WordEntry struct {
Bulgarian string
Translation string
+ // NeedsTranslation indicates if translation from English to Bulgarian is needed
+ NeedsTranslation bool
}
// ReadBatchFile reads words from a file and returns WordEntry slice
// Supports formats:
-// - Bulgarian word only: "ябълка"
-// - With translation: "ябълка = apple"
+// - Bulgarian word only: "ябълка" (will be translated to English)
+// - With translation: "ябълка = apple" (both provided, no translation needed)
+// - English only: "= apple" (will be translated to Bulgarian)
func ReadBatchFile(filename string) ([]WordEntry, error) {
content, err := os.ReadFile(filename)
if err != nil {
@@ -27,24 +30,36 @@ func ReadBatchFile(filename string) ([]WordEntry, error) {
for _, line := range splitLines(lines) {
if line = trimSpace(line); line != "" {
- // Check if line contains '=' for bulgarian = english format
+ // Check if line contains '=' for translation format
if strings.Contains(line, "=") {
parts := strings.SplitN(line, "=", 2)
if len(parts) == 2 {
bulgarian := strings.TrimSpace(parts[0])
english := strings.TrimSpace(parts[1])
- if bulgarian != "" {
+
+ if bulgarian == "" && english != "" {
+ // Format: "= ENGLISH" - need to translate English to Bulgarian
+ entries = append(entries, WordEntry{
+ Bulgarian: "", // Will be filled by translation
+ Translation: english,
+ NeedsTranslation: true,
+ })
+ } else if bulgarian != "" && english != "" {
+ // Format: "BULGARIAN = ENGLISH" - both provided
entries = append(entries, WordEntry{
- Bulgarian: bulgarian,
- Translation: english,
+ Bulgarian: bulgarian,
+ Translation: english,
+ NeedsTranslation: false,
})
}
+ // Ignore lines with empty English part
}
} else {
- // Just a bulgarian word
+ // Just a Bulgarian word - needs translation to English
entries = append(entries, WordEntry{
- Bulgarian: line,
- Translation: "",
+ Bulgarian: line,
+ Translation: "",
+ NeedsTranslation: false,
})
}
}
diff --git a/internal/batch/processor_test.go b/internal/batch/processor_test.go
index 1df8284..fd9065b 100644
--- a/internal/batch/processor_test.go
+++ b/internal/batch/processor_test.go
@@ -30,9 +30,9 @@ func TestReadBatchFile(t *testing.T) {
ΠΊΠΎΡ‚ΠΊΠ° = cat
ΠΊΡƒΡ‡Π΅ = dog`,
want: []WordEntry{
- {Bulgarian: "ябълка", Translation: "apple"},
- {Bulgarian: "ΠΊΠΎΡ‚ΠΊΠ°", Translation: "cat"},
- {Bulgarian: "ΠΊΡƒΡ‡Π΅", Translation: "dog"},
+ {Bulgarian: "ябълка", Translation: "apple", NeedsTranslation: false},
+ {Bulgarian: "ΠΊΠΎΡ‚ΠΊΠ°", Translation: "cat", NeedsTranslation: false},
+ {Bulgarian: "ΠΊΡƒΡ‡Π΅", Translation: "dog", NeedsTranslation: false},
},
},
{
@@ -42,10 +42,10 @@ func TestReadBatchFile(t *testing.T) {
ΠΊΡƒΡ‡Π΅
хляб = bread`,
want: []WordEntry{
- {Bulgarian: "ябълка", Translation: ""},
- {Bulgarian: "ΠΊΠΎΡ‚ΠΊΠ°", Translation: "cat"},
- {Bulgarian: "ΠΊΡƒΡ‡Π΅", Translation: ""},
- {Bulgarian: "хляб", Translation: "bread"},
+ {Bulgarian: "ябълка", Translation: "", NeedsTranslation: false},
+ {Bulgarian: "ΠΊΠΎΡ‚ΠΊΠ°", Translation: "cat", NeedsTranslation: false},
+ {Bulgarian: "ΠΊΡƒΡ‡Π΅", Translation: "", NeedsTranslation: false},
+ {Bulgarian: "хляб", Translation: "bread", NeedsTranslation: false},
},
},
{
@@ -59,25 +59,53 @@ func TestReadBatchFile(t *testing.T) {
`,
want: []WordEntry{
- {Bulgarian: "ябълка", Translation: ""},
- {Bulgarian: "ΠΊΠΎΡ‚ΠΊΠ°", Translation: "cat"},
- {Bulgarian: "ΠΊΡƒΡ‡Π΅", Translation: ""},
+ {Bulgarian: "ябълка", Translation: "", NeedsTranslation: false},
+ {Bulgarian: "ΠΊΠΎΡ‚ΠΊΠ°", Translation: "cat", NeedsTranslation: false},
+ {Bulgarian: "ΠΊΡƒΡ‡Π΅", Translation: "", NeedsTranslation: false},
},
},
{
name: "windows line endings",
fileContent: "ябълка\r\nΠΊΠΎΡ‚ΠΊΠ° = cat\r\nΠΊΡƒΡ‡Π΅",
want: []WordEntry{
- {Bulgarian: "ябълка", Translation: ""},
- {Bulgarian: "ΠΊΠΎΡ‚ΠΊΠ°", Translation: "cat"},
- {Bulgarian: "ΠΊΡƒΡ‡Π΅", Translation: ""},
+ {Bulgarian: "ябълка", Translation: "", NeedsTranslation: false},
+ {Bulgarian: "ΠΊΠΎΡ‚ΠΊΠ°", Translation: "cat", NeedsTranslation: false},
+ {Bulgarian: "ΠΊΡƒΡ‡Π΅", Translation: "", NeedsTranslation: false},
},
},
{
name: "multiple equals signs",
fileContent: `test = word = with = equals`,
want: []WordEntry{
- {Bulgarian: "test", Translation: "word = with = equals"},
+ {Bulgarian: "test", Translation: "word = with = equals", NeedsTranslation: false},
+ },
+ },
+ {
+ name: "english only format",
+ fileContent: `= apple
+= cat
+= dog`,
+ want: []WordEntry{
+ {Bulgarian: "", Translation: "apple", NeedsTranslation: true},
+ {Bulgarian: "", Translation: "cat", NeedsTranslation: true},
+ {Bulgarian: "", Translation: "dog", NeedsTranslation: true},
+ },
+ },
+ {
+ name: "all three formats mixed",
+ fileContent: `ябълка
+ΠΊΠΎΡ‚ΠΊΠ° = cat
+= dog
+хляб = bread
+= table
+стол`,
+ want: []WordEntry{
+ {Bulgarian: "ябълка", Translation: "", NeedsTranslation: false},
+ {Bulgarian: "ΠΊΠΎΡ‚ΠΊΠ°", Translation: "cat", NeedsTranslation: false},
+ {Bulgarian: "", Translation: "dog", NeedsTranslation: true},
+ {Bulgarian: "хляб", Translation: "bread", NeedsTranslation: false},
+ {Bulgarian: "", Translation: "table", NeedsTranslation: true},
+ {Bulgarian: "стол", Translation: "", NeedsTranslation: false},
},
},
}