Skip to main content

sqlite_graphrag/i18n/validation/
messages_naming.rs

1//! Messages about NAMES, namespaces and filesystem paths (GAP-SG-146).
2//!
3//! The kebab-case contract for memory and entity names, namespace shape, and
4//! the path guards that keep writes inside their intended root.
5
6use crate::i18n::{current, Language};
7
8/// Localized message for `name_length`.
9pub fn name_length(max: usize) -> String {
10    match current() {
11        Language::English => format!("name must be 1-{max} chars"),
12        Language::Portuguese => format!("nome deve ter entre 1 e {max} caracteres"),
13    }
14}
15
16/// Localized message for `name_kebab`.
17pub fn name_kebab(nome: &str) -> String {
18    match current() {
19        Language::English => {
20            format!("name must be kebab-case slug (lowercase letters, digits, hyphens): '{nome}'")
21        }
22        Language::Portuguese => {
23            format!("nome deve estar em kebab-case (minúsculas, dígitos, hífens): '{nome}'")
24        }
25    }
26}
27
28/// Name normalized to empty (only hyphens/underscores/spaces).
29pub fn name_empty_after_normalization() -> String {
30    match current() {
31        Language::English => {
32            "name cannot be empty after normalization (input was blank or contained only hyphens/underscores/spaces)"
33                .to_string()
34        }
35        Language::Portuguese => {
36            "nome não pode ficar vazio após normalização (entrada em branco ou só com hífens/sublinhados/espaços)"
37                .to_string()
38        }
39    }
40}
41
42/// Empty name rejected.
43pub fn name_must_not_be_empty() -> String {
44    match current() {
45        Language::English => "name must not be empty".to_string(),
46        Language::Portuguese => "nome não pode ser vazio".to_string(),
47    }
48}
49
50/// `--name-prefix` must be kebab-case starting with a letter.
51pub fn name_prefix_kebab(prefix: &str) -> String {
52    match current() {
53        Language::English => format!(
54            "--name-prefix '{prefix}' must start with a lowercase letter and contain              only lowercase letters, digits and hyphens (kebab-case)"
55        ),
56        Language::Portuguese => format!(
57            "--name-prefix '{prefix}' deve começar com letra minúscula e conter              apenas letras minúsculas, dígitos e hífens (kebab-case)"
58        ),
59    }
60}
61
62/// Localized message for `reserved_name`.
63pub fn reserved_name() -> String {
64    match current() {
65        Language::English => {
66            "names and namespaces starting with __ are reserved for internal use".to_string()
67        }
68        Language::Portuguese => {
69            "nomes e namespaces iniciados com __ são reservados para uso interno".to_string()
70        }
71    }
72}
73
74/// Localized message for `new_name_kebab`.
75pub fn new_name_kebab(nome: &str) -> String {
76    match current() {
77        Language::English => format!(
78            "new-name must be kebab-case slug (lowercase letters, digits, hyphens): '{nome}'"
79        ),
80        Language::Portuguese => {
81            format!("novo nome deve estar em kebab-case (minúsculas, dígitos, hífens): '{nome}'")
82        }
83    }
84}
85
86/// Localized message for `new_name_length`.
87pub fn new_name_length(max: usize) -> String {
88    match current() {
89        Language::English => format!("new-name must be 1-{max} chars"),
90        Language::Portuguese => format!("novo nome deve ter entre 1 e {max} caracteres"),
91    }
92}
93
94/// `--strict-name` refused auto-normalization.
95pub fn strict_name_not_canonical(original: &str, normalized: &str) -> String {
96    match current() {
97        Language::English => format!(
98            "--strict-name is set but '{original}' is not canonical kebab-case; \
99             re-run with --name '{normalized}' (or drop --strict-name to allow auto-normalization)"
100        ),
101        Language::Portuguese => format!(
102            "--strict-name está ativo mas '{original}' não é kebab-case canônico; \
103             reexecute com --name '{normalized}' (ou remova --strict-name para permitir auto-normalização)"
104        ),
105    }
106}
107
108/// Child name derived from parent exceeds MAX_MEMORY_NAME_LEN.
109pub fn child_name_exceeds_max(child: &str, parent: &str, max: usize) -> String {
110    match current() {
111        Language::English => format!(
112            "child name '{child}' derived from '{parent}' exceeds MAX_MEMORY_NAME_LEN ({max})"
113        ),
114        Language::Portuguese => format!(
115            "nome filho '{child}' derivado de '{parent}' excede MAX_MEMORY_NAME_LEN ({max})"
116        ),
117    }
118}
119
120/// Child name is not kebab-case ASCII.
121pub fn child_name_not_kebab(child: &str) -> String {
122    match current() {
123        Language::English => {
124            format!("child name '{child}' is not kebab-case ASCII; rename the parent memory")
125        }
126        Language::Portuguese => {
127            format!("nome filho '{child}' não é kebab-case ASCII; renomeie a memória pai")
128        }
129    }
130}
131
132/// Localized message for `namespace_format`.
133pub fn namespace_format() -> String {
134    match current() {
135        Language::English => "namespace must be alphanumeric + hyphens/underscores".to_string(),
136        Language::Portuguese => {
137            "namespace deve ser alfanumérico com hífens/sublinhados".to_string()
138        }
139    }
140}
141
142/// Localized message for `namespace_length`.
143pub fn namespace_length() -> String {
144    match current() {
145        Language::English => "namespace must be 1-80 chars".to_string(),
146        Language::Portuguese => "namespace deve ter entre 1 e 80 caracteres".to_string(),
147    }
148}
149
150/// Short ALL_CAPS entity name rejected as NER noise.
151pub fn entity_name_all_caps_noise(name: &str) -> String {
152    match current() {
153        Language::English => format!(
154            "entity name '{name}' rejected: short ALL_CAPS names are typically NER noise"
155        ),
156        Language::Portuguese => format!(
157            "nome de entidade '{name}' rejeitado: nomes curtos em CAIXA ALTA são tipicamente ruído de NER"
158        ),
159    }
160}
161
162/// Entity rename target already exists.
163pub fn entity_name_already_exists(name: &str, namespace: &str) -> String {
164    match current() {
165        Language::English => {
166            format!("entity with name '{name}' already exists in namespace '{namespace}'")
167        }
168        Language::Portuguese => {
169            format!("entidade com nome '{name}' já existe no namespace '{namespace}'")
170        }
171    }
172}
173
174/// Entity name normalizes too short.
175pub fn entity_name_normalizes_too_short(original: &str, normalized: &str) -> String {
176    match current() {
177        Language::English => format!(
178            "entity name '{original}' normalizes to '{normalized}' which is too short (minimum 2 characters)"
179        ),
180        Language::Portuguese => format!(
181            "nome de entidade '{original}' normaliza para '{normalized}' que é curto demais (mínimo 2 caracteres)"
182        ),
183    }
184}
185
186/// Purely numeric entity name rejected.
187pub fn entity_name_purely_numeric(name: &str) -> String {
188    match current() {
189        Language::English => format!(
190            "entity name '{name}' rejected: purely numeric names look like entity IDs — \
191             use --from-id/--to-id for ID-based linking, or pass a non-numeric name"
192        ),
193        Language::Portuguese => format!(
194            "nome de entidade '{name}' rejeitado: nomes puramente numéricos parecem IDs — \
195             use --from-id/--to-id para link por ID, ou passe um nome não numérico"
196        ),
197    }
198}
199
200/// Entity name too short.
201pub fn entity_name_too_short(name: &str) -> String {
202    match current() {
203        Language::English => format!("entity name '{name}' must be at least 2 characters"),
204        Language::Portuguese => {
205            format!("nome de entidade '{name}' deve ter pelo menos 2 caracteres")
206        }
207    }
208}
209
210/// Too many name collisions while generating a unique memory name.
211pub fn too_many_name_collisions(base: &str, max: usize) -> String {
212    match current() {
213        Language::English => format!(
214            "too many name collisions for base '{base}' (>{max}); rename source files to disambiguate"
215        ),
216        Language::Portuguese => format!(
217            "muitas colisões de nome para a base '{base}' (>{max}); renomeie os arquivos de origem para desambiguar"
218        ),
219    }
220}
221
222/// Path has no valid parent component.
223pub fn path_no_valid_parent(path: &str) -> String {
224    match current() {
225        Language::English => format!("path '{path}' has no valid parent component"),
226        Language::Portuguese => format!("caminho '{path}' não tem componente pai válido"),
227    }
228}
229
230/// Localized message for `path_traversal`.
231pub fn path_traversal(p: &str) -> String {
232    match current() {
233        Language::English => format!("path traversal rejected: {p}"),
234        Language::Portuguese => format!("traversal de caminho rejeitado: {p}"),
235    }
236}
237
238/// Directory path does not exist.
239pub fn directory_not_found(path: &str) -> String {
240    match current() {
241        Language::English => format!("directory not found: {path}"),
242        Language::Portuguese => format!("diretório não encontrado: {path}"),
243    }
244}
245
246/// Path exists but is not a directory.
247pub fn not_a_directory(path: &str) -> String {
248    match current() {
249        Language::English => format!("path is not a directory: {path}"),
250        Language::Portuguese => format!("caminho não é um diretório: {path}"),
251    }
252}