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