NALU/docs/adding-language.md
Ricardo Carneiro e01787ee60 Add deploy infrastructure, missing validators, and new features
- Add Docker Swarm deploy stack, CI workflow (.gitea), entrypoint script
- Fix Dockerfile to build Nalu.Web (was pointing to old Nalu.Api path)
- Add validate_name.md and other missing validators to prod
- Add Stripe endpoints, HangfireDashboardAuth, InputGuard, NameLookupService
- Add SuspiciousRateLimiter, En/ pages, Legal/ pages, Seguranca docs
- Add Nalu.Jobs and Nalu.NameImporter projects (were untracked)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 12:31:12 -03:00

187 lines
6.3 KiB
Markdown

# Adding a new language
Reference: implemented PT (default) + EN (`/en`). Next planned: ES (`/es`).
## Architecture overview
- Language is URL-prefix based: `/en/...`, `/es/...`
- No cookies, no sessions — URL is the source of truth
- Language detected in `_Layout.cshtml` via `Context.Request.Path`
- Pages without a translation simply don't get hreflang tags
## Checklist to add a new language (e.g. `/es`)
### 1. Create page files
Mirror the `Pages/En/` folder structure:
```
Pages/Es/
Index.cshtml + Index.cshtml.cs → @page "/es"
Pricing.cshtml + Pricing.cshtml.cs → @page "/es/pricing"
Playground.cshtml + Playground.cshtml.cs → @page "/es/playground"
Validators/
Index.cshtml + Index.cshtml.cs → @page "/es/validators"
Docs/
Index.cshtml + Index.cshtml.cs → @page "/es/docs"
Quickstart.cshtml + .cs → @page "/es/docs/quickstart"
ApiReference.cshtml + .cs → @page "/es/docs/api-reference"
Mcp.cshtml + .cs → @page "/es/docs/mcp"
N8n.cshtml + .cs → @page "/es/docs/n8n"
Credits.cshtml + .cs → @page "/es/docs/credits"
Errors.cshtml + .cs → @page "/es/docs/errors"
```
**Validator ordering for ES:** Universal first (same as EN), Brazilian second.
### 2. Update `_Layout.cshtml`
File: `src/Nalu.Web/Pages/_Layout.cshtml`
#### a) Language detection block (top `@{ }`)
Add ES detection alongside EN:
```csharp
var _isEn = Context.Request.Path.StartsWithSegments("/en");
var _isEs = Context.Request.Path.StartsWithSegments("/es"); // ADD
var _lp = _isEn ? "/en" : _isEs ? "/es" : ""; // UPDATE
```
#### b) Known pages sets — add ES set
```csharp
var _knownEs = new HashSet<string> {
"/es", "/es/pricing", "/es/validators", "/es/playground",
"/es/docs", "/es/docs/quickstart", "/es/docs/api-reference",
"/es/docs/mcp", "/es/docs/n8n", "/es/docs/credits", "/es/docs/errors"
};
bool _hasAlternate = (_isEn ? _knownEn : _isEs ? _knownEs : _knownPt).Contains(_cur);
```
#### c) `_altUrl` switch — add ES cases to all three branches
The switch currently has EN→PT and PT→EN. Add:
- EN→ES branch (or link via PT as pivot)
- ES→PT branch
- PT→ES branch
Simplest: each language maps to PT as canonical pivot, then PT maps to all others. Or: extend the switch to map directly between all pairs. Given 3 languages, direct mapping is cleaner:
```csharp
// When on ES page, altUrl = PT equivalent
"/es" => "/",
"/es/pricing" => "/precos",
// ... etc
// When on PT page, need to decide which alternate to link to.
// Convention: globe shows the "other" language not currently active.
// With 3 languages, globe becomes a dropdown with all options.
```
#### d) Globe dropdown — extend to 3 options
Replace the current 2-option globe with a 3-option dropdown:
```html
<a href="[PT URL]">🇧🇷 Português @(_isEn || _isEs ? "" : "✓")</a>
<a href="[EN URL]">🇺🇸 English @(_isEn ? "✓" : "")</a>
<a href="[ES URL]">🇪🇸 Español @(_isEs ? "✓" : "")</a>
```
You'll need to compute both `_altUrlEn` and `_altUrlEs` (and `_altUrlPt`) separately instead of a single `_altUrl`.
#### e) Nav link labels — add ES strings
```csharp
// Current: @(_isEn ? "Validators" : "Validadores")
// Updated:
@(_isEn ? "Validators" : _isEs ? "Validadores" : "Validadores")
// Most validator names are the same in ES/PT — adjust as needed.
```
Pricing label:
```csharp
@(_isEn ? "Pricing" : _isEs ? "Precios" : "Preços")
```
#### f) Footer — add ES to use cases section
Currently the "Casos/Use cases" section links to PT-only `/casos/...` pages. For ES, either link to the same PT pages or create ES case study pages.
#### g) hreflang — add ES alternate
```csharp
// _esAbsolute = ES version URL
<link rel="alternate" hreflang="es" href="@_esAbsolute" />
```
#### h) `html lang` attribute
```csharp
<html lang="@(_isEn ? "en" : _isEs ? "es" : "pt-BR")">
```
### 3. Logo link
Currently:
```csharp
<a href="@(_isEn ? "/en" : "/")">
```
Update:
```csharp
<a href="@(_isEn ? "/en" : _isEs ? "/es" : "/")">
```
### 4. Pricing page — currency
ES pricing: same USD values as EN page (`/en/pricing` as reference). Spanish-speaking markets outside Brazil → use USD, show BRL as `≈ R$ X` secondary (same pattern as EN).
Or: if targeting Spain specifically, consider EUR. Decision needed per market.
### 5. Validators ordering
| Language | Order |
|----------|-------|
| PT | Brazilian first, Universal second |
| EN | Universal first, Brazilian second |
| ES | Universal first, Brazilian second (same as EN) |
### 6. PT pages without EN equivalent
Pages like `/casos/parcelas-48x`, `/docs/fluxos`, `/validadores/reply` have no EN/ES version. Globe dropdown on these pages shows links to EN/ES home (`/en`, `/es`) as fallback. This is intentional.
## URL slug conventions
| Concept | PT | EN | ES (planned) |
|-------------|--------------|----------------|--------------|
| Home | `/` | `/en` | `/es` |
| Pricing | `/precos` | `/en/pricing` | `/es/precios`|
| Validators | `/validadores`| `/en/validators`| `/es/validadores`|
| Playground | `/playground`| `/en/playground`| `/es/playground`|
| Docs | `/docs` | `/en/docs` | `/es/docs` |
| Credits | `/docs/creditos`| `/en/docs/credits`| `/es/docs/credits`|
| Errors | `/docs/erros`| `/en/docs/errors`| `/es/docs/errors`|
## SEO tags (auto-generated in layout)
The layout generates these automatically for pages with known translations:
```html
<link rel="canonical" href="https://naluai.dev/[current-path]" />
<link rel="alternate" hreflang="pt-BR" href="https://naluai.dev/[pt-path]" />
<link rel="alternate" hreflang="en" href="https://naluai.dev/en/[en-path]" />
<link rel="alternate" hreflang="x-default" href="https://naluai.dev/[pt-path]" />
```
`x-default` always points to PT (primary market). Add `hreflang="es"` when ES is implemented.
## Files to touch (summary)
When adding ES:
1. `Pages/En/*.cshtml` — duplicate folder as `Pages/Es/`, translate content
2. `Pages/_Layout.cshtml` — 6 locations: detection, known sets, altUrl switch, globe dropdown, nav labels, hreflang tags
3. No changes needed to: PageModels (thin, language-agnostic), API endpoints, auth, Stripe