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