diff --git a/README.md b/README.md
index 042fcaf759..e3dd80936e 100644
--- a/README.md
+++ b/README.md
@@ -403,7 +403,7 @@ claude mcp add-server omniroute --type http --url http://localhost:20128/api/mcp
-> **Why use many token when few token do trick?** Every request passes through OmniRoute's compression pipeline **transparently** — no client changes. It stacks ideas from [RTK](https://github.com/rtk-ai/rtk) and [Caveman](https://github.com/JuliusBrussee/caveman) (⭐ 51K+).
+> **Why use many token when few token do trick?** Every request passes through OmniRoute's compression pipeline **transparently** — no client changes. It stacks ideas from [RTK](https://github.com/rtk-ai/rtk), [Caveman](https://github.com/JuliusBrussee/caveman) (⭐ 51K+), and [Troglodita](https://github.com/leninejunior/troglodita) (PT-BR).
| Mode | Savings | Best for |
| ------------------------------ | ---------- | --------------------------- |
@@ -422,6 +422,14 @@ claude mcp add-server omniroute --type http --url http://localhost:20128/api/mcp
>
> **Same answer. 72% fewer tokens. Zero accuracy loss.** ✅
+**PT-BR example — [Troglodita](https://github.com/leninejunior/troglodita) mode:**
+
+> **Antes (42 tokens):** _"O problema é que o componente está re-renderizando porque uma nova referência de objeto está sendo criada em cada ciclo de renderização. Eu recomendaria usar useMemo."_
+>
+> **Depois (12 tokens):** _"Re-render: ref nova cada ciclo (objeto inline recriado). Usar `useMemo`."_
+>
+> **Mesma resposta. ~70% menos tokens. Precisão técnica intacta.** ✅
+
### 📖 How it works — pipeline, architecture & savings math
@@ -938,6 +946,8 @@ Special thanks to **[Caveman](https://github.com/JuliusBrussee/caveman)** by **[
Special thanks to **[RTK - Rust Token Killer](https://github.com/rtk-ai/rtk)** by **[RTK AI](https://github.com/rtk-ai)** — the high-performance command-output compression project whose terminal, build, test, git, and tool-output filtering model inspired OmniRoute's RTK engine, JSON filter DSL, raw-output recovery, and stacked RTK → Caveman compression pipeline.
+Special thanks to **[Troglodita](https://github.com/leninejunior/troglodita)** by **[Lenine Júnior](https://github.com/leninejunior)** — the PT-BR token compression project ("por que gastar muitos tokens quando poucos resolve?") whose Portuguese-native rules power OmniRoute's pt-BR language pack: pleonasm reduction, filler removal tuned for Brazilian Portuguese grammar, and technical abbreviations for the dev BR community.
+
## 📄 License
diff --git a/docs/compression/COMPRESSION_LANGUAGE_PACKS.md b/docs/compression/COMPRESSION_LANGUAGE_PACKS.md
index bfa445a27b..1a0e794ed6 100644
--- a/docs/compression/COMPRESSION_LANGUAGE_PACKS.md
+++ b/docs/compression/COMPRESSION_LANGUAGE_PACKS.md
@@ -24,12 +24,14 @@ Current shipped packs (verified against `rules/` directory contents):
| ------------------- | -------------- | --------------------------------------------------- |
| English | `rules/en/` | `context`, `dedup`, `filler`, `structural`, `ultra` |
| Spanish | `rules/es/` | `context`, `dedup`, `filler`, `structural`, `ultra` |
-| Portuguese (Brazil) | `rules/pt-BR/` | `context`, `filler`, `structural` |
+| Portuguese (Brazil) | `rules/pt-BR/` | `context`, `dedup`, `filler`, `structural`, `ultra` |
| German | `rules/de/` | `context`, `filler`, `structural` |
| French | `rules/fr/` | `context`, `filler`, `structural` |
| Japanese | `rules/ja/` | `context`, `filler`, `structural` |
-> **Parity note:** `en` and `es` packs have the full 5 categories; `pt-BR`, `de`, `fr`, `ja` ship 3 categories. The missing `dedup` and `ultra` categories silently fall back to the English built-ins. Contributions welcome to add `dedup.json` and `ultra.json` for the smaller packs.
+> **Parity note:** `en`, `es`, and `pt-BR` packs have the full 5 categories; `de`, `fr`, `ja` ship 3 categories. The missing `dedup` and `ultra` categories silently fall back to the English built-ins. Contributions welcome to add `dedup.json` and `ultra.json` for the smaller packs.
+>
+> The `pt-BR` pack is based on **[Troglodita](https://github.com/leninejunior/troglodita)** by Lenine Júnior — a compression system designed from scratch for Brazilian Portuguese grammar (pleonasm reduction, PT-BR filler removal, technical abbreviations for the dev BR community).
>
> The canonical category list and per-category schema live in [`open-sse/services/compression/rules/_schema.json`](../../open-sse/services/compression/rules/_schema.json) (JSON Schema draft 2020-12).
diff --git a/open-sse/services/compression/rules/pt-BR/context.json b/open-sse/services/compression/rules/pt-BR/context.json
index c0f8ed6538..90ed2d58f0 100644
--- a/open-sse/services/compression/rules/pt-BR/context.json
+++ b/open-sse/services/compression/rules/pt-BR/context.json
@@ -4,35 +4,66 @@
"rules": [
{
"name": "pt_context_setup",
- "pattern": "\\b(?:segue o codigo|segue o código|abaixo esta o codigo|abaixo está o código|este e o codigo|este é o código)\\b\\s*[:.]?\\s*",
+ "pattern": "\\b(?:segue o codigo|segue o código|abaixo esta o codigo|abaixo está o código|este e o codigo|este é o código|aqui está o código)\\b\\s*[:.]?\\s*",
"replacement": "Código:",
"context": "user",
"category": "context",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Code introduction framing → direct label"
},
{
"name": "pt_intent",
- "pattern": "\\b(?:o que eu quero fazer e|o que eu quero fazer é|meu objetivo e|meu objetivo é|a ideia e|a ideia é)\\b\\s*",
- "replacement": "Objetivo:",
+ "pattern": "\\b(?:o que eu quero fazer e|o que eu quero fazer é|meu objetivo e|meu objetivo é|a ideia e|a ideia é|o que preciso é)\\b\\s*",
+ "replacement": "Objetivo: ",
"context": "user",
"category": "context",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Intent declaration → label"
},
{
"name": "pt_question_directive",
- "pattern": "\\b(?:voce pode explicar por que|você pode explicar por que|pode mostrar como|poderia mostrar como)\\b\\s*",
+ "pattern": "\\b(?:voce pode explicar por que|você pode explicar por que|pode mostrar como|poderia mostrar como|me explica como|me explica por que)\\b\\s*",
"replacement": "Explique ",
"context": "user",
"category": "context",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Question framing → direct imperative"
},
{
"name": "pt_background",
- "pattern": "\\b(?:como voce sabe|como você sabe|como falamos antes|como mencionei antes)\\b[,.]?\\s*",
+ "pattern": "\\b(?:como voce sabe|como você sabe|como falamos antes|como mencionei antes|como já disse|conforme mencionado)\\b[,.]?\\s*",
"replacement": "",
"context": "all",
"category": "context",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Background references — context is already in conversation"
+ },
+ {
+ "name": "pt_error_framing",
+ "pattern": "\\b(?:o erro que voce está vendo|o erro que você está vendo|esse erro acontece porque|esse erro ocorre porque|o motivo desse erro é)\\b\\s*",
+ "replacement": "Erro: ",
+ "context": "assistant",
+ "category": "context",
+ "minIntensity": "lite",
+ "description": "Error explanation padding → diagnostic label"
+ },
+ {
+ "name": "pt_solution_framing",
+ "pattern": "\\b(?:para resolver isso|para corrigir isso|a solução é|a correção é|o que voce precisa fazer é|o que você precisa fazer é)\\b[,:]?\\s*",
+ "replacement": "Resolver: ",
+ "context": "assistant",
+ "category": "context",
+ "minIntensity": "full",
+ "description": "Solution introduction → action label"
+ },
+ {
+ "name": "pt_step_framing",
+ "pattern": "\\b(?:primeiro voce precisa|primeiro você precisa|o primeiro passo é|em seguida voce deve|em seguida você deve)\\b\\s*",
+ "replacement": "1. ",
+ "context": "assistant",
+ "category": "context",
+ "minIntensity": "full",
+ "description": "Step-by-step padding → numbered list"
}
]
}
diff --git a/open-sse/services/compression/rules/pt-BR/dedup.json b/open-sse/services/compression/rules/pt-BR/dedup.json
new file mode 100644
index 0000000000..fa1c0d08aa
--- /dev/null
+++ b/open-sse/services/compression/rules/pt-BR/dedup.json
@@ -0,0 +1,51 @@
+{
+ "language": "pt-BR",
+ "category": "dedup",
+ "rules": [
+ {
+ "name": "pt_repeated_context",
+ "pattern": "\\b(?:como falamos antes|como mencionamos|como vimos anteriormente|conforme discutido|como já expliquei)\\b[,.]?\\s*",
+ "replacement": "Ver acima. ",
+ "context": "all",
+ "category": "dedup",
+ "minIntensity": "lite",
+ "description": "References to earlier discussion"
+ },
+ {
+ "name": "pt_repeated_question",
+ "pattern": "\\b(?:mesma pergunta de antes|já perguntei isso|é a mesma dúvida|repito a pergunta)\\b[,.]?\\s*",
+ "replacement": "[mesma pergunta] ",
+ "context": "user",
+ "category": "dedup",
+ "minIntensity": "lite",
+ "description": "Repeated question markers"
+ },
+ {
+ "name": "pt_reestablished_context",
+ "pattern": "\\b(?:voltando ao código acima|voltando ao que falamos|retomando o assunto|voltando ao ponto)\\b[,.]?\\s*",
+ "replacement": "Re: ",
+ "context": "all",
+ "category": "dedup",
+ "minIntensity": "lite",
+ "description": "Context re-establishment"
+ },
+ {
+ "name": "pt_summary",
+ "pattern": "\\b(?:resumindo o que discutimos|pra resumir|em resumo|resumidamente|recapitulando)\\b[,.]?\\s*",
+ "replacement": "Resumo: ",
+ "context": "assistant",
+ "category": "dedup",
+ "minIntensity": "lite",
+ "description": "Summary framing"
+ },
+ {
+ "name": "pt_reiteration",
+ "pattern": "\\b(?:como eu disse|como mencionei|reitero que|repito que|novamente)\\b[,.]?\\s*",
+ "replacement": "",
+ "context": "all",
+ "category": "dedup",
+ "minIntensity": "lite",
+ "description": "Self-reiteration markers — content already in context"
+ }
+ ]
+}
diff --git a/open-sse/services/compression/rules/pt-BR/filler.json b/open-sse/services/compression/rules/pt-BR/filler.json
index a9ce881656..6763e9bf6b 100644
--- a/open-sse/services/compression/rules/pt-BR/filler.json
+++ b/open-sse/services/compression/rules/pt-BR/filler.json
@@ -8,63 +8,144 @@
"replacement": "",
"context": "all",
"category": "filler",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Formal request framing — unnecessary in direct communication"
},
{
"name": "pt_pleasantries",
- "pattern": "\\b(?:ola|olá|oi|bom dia|boa tarde|boa noite|obrigado|obrigada|valeu)\\b[,.!?\\s]*",
+ "pattern": "\\b(?:ola|olá|oi|bom dia|boa tarde|boa noite|obrigado|obrigada|valeu|tchau|até mais)\\b[,.!?\\s]*",
"replacement": "",
"context": "all",
"category": "filler",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Greetings and farewells — zero information content"
+ },
+ {
+ "name": "pt_amenities",
+ "pattern": "\\b(?:claro|com certeza|fico feliz em ajudar|seria um prazer|sem problemas|fique à vontade|fique a vontade|não se preocupe|nao se preocupe)\\b[!,.\\s]*",
+ "replacement": "",
+ "context": "assistant",
+ "category": "filler",
+ "minIntensity": "lite",
+ "description": "Assistant amenities that add no technical value"
},
{
"name": "pt_hedging",
- "pattern": "\\b(?:eu acho que|eu acredito que|parece que|talvez|provavelmente|possivelmente)\\b\\s*",
+ "pattern": "\\b(?:eu acho que|eu acredito que|parece que|talvez|provavelmente|possivelmente|aparentemente)\\b\\s*",
"replacement": "",
"context": "all",
"category": "filler",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Uncertainty hedging — if uncertain, state the fact directly"
+ },
+ {
+ "name": "pt_hesitations",
+ "pattern": "\\b(?:talvez valha a pena|seria interessante considerar|pode ser que|não sei se|a depender do caso)\\b\\s*",
+ "replacement": "",
+ "context": "all",
+ "category": "filler",
+ "minIntensity": "lite",
+ "description": "Extended hesitation phrases common in PT-BR technical writing"
},
{
"name": "pt_filler_adverbs",
- "pattern": "\\b(?:basicamente|essencialmente|na verdade|literalmente|simplesmente|atualmente)\\b\\s*",
+ "pattern": "\\b(?:basicamente|essencialmente|na verdade|literalmente|simplesmente|atualmente|obviamente|claramente|naturalmente|certamente|definitivamente)\\b\\s*",
"replacement": "",
"context": "all",
"category": "filler",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Filler adverbs — 'muletas' that pad without adding meaning"
+ },
+ {
+ "name": "pt_emphasis_fillers",
+ "pattern": "\\b(?:vale ressaltar|vale mencionar|vale notar|vale lembrar|é importante notar que|é importante mencionar que|convém destacar que)\\b\\s*",
+ "replacement": "",
+ "context": "all",
+ "category": "filler",
+ "minIntensity": "lite",
+ "description": "Emphasis markers — if it's worth noting, just note it"
},
{
"name": "pt_self_reference",
- "pattern": "^(?:eu estou tentando|estou tentando|eu quero|eu preciso|gostaria de)\\b\\s*",
+ "pattern": "^(?:eu estou tentando|estou tentando|eu quero|eu preciso|gostaria de|estou precisando)\\b\\s*",
"replacement": "",
"context": "user",
"category": "filler",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "User self-reference at start of sentence"
},
{
"name": "pt_verbose_request",
- "pattern": "\\b(?:voce poderia me explicar|você poderia me explicar|poderia detalhar|gostaria que voce explicasse|gostaria que você explicasse)\\b\\s*",
+ "pattern": "\\b(?:voce poderia me explicar|você poderia me explicar|poderia detalhar|gostaria que voce explicasse|gostaria que você explicasse|me explica)\\b\\s*",
"replacement": "Explique ",
"context": "user",
"category": "filler",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Verbose request phrasing → direct imperative"
},
{
"name": "pt_qualifiers",
- "pattern": "\\b(?:um pouco|meio que|tipo assim|de certa forma|mais ou menos)\\b\\s*",
+ "pattern": "\\b(?:um pouco|meio que|tipo assim|de certa forma|mais ou menos|de alguma forma|de alguma maneira)\\b\\s*",
"replacement": "",
"context": "all",
"category": "filler",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Vague qualifiers that weaken statements"
},
{
"name": "pt_softeners",
- "pattern": "\\b(?:se possivel|se possível|quando puder|sem pressa|so queria|só queria)\\b[,.!?\\s]*",
+ "pattern": "\\b(?:se possivel|se possível|quando puder|sem pressa|so queria|só queria|se não for incomodo|se não for incômodo)\\b[,.!?\\s]*",
"replacement": "",
"context": "all",
"category": "filler",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Request softeners — unnecessary in AI interaction"
+ },
+ {
+ "name": "pt_redundancies",
+ "pattern": "\\b(?:subir pra cima|descer pra baixo|voltar atrás|a razão é porque|o motivo é porque|entrar pra dentro|sair pra fora)\\b",
+ "replacement": "",
+ "replacementMap": {
+ "subir pra cima": "subir",
+ "descer pra baixo": "descer",
+ "voltar atrás": "voltar",
+ "a razão é porque": "porque",
+ "o motivo é porque": "porque",
+ "entrar pra dentro": "entrar",
+ "sair pra fora": "sair"
+ },
+ "flags": "gi",
+ "context": "all",
+ "category": "filler",
+ "minIntensity": "lite",
+ "description": "Pleonasms — redundant phrases native to PT-BR speech"
+ },
+ {
+ "name": "pt_linking_verbs",
+ "pattern": "\\b(?:está sendo|foi feito|tem que ser|precisa ser|deve ser feito|foi realizado)\\b\\s*",
+ "replacement": "",
+ "replacementMap": {
+ "está sendo": "é",
+ "foi feito": "",
+ "tem que ser": "deve",
+ "precisa ser": "deve",
+ "deve ser feito": "fazer",
+ "foi realizado": ""
+ },
+ "flags": "gi",
+ "context": "all",
+ "category": "filler",
+ "minIntensity": "full",
+ "description": "Verbose linking verb constructions → compact form"
+ },
+ {
+ "name": "pt_explanation_padding",
+ "pattern": "\\b(?:o que acontece é que|o que está acontecendo é que|o problema é que|a questão é que|o ponto é que)\\b\\s*",
+ "replacement": "",
+ "context": "assistant",
+ "category": "filler",
+ "minIntensity": "full",
+ "description": "Explanation padding before the actual content"
}
]
}
diff --git a/open-sse/services/compression/rules/pt-BR/structural.json b/open-sse/services/compression/rules/pt-BR/structural.json
index 8144ef2b6e..7209024764 100644
--- a/open-sse/services/compression/rules/pt-BR/structural.json
+++ b/open-sse/services/compression/rules/pt-BR/structural.json
@@ -4,27 +4,75 @@
"rules": [
{
"name": "pt_purpose",
- "pattern": "\\b(?:a fim de|com o objetivo de|para poder)\\b\\s*",
+ "pattern": "\\b(?:a fim de|com o objetivo de|para poder|com a finalidade de|com o intuito de)\\b\\s*",
"replacement": "para ",
"context": "all",
"category": "structural",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Verbose purpose connectors → 'para'"
},
{
"name": "pt_connectors",
- "pattern": "\\b(?:alem disso|além disso|adicionalmente|outrossim)\\b\\s*",
+ "pattern": "\\b(?:alem disso|além disso|adicionalmente|outrossim|não obstante|por outro lado)\\b[,]?\\s*",
"replacement": "também ",
"context": "all",
"category": "structural",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Verbose additive connectors"
},
{
"name": "pt_emphasis",
- "pattern": "\\b(?:muito|realmente|extremamente|bastante)\\s+(?=[a-záéíóúâêôãõç])",
+ "pattern": "\\b(?:muito|realmente|extremamente|bastante|totalmente|completamente|absolutamente)\\s+(?=[a-záéíóúâêôãõç])",
"replacement": "",
"context": "all",
"category": "structural",
- "minIntensity": "lite"
+ "minIntensity": "lite",
+ "description": "Intensity adverbs before adjectives — rarely add precision"
+ },
+ {
+ "name": "pt_passive_voice",
+ "pattern": "\\b(?:é necessário que|é preciso que|é importante que|é fundamental que|é essencial que)\\b\\s*",
+ "replacement": "Deve ",
+ "context": "all",
+ "category": "structural",
+ "minIntensity": "full",
+ "description": "Impersonal passive constructions → direct imperative"
+ },
+ {
+ "name": "pt_causality_verbose",
+ "pattern": "\\b(?:isso acontece porque|isso ocorre porque|isso se deve ao fato de que|a causa disso é que)\\b\\s*",
+ "replacement": "Causa: ",
+ "context": "assistant",
+ "category": "structural",
+ "minIntensity": "full",
+ "description": "Verbose causality explanation → diagnostic label"
+ },
+ {
+ "name": "pt_consequence",
+ "pattern": "\\b(?:como consequência|como resultado|por conta disso|em decorrência disso|por causa disso)\\b[,]?\\s*",
+ "replacement": "→ ",
+ "context": "all",
+ "category": "structural",
+ "minIntensity": "full",
+ "description": "Consequence connectors → arrow notation (troglodita style)"
+ },
+ {
+ "name": "pt_comparison_verbose",
+ "pattern": "\\b(?:em comparação com|quando comparado com|se compararmos com|diferente de)\\b\\s*",
+ "replacement": "vs ",
+ "context": "all",
+ "category": "structural",
+ "minIntensity": "full",
+ "description": "Verbose comparisons → compact 'vs'"
+ },
+ {
+ "name": "pt_conclusion",
+ "pattern": "\\b(?:sendo assim|portanto|dessa forma|desse modo|consequentemente|em suma|resumindo)\\b[,]?\\s*",
+ "replacement": "∴ ",
+ "context": "all",
+ "category": "structural",
+ "minIntensity": "full",
+ "description": "Conclusion connectors → therefore symbol"
}
]
}
diff --git a/open-sse/services/compression/rules/pt-BR/ultra.json b/open-sse/services/compression/rules/pt-BR/ultra.json
new file mode 100644
index 0000000000..606cc22457
--- /dev/null
+++ b/open-sse/services/compression/rules/pt-BR/ultra.json
@@ -0,0 +1,192 @@
+{
+ "language": "pt-BR",
+ "category": "ultra",
+ "rules": [
+ {
+ "name": "pt_terse_leader_phrases",
+ "pattern": "^(?:eu vou|vou|eu posso|posso|deixa eu|deixe-me|vamos|a gente pode)\\s+(?=[a-záéíóúâêôãõç])",
+ "replacement": "",
+ "flags": "gm",
+ "context": "all",
+ "category": "terse",
+ "minIntensity": "full",
+ "description": "Leader phrases at sentence start — PT-BR equivalent of 'I'll/Let me'"
+ },
+ {
+ "name": "pt_ultra_banco_de_dados",
+ "pattern": "\\bbanco de dados\\b",
+ "replacement": "BD",
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "banco de dados → BD"
+ },
+ {
+ "name": "pt_ultra_configuracao",
+ "pattern": "\\b(?:configuração|configurações)\\b",
+ "replacement": "config",
+ "replacementMap": {
+ "configuração": "config",
+ "configurações": "configs"
+ },
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "configuração → config"
+ },
+ {
+ "name": "pt_ultra_funcao",
+ "pattern": "\\b(?:função|funções)\\b",
+ "replacement": "fn",
+ "replacementMap": {
+ "função": "fn",
+ "funções": "fns"
+ },
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "função → fn"
+ },
+ {
+ "name": "pt_ultra_requisicao",
+ "pattern": "\\b(?:requisição|requisições)\\b",
+ "replacement": "req",
+ "replacementMap": {
+ "requisição": "req",
+ "requisições": "reqs"
+ },
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "requisição → req"
+ },
+ {
+ "name": "pt_ultra_resposta",
+ "pattern": "\\bresposta\\b",
+ "replacement": "res",
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "resposta → res"
+ },
+ {
+ "name": "pt_ultra_implementacao",
+ "pattern": "\\b(?:implementação|implementações)\\b",
+ "replacement": "impl",
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "implementação → impl"
+ },
+ {
+ "name": "pt_ultra_autenticacao",
+ "pattern": "\\b(?:autenticação|autenticações)\\b",
+ "replacement": "auth",
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "autenticação → auth"
+ },
+ {
+ "name": "pt_ultra_autorizacao",
+ "pattern": "\\b(?:autorização|autorizações)\\b",
+ "replacement": "authz",
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "autorização → authz"
+ },
+ {
+ "name": "pt_ultra_aplicacao",
+ "pattern": "\\b(?:aplicação|aplicações)\\b",
+ "replacement": "app",
+ "replacementMap": {
+ "aplicação": "app",
+ "aplicações": "apps"
+ },
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "aplicação → app"
+ },
+ {
+ "name": "pt_ultra_dependencia",
+ "pattern": "\\b(?:dependência|dependências)\\b",
+ "replacement": "dep",
+ "replacementMap": {
+ "dependência": "dep",
+ "dependências": "deps"
+ },
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "dependência → dep"
+ },
+ {
+ "name": "pt_ultra_repositorio",
+ "pattern": "\\b(?:repositório|repositórios)\\b",
+ "replacement": "repo",
+ "replacementMap": {
+ "repositório": "repo",
+ "repositórios": "repos"
+ },
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "repositório → repo"
+ },
+ {
+ "name": "pt_ultra_variavel",
+ "pattern": "\\b(?:variável|variáveis)\\b",
+ "replacement": "var",
+ "replacementMap": {
+ "variável": "var",
+ "variáveis": "vars"
+ },
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "variável → var"
+ },
+ {
+ "name": "pt_ultra_componente",
+ "pattern": "\\b(?:componente|componentes)\\b",
+ "replacement": "comp",
+ "replacementMap": {
+ "componente": "comp",
+ "componentes": "comps"
+ },
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "componente → comp"
+ },
+ {
+ "name": "pt_ultra_diretorio",
+ "pattern": "\\b(?:diretório|diretórios)\\b",
+ "replacement": "dir",
+ "replacementMap": {
+ "diretório": "dir",
+ "diretórios": "dirs"
+ },
+ "flags": "gi",
+ "context": "all",
+ "category": "ultra",
+ "minIntensity": "ultra",
+ "description": "diretório → dir"
+ }
+ ]
+}