Skip to main content

sqlite_graphrag/i18n/validation/
messages_b.rs

1use crate::i18n::{current, Language};
2
3/// `--name-prefix` must be kebab-case starting with a letter.
4pub fn name_prefix_kebab(prefix: &str) -> String {
5    match current() {
6        Language::English => format!(
7            "--name-prefix '{prefix}' must start with a lowercase letter and contain              only lowercase letters, digits and hyphens (kebab-case)"
8        ),
9        Language::Portuguese => format!(
10            "--name-prefix '{prefix}' deve começar com letra minúscula e conter              apenas letras minúsculas, dígitos e hífens (kebab-case)"
11        ),
12    }
13}
14
15/// Too many name collisions while generating a unique memory name.
16pub fn too_many_name_collisions(base: &str, max: usize) -> String {
17    match current() {
18        Language::English => format!(
19            "too many name collisions for base '{base}' (>{max}); rename source files to disambiguate"
20        ),
21        Language::Portuguese => format!(
22            "muitas colisões de nome para a base '{base}' (>{max}); renomeie os arquivos de origem para desambiguar"
23        ),
24    }
25}
26
27/// Failed to parse an ExtractionResult from a provider.
28pub fn failed_to_parse_extraction(provider: &str, err: &impl std::fmt::Display) -> String {
29    match current() {
30        Language::English => {
31            format!("failed to deserialize {provider} output as ExtractionResult: {err}")
32        }
33        Language::Portuguese => {
34            format!("falha ao deserializar saída de {provider} como ExtractionResult: {err}")
35        }
36    }
37}
38
39/// Codex turn failed with a message.
40pub fn codex_turn_failed(message: &str) -> String {
41    match current() {
42        Language::English => format!("codex turn failed: {message}"),
43        Language::Portuguese => format!("turno codex falhou: {message}"),
44    }
45}
46
47/// Failed to parse codex agent_message as ExtractionResult.
48pub fn failed_to_parse_codex_agent_message(err: &impl std::fmt::Display, text: &str) -> String {
49    match current() {
50        Language::English => format!(
51            "failed to parse codex agent_message as ExtractionResult: {err}. text={text}"
52        ),
53        Language::Portuguese => format!(
54            "falha ao parsear agent_message do codex como ExtractionResult: {err}. text={text}"
55        ),
56    }
57}
58
59/// Claude -p failed with an error message.
60pub fn claude_p_failed(err: &str) -> String {
61    match current() {
62        Language::English => format!("claude -p failed: {err}"),
63        Language::Portuguese => format!("claude -p falhou: {err}"),
64    }
65}
66
67/// Mode-conditional flag conflicts (G20).
68pub fn mode_flag_conflicts(mode: &str, conflicts: &str) -> String {
69    match current() {
70        Language::English => format!(
71            "G20: mode-conditional flag conflicts detected for --mode={mode}:\n  - {conflicts}"
72        ),
73        Language::Portuguese => format!(
74            "G20: conflitos de flags condicionais ao modo detectados para --mode={mode}:\n  - {conflicts}"
75        ),
76    }
77}
78
79
80// ── GAP-SG-110/123: remaining Validation catalog helpers ──────────────────
81// Prefer these over ad-hoc AppError::Validation construction so EN/PT stay
82// in one place.
83
84/// Config file is a symlink (potential attack).
85pub fn config_file_is_symlink(path: &str) -> String {
86    match current() {
87        Language::English => format!("config file is a symlink (potential attack): {path}"),
88        Language::Portuguese => {
89            format!("arquivo de config é um symlink (potencial ataque): {path}")
90        }
91    }
92}
93
94/// Config parse error at path.
95pub fn config_parse_error(path: &str, err: &impl std::fmt::Display) -> String {
96    match current() {
97        Language::English => format!("config parse error in {path}: {err}"),
98        Language::Portuguese => format!("erro de parse de config em {path}: {err}"),
99    }
100}
101
102/// Config path has no parent directory component.
103pub fn config_path_no_parent(path: &str) -> String {
104    match current() {
105        Language::English => format!("config path has no parent: {path}"),
106        Language::Portuguese => format!("caminho de config sem diretório pai: {path}"),
107    }
108}
109
110/// Config file owned by a different uid; refuse overwrite.
111pub fn config_file_wrong_owner(path: &str, file_uid: u32, my_uid: u32) -> String {
112    match current() {
113        Language::English => format!(
114            "config file {path} owned by uid {file_uid}, not current uid {my_uid}; refusing to overwrite"
115        ),
116        Language::Portuguese => format!(
117            "arquivo de config {path} pertence ao uid {file_uid}, não ao uid atual {my_uid}; recusando sobrescrever"
118        ),
119    }
120}
121
122/// Path has no valid parent component.
123pub fn path_no_valid_parent(path: &str) -> String {
124    match current() {
125        Language::English => format!("path '{path}' has no valid parent component"),
126        Language::Portuguese => format!("caminho '{path}' não tem componente pai válido"),
127    }
128}
129
130/// Embedded schema JSON is invalid.
131pub fn embedded_schema_invalid_json(name: &str, err: &impl std::fmt::Display) -> String {
132    match current() {
133        Language::English => format!("embedded schema for {name} is not valid JSON: {err}"),
134        Language::Portuguese => {
135            format!("schema embutido para {name} não é JSON válido: {err}")
136        }
137    }
138}
139
140/// Invalid memory source string.
141pub fn invalid_memory_source(other: &str, expected: &str) -> String {
142    match current() {
143        Language::English => {
144            format!("invalid memory source: {other}; expected one of {expected}")
145        }
146        Language::Portuguese => {
147            format!("fonte de memória inválida: {other}; esperado um de {expected}")
148        }
149    }
150}
151
152/// Legacy embedding extraction backend removed.
153pub fn legacy_embedding_backend_removed(model: &str) -> String {
154    match current() {
155        Language::English => format!(
156            "the legacy embedding extraction backend was removed in v1.0.79 \
157             (the CLI is LLM-only); use --extraction-backend llm instead. \
158             Model requested: {model}"
159        ),
160        Language::Portuguese => format!(
161            "o backend legado de extração por embedding foi removido em v1.0.79 \
162             (a CLI é apenas LLM); use --extraction-backend llm. \
163             Modelo solicitado: {model}"
164        ),
165    }
166}
167
168/// Unknown pending_embeddings status string.
169pub fn unknown_pending_embeddings_status(other: &str) -> String {
170    match current() {
171        Language::English => format!("unknown pending_embeddings status: {other}"),
172        Language::Portuguese => {
173            format!("status de pending_embeddings desconhecido: {other}")
174        }
175    }
176}
177
178/// Unknown pending_memories status string.
179pub fn unknown_pending_memories_status(other: &str) -> String {
180    match current() {
181        Language::English => format!("unknown pending_memories status: {other}"),
182        Language::Portuguese => {
183            format!("status de pending_memories desconhecido: {other}")
184        }
185    }
186}
187
188/// Child name derived from parent exceeds MAX_MEMORY_NAME_LEN.
189pub fn child_name_exceeds_max(child: &str, parent: &str, max: usize) -> String {
190    match current() {
191        Language::English => format!(
192            "child name '{child}' derived from '{parent}' exceeds MAX_MEMORY_NAME_LEN ({max})"
193        ),
194        Language::Portuguese => format!(
195            "nome filho '{child}' derivado de '{parent}' excede MAX_MEMORY_NAME_LEN ({max})"
196        ),
197    }
198}
199
200/// Child name is not kebab-case ASCII.
201pub fn child_name_not_kebab(child: &str) -> String {
202    match current() {
203        Language::English => {
204            format!("child name '{child}' is not kebab-case ASCII; rename the parent memory")
205        }
206        Language::Portuguese => format!(
207            "nome filho '{child}' não é kebab-case ASCII; renomeie a memória pai"
208        ),
209    }
210}
211
212/// Refusing orphan entity delete without --yes.
213pub fn refuse_delete_orphans_without_yes(orphan_count: usize) -> String {
214    match current() {
215        Language::English => format!(
216            "refusing to delete {orphan_count} orphan entities without --yes (use --dry-run to preview)"
217        ),
218        Language::Portuguese => format!(
219            "recusando excluir {orphan_count} entidades órfãs sem --yes (use --dry-run para pré-visualizar)"
220        ),
221    }
222}
223
224/// Failed to run opencode --version.
225pub fn failed_to_run_opencode_version(err: &impl std::fmt::Display) -> String {
226    match current() {
227        Language::English => format!("failed to run opencode --version: {err}"),
228        Language::Portuguese => format!("falha ao executar opencode --version: {err}"),
229    }
230}
231
232/// Could not parse opencode version string.
233pub fn could_not_parse_opencode_version(raw: &str) -> String {
234    match current() {
235        Language::English => format!("could not parse opencode version from: {raw}"),
236        Language::Portuguese => {
237            format!("não foi possível parsear a versão do opencode de: {raw}")
238        }
239    }
240}
241
242/// Entity rename target already exists.
243pub fn entity_name_already_exists(name: &str, namespace: &str) -> String {
244    match current() {
245        Language::English => {
246            format!("entity with name '{name}' already exists in namespace '{namespace}'")
247        }
248        Language::Portuguese => {
249            format!("entidade com nome '{name}' já existe no namespace '{namespace}'")
250        }
251    }
252}
253
254/// Entity name too short.
255pub fn entity_name_too_short(name: &str) -> String {
256    match current() {
257        Language::English => format!("entity name '{name}' must be at least 2 characters"),
258        Language::Portuguese => {
259            format!("nome de entidade '{name}' deve ter pelo menos 2 caracteres")
260        }
261    }
262}
263
264/// Purely numeric entity name rejected.
265pub fn entity_name_purely_numeric(name: &str) -> String {
266    match current() {
267        Language::English => format!(
268            "entity name '{name}' rejected: purely numeric names look like entity IDs — \
269             use --from-id/--to-id for ID-based linking, or pass a non-numeric name"
270        ),
271        Language::Portuguese => format!(
272            "nome de entidade '{name}' rejeitado: nomes puramente numéricos parecem IDs — \
273             use --from-id/--to-id para link por ID, ou passe um nome não numérico"
274        ),
275    }
276}
277
278/// Short ALL_CAPS entity name rejected as NER noise.
279pub fn entity_name_all_caps_noise(name: &str) -> String {
280    match current() {
281        Language::English => format!(
282            "entity name '{name}' rejected: short ALL_CAPS names are typically NER noise"
283        ),
284        Language::Portuguese => format!(
285            "nome de entidade '{name}' rejeitado: nomes curtos em CAIXA ALTA são tipicamente ruído de NER"
286        ),
287    }
288}
289
290/// Entity name normalizes too short.
291pub fn entity_name_normalizes_too_short(original: &str, normalized: &str) -> String {
292    match current() {
293        Language::English => format!(
294            "entity name '{original}' normalizes to '{normalized}' which is too short (minimum 2 characters)"
295        ),
296        Language::Portuguese => format!(
297            "nome de entidade '{original}' normaliza para '{normalized}' que é curto demais (mínimo 2 caracteres)"
298        ),
299    }
300}
301
302/// Invalid pending-embeddings status filter.
303pub fn invalid_status_filter(other: &str) -> String {
304    match current() {
305        Language::English => format!(
306            "invalid status filter: {other} (expected pending|in_progress|done|abandoned)"
307        ),
308        Language::Portuguese => format!(
309            "filtro de status inválido: {other} (esperado pending|in_progress|done|abandoned)"
310        ),
311    }
312}
313
314/// Non-canonical relation under --strict-relations.
315pub fn non_canonical_relation(relation: &str, allowed: &str) -> String {
316    match current() {
317        Language::English => format!(
318            "non-canonical relation '{relation}': use --strict-relations=false or choose from: {allowed}"
319        ),
320        Language::Portuguese => format!(
321            "relação não canônica '{relation}': use --strict-relations=false ou escolha entre: {allowed}"
322        ),
323    }
324}
325
326/// Self-referential merge by id (pre-check with --ids hint).
327pub fn self_merge_id_in_ids(id: i64) -> String {
328    match current() {
329        Language::English => format!(
330            "source entity id={id} equals target id={id} — \
331             self-referential merge is not allowed (remove target from --ids)"
332        ),
333        Language::Portuguese => format!(
334            "entidade fonte id={id} é igual ao alvo id={id} — \
335             merge auto-referencial não é permitido (remova o alvo de --ids)"
336        ),
337    }
338}
339
340/// Self-referential merge by name (pre-check with --names hint).
341pub fn self_merge_name_in_names(name: &str) -> String {
342    match current() {
343        Language::English => format!(
344            "source entity '{name}' equals target '{name}' — \
345             self-referential merge is not allowed (remove target from --names)"
346        ),
347        Language::Portuguese => format!(
348            "entidade fonte '{name}' é igual ao alvo '{name}' — \
349             merge auto-referencial não é permitido (remova o alvo de --names)"
350        ),
351    }
352}
353
354/// Self-referential merge by id (generic).
355pub fn self_merge_id(id: i64, target_id: i64) -> String {
356    match current() {
357        Language::English => format!(
358            "source entity id={id} equals target id={target_id} — \
359             self-referential merge is not allowed"
360        ),
361        Language::Portuguese => format!(
362            "entidade fonte id={id} é igual ao alvo id={target_id} — \
363             merge auto-referencial não é permitido"
364        ),
365    }
366}
367
368/// Self-referential merge by name (generic).
369pub fn self_merge_name(name: &str, target_name: &str) -> String {
370    match current() {
371        Language::English => format!(
372            "source entity '{name}' equals target '{target_name}' — \
373             self-referential merge is not allowed"
374        ),
375        Language::Portuguese => format!(
376            "entidade fonte '{name}' é igual ao alvo '{target_name}' — \
377             merge auto-referencial não é permitido"
378        ),
379    }
380}
381
382/// Source name resolves to target id (self-merge).
383pub fn self_merge_name_resolves_to_target(name: &str, target_id: i64) -> String {
384    match current() {
385        Language::English => format!(
386            "source entity '{name}' resolves to the target (id={target_id}) — \
387             self-referential merge is not allowed"
388        ),
389        Language::Portuguese => format!(
390            "entidade fonte '{name}' resolve para o alvo (id={target_id}) — \
391             merge auto-referencial não é permitido"
392        ),
393    }
394}
395
396/// Batch line: invalid JSON.
397pub fn batch_line_invalid_json(index: usize, err: &impl std::fmt::Display) -> String {
398    match current() {
399        Language::English => format!("line {index}: invalid JSON: {err}"),
400        Language::Portuguese => format!("linha {index}: JSON inválido: {err}"),
401    }
402}
403
404/// Batch line: name normalizes empty.
405pub fn batch_line_name_empty(index: usize) -> String {
406    match current() {
407        Language::English => format!("line {index}: name normalizes to empty string"),
408        Language::Portuguese => {
409            format!("linha {index}: nome normaliza para string vazia")
410        }
411    }
412}
413
414/// Batch line: type/description required.
415pub fn batch_line_type_description_required(index: usize) -> String {
416    match current() {
417        Language::English => format!(
418            "line {index}: --type and --description are required when creating a new memory"
419        ),
420        Language::Portuguese => format!(
421            "linha {index}: --type e --description são obrigatórios ao criar uma nova memória"
422        ),
423    }
424}
425
426/// Executable not found in PATH (generic install wording).
427pub fn executable_not_in_path_generic(binary: &str) -> String {
428    match current() {
429        Language::English => format!(
430            "executable '{binary}' not found in PATH; ensure it is installed and accessible"
431        ),
432        Language::Portuguese => format!(
433            "executável '{binary}' não encontrado no PATH; certifique-se de que está instalado e acessível"
434        ),
435    }
436}
437
438/// Failed to parse claude output as JSON array.
439pub fn failed_to_parse_claude_json_array(err: &impl std::fmt::Display) -> String {
440    match current() {
441        Language::English => format!("failed to parse claude output as JSON array: {err}"),
442        Language::Portuguese => {
443            format!("falha ao parsear saída do claude como array JSON: {err}")
444        }
445    }
446}
447
448/// Claude extraction failed.
449pub fn claude_extraction_failed(err: &str) -> String {
450    match current() {
451        Language::English => format!("claude extraction failed: {err}"),
452        Language::Portuguese => format!("extração claude falhou: {err}"),
453    }
454}
455
456/// Failed to parse claude result field as JSON.
457pub fn failed_to_parse_claude_result_field(err: &impl std::fmt::Display) -> String {
458    match current() {
459        Language::English => format!("failed to parse claude result field as JSON: {err}"),
460        Language::Portuguese => {
461            format!("falha ao parsear campo result do claude como JSON: {err}")
462        }
463    }
464}
465
466/// Codex model not supported with ChatGPT Pro OAuth.
467pub fn codex_model_not_supported_oauth(model: &str, accepted: &str) -> String {
468    match current() {
469        Language::English => format!(
470            "--codex-model {model:?} is not supported with ChatGPT Pro OAuth. \
471             Accepted: {accepted}"
472        ),
473        Language::Portuguese => format!(
474            "--codex-model {model:?} não é suportado com ChatGPT Pro OAuth. \
475             Aceitos: {accepted}"
476        ),
477    }
478}
479
480/// No agent_message in codex JSONL output.
481pub fn no_agent_message_in_codex_jsonl(
482    rate_limited: bool,
483    schema_error: bool,
484    turn_failed: bool,
485) -> String {
486    match current() {
487        Language::English => format!(
488            "no agent_message in codex JSONL output (rate_limited={rate_limited}, schema_error={schema_error}, turn_failed={turn_failed})"
489        ),
490        Language::Portuguese => format!(
491            "nenhum agent_message na saída JSONL do codex (rate_limited={rate_limited}, schema_error={schema_error}, turn_failed={turn_failed})"
492        ),
493    }
494}
495
496/// Codex rate-limited message.
497pub fn codex_rate_limited(message: &str) -> String {
498    match current() {
499        Language::English => format!("codex rate-limited: {message}"),
500        Language::Portuguese => format!("codex com limite de taxa: {message}"),
501    }
502}
503
504/// Failed to parse codex agent_message as JSON.
505pub fn failed_to_parse_codex_agent_message_json(err: &impl std::fmt::Display) -> String {
506    match current() {
507        Language::English => format!("failed to parse codex agent_message as JSON: {err}"),
508        Language::Portuguese => {
509            format!("falha ao parsear agent_message do codex como JSON: {err}")
510        }
511    }
512}
513
514/// Codex agent_message is not valid JSON (with raw snippet).
515pub fn codex_agent_message_not_valid_json(err: &impl std::fmt::Display, raw: &str) -> String {
516    match current() {
517        Language::English => {
518            format!("codex agent_message is not valid JSON: {err}; raw={raw}")
519        }
520        Language::Portuguese => {
521            format!("agent_message do codex não é JSON válido: {err}; raw={raw}")
522        }
523    }
524}
525
526/// Opencode response is not valid JSON.
527pub fn opencode_response_not_valid_json(err: &impl std::fmt::Display) -> String {
528    match current() {
529        Language::English => format!("opencode response is not valid JSON: {err}"),
530        Language::Portuguese => {
531            format!("resposta do opencode não é JSON válido: {err}")
532        }
533    }
534}
535
536/// Failed to parse entities array.
537pub fn failed_to_parse_entities_array(err: &impl std::fmt::Display) -> String {
538    match current() {
539        Language::English => format!("failed to parse entities array: {err}"),
540        Language::Portuguese => format!("falha ao parsear array de entidades: {err}"),
541    }
542}
543
544/// Failed to parse relationships array.
545pub fn failed_to_parse_relationships_array(err: &impl std::fmt::Display) -> String {
546    match current() {
547        Language::English => format!("failed to parse relationships array: {err}"),
548        Language::Portuguese => {
549            format!("falha ao parsear array de relacionamentos: {err}")
550        }
551    }
552}
553
554/// Queue namespace migration failed.
555pub fn queue_namespace_migration_failed(err: &impl std::fmt::Display) -> String {
556    match current() {
557        Language::English => format!("queue namespace migration failed: {err}"),
558        Language::Portuguese => {
559            format!("migração de namespace da fila falhou: {err}")
560        }
561    }
562}
563
564/// Failed to read names file.
565pub fn failed_to_read_names_file(path: &str, err: &impl std::fmt::Display) -> String {
566    match current() {
567        Language::English => format!("failed to read names file {path}: {err}"),
568        Language::Portuguese => format!("falha ao ler arquivo de nomes {path}: {err}"),
569    }
570}
571
572/// Requeue-skipped failed.
573pub fn requeue_skipped_failed(err: &impl std::fmt::Display) -> String {
574    match current() {
575        Language::English => format!("requeue-skipped failed: {err}"),
576        Language::Portuguese => format!("requeue-skipped falhou: {err}"),
577    }
578}
579
580/// Requeue-dead failed.
581pub fn requeue_dead_failed(err: &impl std::fmt::Display) -> String {
582    match current() {
583        Language::English => format!("requeue-dead failed: {err}"),
584        Language::Portuguese => format!("requeue-dead falhou: {err}"),
585    }
586}
587
588/// Invalid chunk id in re-embed key.
589pub fn invalid_chunk_id_in_reembed_key(chunk_key: &str) -> String {
590    match current() {
591        Language::English => format!("invalid chunk id in re-embed key: {chunk_key}"),
592        Language::Portuguese => {
593            format!("id de chunk inválido na chave de re-embed: {chunk_key}")
594        }
595    }
596}
597
598/// Invalid relationship id.
599pub fn invalid_relationship_id(item_key: &str) -> String {
600    match current() {
601        Language::English => format!("invalid relationship id: {item_key}"),
602        Language::Portuguese => format!("id de relacionamento inválido: {item_key}"),
603    }
604}
605
606/// Preflight probe failed.
607pub fn preflight_probe_failed(stderr: &str) -> String {
608    match current() {
609        Language::English => format!("preflight probe failed: {stderr}"),
610        Language::Portuguese => format!("sonda de preflight falhou: {stderr}"),
611    }
612}
613
614/// Preflight probe timed out.
615pub fn preflight_probe_timed_out(secs: u64) -> String {
616    match current() {
617        Language::English => format!("preflight probe timed out after {secs}s"),
618        Language::Portuguese => format!("sonda de preflight expirou após {secs}s"),
619    }
620}
621
622/// Deep-research output path missing after atomic write.
623pub fn deep_research_output_missing(path: &str) -> String {
624    match current() {
625        Language::English => format!(
626            "deep-research --output failed: path does not exist after atomic write: {path}"
627        ),
628        Language::Portuguese => format!(
629            "deep-research --output falhou: caminho não existe após escrita atômica: {path}"
630        ),
631    }
632}
633
634/// Deep-research output file is empty.
635pub fn deep_research_output_empty(path: &str) -> String {
636    match current() {
637        Language::English => format!(
638            "deep-research --output failed: written file is empty (0 bytes): {path}"
639        ),
640        Language::Portuguese => format!(
641            "deep-research --output falhou: arquivo escrito está vazio (0 bytes): {path}"
642        ),
643    }
644}
645
646/// Sub-queries file has no usable lines.
647pub fn sub_queries_file_empty(path: &str) -> String {
648    match current() {
649        Language::English => format!("sub-queries file '{path}' has no usable lines"),
650        Language::Portuguese => {
651            format!("arquivo de sub-consultas '{path}' não tem linhas utilizáveis")
652        }
653    }
654}
655
656/// Refusing to release slot without --yes.
657pub fn refuse_release_slot_without_yes(slot_id: &str, path: &str) -> String {
658    match current() {
659        Language::English => {
660            format!("refusing to release slot {slot_id} without --yes (file: {path})")
661        }
662        Language::Portuguese => format!(
663            "recusando liberar slot {slot_id} sem --yes (arquivo: {path})"
664        ),
665    }
666}
667
668/// Refusing vec orphan delete without --yes.
669pub fn refuse_delete_vec_orphans_without_yes(
670    orphan_count: i64,
671    orphan_entities_count: i64,
672    orphan_chunks_count: i64,
673) -> String {
674    match current() {
675        Language::English => format!(
676            "refusing to delete {orphan_count} memory embedding + {orphan_entities_count} vec_entities + {orphan_chunks_count} vec_chunks orphan rows without --yes (use --dry-run to preview)"
677        ),
678        Language::Portuguese => format!(
679            "recusando excluir {orphan_count} embeddings de memória + {orphan_entities_count} vec_entities + {orphan_chunks_count} vec_chunks órfãos sem --yes (use --dry-run para pré-visualizar)"
680        ),
681    }
682}