Skip to main content

sqlite_graphrag/i18n/validation/
app_error_pt.rs

1/// Localized `validation` message wrapping `msg`.
2pub fn validation(msg: &str) -> String {
3    format!("erro de validação: {msg}")
4}
5
6/// Localized `duplicate` message wrapping `msg`.
7pub fn duplicate(msg: &str) -> String {
8    let translated = msg
9        .replace("already exists in namespace", "já existe no namespace")
10        .replace(
11            "exists but is soft-deleted in namespace",
12            "existe mas está excluída temporariamente no namespace",
13        )
14        .replace(
15            "Use --force-merge to update.",
16            "Use --force-merge para atualizar.",
17        )
18        .replace(
19            "use --force-merge to restore and update, or `restore` to revive it",
20            "use --force-merge para restaurar e atualizar, ou `restore` para revivê-la",
21        )
22        .replace("memory", "memória");
23    format!("duplicata detectada: {translated}")
24}
25
26/// Localized `conflict` message wrapping `msg`.
27pub fn conflict(msg: &str) -> String {
28    let translated = msg
29        .replace("optimistic lock conflict", "conflito de lock otimista")
30        .replace("but current is", "mas atual é")
31        .replace(
32            "was modified by another process",
33            "foi modificada por outro processo",
34        );
35    format!("conflito: {translated}")
36}
37
38/// Localized `not_found` message wrapping `msg`.
39pub fn not_found(msg: &str) -> String {
40    // G55 T3: add replacements for the read.rs format produced by the
41    // T1 fix: `memory not found: name='X' in namespace 'Y'`.
42    // The existing chain did not catch ` in namespace '` when broken
43    // by the name label, leaving a bilingual hybrid. New patterns
44    // must run BEFORE the catch-all `memory` → `memória` to avoid
45    // being shadowed.
46    // GAP-SG-143: the chain now covers the whole
47    // `crate::i18n::validation::messages_not_found` catalog. Rules are ordered
48    // from most specific to most generic — a generic rule that runs early
49    // shadows every specific rule after it, which is how the pre-G55 hybrid
50    // was produced.
51    //
52    // Grammatical gender is decided by ONE structural cue: the catalog quotes
53    // the subject's NAME (`memory 'x'`, `entity 'y'`) and leaves ids bare
54    // (`chunk 3`, `entity id=9`). A quoted subject takes the feminine
55    // agreement that `memória`/`entidade` require; a bare id falls to the
56    // masculine default. Plain `str::replace` cannot see the noun across a
57    // varying id, so a bare-id line whose noun is feminine keeps the masculine
58    // form. That is a known agreement imperfection, deliberately preferred
59    // over leaving English in the output.
60    let translated = msg
61        // -- endpoint-qualified entities, before the generic `entity` rule
62        .replace("source entity '", "entidade de origem '")
63        .replace("target entity '", "entidade de destino '")
64        // -- multi-word phrases, before any single-word rule
65        .replace("memory not found:", "memória não encontrada:")
66        .replace(
67            "exists but belongs to namespace",
68            "existe mas pertence ao namespace",
69        )
70        .replace("' not found in namespace", "' não encontrada no namespace")
71        .replace("not found in namespace", "não encontrado no namespace")
72        .replace(
73            "not found in pending_memories",
74            "não encontrado em pending_memories",
75        )
76        .replace("not found for memory", "não encontrada para memória")
77        .replace("does not exist in namespace", "não existe no namespace")
78        .replace("memory or entity", "memória ou entidade")
79        .replace("Did you mean:", "Você quis dizer:")
80        .replace(
81            "Re-run with --fuzzy to auto-resolve a clear match, or pass the canonical name.",
82            "Repita com --fuzzy para resolver automaticamente uma correspondência clara, \
83             ou informe o nome canônico.",
84        )
85        .replace(
86            "is not held (no file at",
87            "não está retido (nenhum arquivo em",
88        )
89        .replace("no key with fingerprint", "nenhuma chave com fingerprint")
90        .replace("name='", "nome='")
91        // -- nouns
92        .replace("relationship", "relacionamento")
93        .replace("edge '", "aresta '")
94        .replace("memory", "memória")
95        .replace("entity", "entidade")
96        // -- trailing `not found`, quoted subject first (feminine agreement)
97        .replace("' not found", "' não encontrada")
98        .replace("not found", "não encontrado")
99        // -- residual connectors
100        .replace(", not '", ", e não '")
101        .replace(" in namespace '", " no namespace '")
102        .replace("version", "versão")
103        .replace("soft-deleted", "excluída temporariamente");
104    format!("não encontrado: {translated}")
105}
106
107// G55 S2 (v1.0.80): structured variant helpers. They synthesize the
108// canonical English message and feed it through the `not_found`
109// replace-chain so the pt-BR translation stays in one place.
110/// Localized message for `memory_not_found`.
111pub fn memory_not_found(name: &str, namespace: &str) -> String {
112    not_found(&format!(
113        "memory not found: name='{name}' in namespace '{namespace}'"
114    ))
115}
116
117/// Localized message for `memory_not_found_by_id`.
118pub fn memory_not_found_by_id(id: i64) -> String {
119    not_found(&format!("memory not found: id={id}"))
120}
121
122// GAP-SG-78: transitory entity absence (materialized on a later enrich
123// pass). Own pt-BR string, distinct from the terminal not-found chain.
124/// Localized message for `entity_not_yet_materialized`.
125pub fn entity_not_yet_materialized(name: &str, namespace: &str) -> String {
126    format!("entidade '{name}' ainda não materializada no namespace '{namespace}'")
127}
128
129/// Localized message for `namespace_error`.
130pub fn namespace_error(msg: &str) -> String {
131    format!("namespace não resolvido: {msg}")
132}
133
134/// Localized message for `limit_exceeded`.
135pub fn limit_exceeded(msg: &str) -> String {
136    let translated = msg
137        .replace("exceeds limit of", "excede limite de")
138        .replace("body exceeds", "corpo excede")
139        .replace("entities exceed limit", "entidades excedem limite")
140        .replace(
141            "relationships exceed limit",
142            "relacionamentos excedem limite",
143        );
144    format!("limite excedido: {translated}")
145}
146
147// v1.1.1 (P11): typed ceiling variants. Own pt-BR strings mirroring
148// the English `#[error]` text of `BodyTooLarge`/`TooManyChunks`,
149// naming the constant so the operator knows WHICH cap fired.
150/// Localized message for `body_too_large`.
151pub fn body_too_large(bytes: u64, limit: u64) -> String {
152    format!(
153        "limite excedido: corpo tem {bytes} bytes, acima do teto de {limit} bytes \
154         (MAX_MEMORY_BODY_LEN); divida o conteúdo em múltiplas memórias"
155    )
156}
157
158/// Too many chunks.
159pub fn too_many_chunks(chunks: usize, limit: usize) -> String {
160    format!(
161        "limite excedido: documento produz {chunks} chunks, acima do teto de {limit} \
162         chunks (REMEMBER_MAX_SAFE_MULTI_CHUNKS); divida o documento antes da escrita"
163    )
164}
165
166// v1.1.2 (Gap 2): third typed payload ceiling — token cap, mirroring
167// the English `#[error]` text of `TooManyTokens`.
168/// Too many tokens.
169pub fn too_many_tokens(tokens: u64, limit: u64) -> String {
170    format!(
171        "limite excedido: corpo tem {tokens} tokens (estimado), acima do teto de \
172         {limit} tokens (EMBEDDING_REQUEST_MAX_TOKENS); divida o conteúdo em \
173         múltiplas memórias"
174    )
175}
176
177/// Database.
178pub fn database(err: &str) -> String {
179    format!("erro de banco de dados: {err}")
180}
181
182/// Embedding.
183pub fn embedding(msg: &str) -> String {
184    format!("erro de embedding: {msg}")
185}
186
187/// VEC extension.
188pub fn vec_extension(msg: &str) -> String {
189    format!("extensão sqlite-vec falhou: {msg}")
190}
191
192/// Provider error.
193pub fn provider_error(code: &str, message: &str) -> String {
194    format!("erro do provedor (código {code}): {message}")
195}
196
197/// DB busy.
198pub fn db_busy(msg: &str) -> String {
199    format!("banco ocupado: {msg}")
200}
201
202/// Batch partial failure.
203pub fn batch_partial_failure(total: usize, failed: usize) -> String {
204    format!("falha parcial em batch: {failed} de {total} itens falharam")
205}
206
207/// IO.
208pub fn io(err: &str) -> String {
209    format!("erro de I/O: {err}")
210}
211
212/// Internal.
213pub fn internal(err: &str) -> String {
214    format!("erro interno: {err}")
215}
216
217/// JSON.
218pub fn json(err: &str) -> String {
219    format!("erro de JSON: {err}")
220}
221
222/// Lock busy.
223pub fn lock_busy(msg: &str) -> String {
224    format!("lock ocupado: {msg}")
225}
226
227/// All slots full.
228pub fn all_slots_full(max: usize, waited_secs: u64) -> String {
229    format!(
230        "todos os {max} slots de concorrência ocupados após aguardar {waited_secs}s \
231         (exit 75); use --max-concurrency ou aguarde outras invocações terminarem"
232    )
233}
234
235/// Job singleton locked.
236pub fn job_singleton_locked(job_type: &str, namespace: &str) -> String {
237    format!(
238        "job {job_type} para o namespace '{namespace}' já está em execução (exit 75); \
239         aguarde a conclusão ou passe --wait-job-singleton <SEGUNDOS>"
240    )
241}
242
243/// Embedding singleton locked.
244pub fn embedding_singleton_locked(namespace: &str) -> String {
245    format!(
246        "singleton de embedding para o namespace '{namespace}' já está retido (exit 75); \
247         outra CLI está chamando o LLM neste banco; passe --wait-embed-singleton <SEGUNDOS> para aguardar"
248    )
249}
250
251/// Low memory.
252pub fn low_memory(available_mb: u64, required_mb: u64) -> String {
253    format!(
254        "memória disponível ({available_mb}MB) abaixo do mínimo requerido ({required_mb}MB) \
255         para carregar o modelo; aborte outras cargas ou use --skip-memory-guard (exit 77)"
256    )
257}
258
259/// Shutdown.
260pub fn shutdown(signal: &str) -> String {
261    format!("sinal de desligamento recebido: {signal}; operação cancelada pelo usuário (exit 19)")
262}
263
264// `preflight_failed` lived here until v1.2.3. It localised the exit-16 MCP
265// preflight error for a `src/spawn/` module and an `AppError` variant that no
266// longer exist, and it advertised `config set spawn.skip_preflight=1` — a key
267// that was itself removed in the same change. A message nothing can emit is a
268// translated promise about a code path the product no longer has.
269/// Localized message for `binary_not_found`.
270pub fn binary_not_found(name: &str) -> String {
271    format!("binário não encontrado: {name} — instale e adicione ao PATH")
272}
273
274/// Rate limited.
275pub fn rate_limited(detail: &str) -> String {
276    format!("taxa de requisição excedida: {detail}")
277}
278
279/// Timeout.
280pub fn timeout(operation: &str, secs: u64) -> String {
281    format!("timeout após {secs}s: {operation}")
282}