Skip to content

docs: translate README into Spanish - #666

Closed
ositaemmanuel653-netizen wants to merge 1 commit into
TegoLabs:mainfrom
ositaemmanuel653-netizen:docs/translate-readme-es-v2
Closed

ositaemmanuel653-netizen wants to merge 1 commit into
TegoLabs:mainfrom
ositaemmanuel653-netizen:docs/translate-readme-es-v2

Conversation

@ositaemmanuel653-netizen

Copy link
Copy Markdown

What does this PR do?

Closes #475

  • Adds a new README.es.md containing a complete Spanish translation of README.md.
  • Adds a language switcher at the top of both README.md and README.es.md so readers can easily navigate between the English and Spanish versions.
  • Preserves all code blocks, command names, CLI flags, and other technical identifiers in their original form.

Why?

This PR makes Sorokeep more accessible to the Spanish-speaking Stellar and Soroban developer community, particularly across Latin America. It lowers the barrier to entry for developers who prefer reading documentation in Spanish while keeping technical commands consistent with the English documentation.

As noted in the issue, documentation translations require ongoing maintenance as the English README evolves. I'm willing to help keep the Spanish translation in sync with future updates.

Does this touch secret-key handling or transaction submission?

  • Yes — see notes above
  • No

Checklist

  • Tests pass (npm test) (Not applicable — documentation-only changes.)
  • Type check passes (npx tsc --noEmit) (Not applicable — documentation-only changes.)
  • Lint passes (npm run lint) (Not applicable — documentation-only changes.)
  • Tests cover the new functionality (TDD preferred — see [CONTRIBUTING.md](../CONTRIBUTING.md#test-driven-development)) (Not applicable — documentation-only changes.)
  • No unnecessary dependencies added
  • Commit messages follow [conventional format](../CONTRIBUTING.md#commits)
  • No console.log in core logic
  • ADR added if this is a significant design decision (Not applicable.)
  • E2E sandbox tested, if this touches RPC or daemon behavior (Not applicable.)

Notes

  • README.es.md includes every section present in README.md.
  • All code examples, commands, flags, and technical identifiers remain untranslated.
  • The translation has been reviewed by a native/fluent Spanish speaker before merge.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Documentation
    • Added a comprehensive Spanish README for Sorokeep.
    • Documented installation, quick start, CLI commands, configuration, alerting, auto-extension, restoration, cost tracking, and daemon behavior.
    • Added guidance on security, notification channels, storage, deployment integrations, testing, FAQs, roadmap, contribution, and licensing.

Walkthrough

Added README.es.md, a complete Spanish translation of Sorokeep documentation. It covers installation, CLI commands, alerting, architecture, configuration, testing, FAQ, roadmap, contribution, licensing, and author information.

Changes

Spanish README

Layer / File(s) Summary
Overview and feature reference
README.es.md
Adds Spanish project context and descriptions of Soroban lifecycle management, monitoring, alerting, restoration, storage, security, and deployment features.
Installation and CLI workflow
README.es.md
Adds installation, quick-start, daemon, contract, alert, policy, cost, restoration, channel, database, and shell completion documentation.
Alerting and runtime architecture
README.es.md
Documents alert severity, webhook signatures, Slack, retries, daemon phases, data flow, SQLite storage, database tables, and configuration behavior.
Project reference and contribution guide
README.es.md
Adds project structure, architecture, technology stack, testing, FAQ, roadmap, contribution, licensing, and author information.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

  • #477 — Adds translated Sorokeep README documentation without code changes.

Possibly related PRs

Suggested reviewers: abdulmalikalayande

Poem

A rabbit reads the Spanish guide,
With CLI commands neatly tied.
Alerts hop, and daemons keep,
Soroban contracts safe in sleep.
New words bloom from page to page—
Documentation takes the stage.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The Spanish README is present and the stated review and maintenance requirements are addressed, but the provided summary does not confirm switcher links in both README files. Add or provide evidence of language-switcher links at the top of both README.md and README.es.md.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: translating the README into Spanish.
Description check ✅ Passed The description directly explains the Spanish README translation, navigation links, scope, and accessibility goal.
Out of Scope Changes check ✅ Passed The documented change adds the Spanish README and concerns only documentation, which matches the linked issue scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ositaemmanuel653-netizen

Copy link
Copy Markdown
Author

@AbdulmalikAlayande Recreated this contribution from the latest main to avoid the merge conflicts. Please review the new PR instead.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.es.md`:
- Around line 1-2: Update the README.es.md opening banner so the file begins
with the Markdown top-level heading “# Sorokeep” instead of the HTML paragraph
wrapper, or apply the existing documented MD041 exception consistently to both
README files.
- Around line 594-596: Correct the Spanish wording in the Núcleo architecture
description by replacing “Probable sin red o CLI” with “Probablemente sin red ni
CLI”, while leaving the surrounding architecture descriptions unchanged.
- Around line 132-144: README.es.md requires language tags on all three fenced
blocks: add the text language identifier to the fences for the output example at
lines 132-144, webhook header example at lines 421-423, and project tree at
lines 549-590.
- Around line 16-24: Update the navigation links at README.es.md lines 16-24 to
use the Spanish heading fragments, or add stable explicit anchors for those
headings. Also update README.es.md line 209 so the webhook-signing link targets
the fragment for “Firma de Webhook” or its explicit anchor.
- Line 54: Update the “Local Primero” description in README.es.md to state that
all state is stored locally in a SQLite database, replacing the claim that it is
stored in a queue while preserving the existing Stellar RPC endpoint qualifier.
- Around line 48-50: Reconcile the documented alert-channel support across
README.es.md:48-50, README.es.md:371-379, README.es.md:634-637, and
README.es.md:668-670. Ensure the overview, alerting section, test-coverage
claims, and FAQ consistently list only implemented channels, or add the missing
channel documentation and support; do not leave claims that Webhook and Slack
are the only supported integrations while other channels are advertised.
- Around line 430-434: Update verifySignature to extract the fixed-length
32-byte SHA-256 MAC from the signature, reject invalid formatting without
comparing variable-length values, and use crypto.timingSafeEqual for the MAC
comparison. Ensure the comparison only occurs when both extracted and expected
MAC buffers are exactly 32 bytes.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c8872368-9d58-4536-905e-587d12da26e3

📥 Commits

Reviewing files that changed from the base of the PR and between 833394c and 71bb0d1.

📒 Files selected for processing (1)
  • README.es.md
📜 Review details
🧰 Additional context used
🪛 LanguageTool
README.es.md

[style] ~204-~204: Considere alternativas para este anglicismo (recomendable sobre todo en contextos más formales).
Context: ...ck(requerido) | |--url ` | URL POST del webhook (requerido para webhook) | ...

(POST)


[style] ~393-~393: Considere alternativas para este anglicismo (recomendable sobre todo en contextos más formales).
Context: ...bhook se entregan como solicitudes HTTP POST con un cuerpo JSON: ```json { "type"...

(POST)

🪛 markdownlint-cli2 (0.23.2)
README.es.md

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)


[warning] 132-132: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 209-209: Link fragments should be valid

(MD051, link-fragments)


[warning] 421-421: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 549-549: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (1)
README.es.md (1)

4-8: 🗄️ Data Integrity & Integration

Verify the reciprocal language-switcher links.

The PR objective requires both README files to link to the Spanish version. Confirm that README.md links to README.es.md, and verify that README.pt.md exists before merge.

Comment thread README.es.md
Comment on lines +1 to +2
<p align="center">
<h1 align="center">Sorokeep</h1>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Resolve the MD041 heading warning.

markdownlint reports MD041 because the file starts with <p> instead of a Markdown top-level heading. Replace the banner with # Sorokeep, or configure the same documented exception for both README files.

🧰 Tools
🪛 markdownlint-cli2 (0.23.2)

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es.md` around lines 1 - 2, Update the README.es.md opening banner so
the file begins with the Markdown top-level heading “# Sorokeep” instead of the
HTML paragraph wrapper, or apply the existing documented MD041 exception
consistently to both README files.

Source: Linters/SAST tools

Comment thread README.es.md
Comment on lines +16 to +24
<a href="#install">Instalación</a>
&middot;
<a href="#quick-start">Inicio Rápido</a>
&middot;
<a href="#commands">Comandos</a>
&middot;
<a href="#alerting">Alertas</a>
&middot;
<a href="#contributing">Contribución</a>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix the translated heading fragments.

The navigation still uses English fragments after the headings were translated. These links do not resolve in README.es.md.

  • README.es.md#L16-L24: update the links to the Spanish heading fragments or add explicit stable anchors.
  • README.es.md#L209-L209: replace #webhook-signing with the fragment for Firma de Webhook, or add an explicit anchor.
📍 Affects 1 file
  • README.es.md#L16-L24 (this comment)
  • README.es.md#L209-L209
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es.md` around lines 16 - 24, Update the navigation links at
README.es.md lines 16-24 to use the Spanish heading fragments, or add stable
explicit anchors for those headings. Also update README.es.md line 209 so the
webhook-signing link targets the fragment for “Firma de Webhook” or its explicit
anchor.

Source: Linters/SAST tools

Comment thread README.es.md
Comment on lines +48 to +50
- **Alertas** — Notificaciones multicanal respaldadas por colas y desacopladas (Webhook con HMAC-SHA256, Slack Block Kit, Discord, Telegram, PagerDuty) con una robusta lógica de reintentos para TTLs bajos, picos de uso de recursos y cambios de estado
- **Auto-Extensión** — Extensión automática del TTL basada en políticas con simulación de transacciones antes del envío a través de `ExtendFootprintTTLOp`
- **Restauración** — Recupera entradas archivadas a través de `RestoreFootprintOp` con simulación previa al envío

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reconcile the documented alert-channel support.

The overview and alerting sections list Webhook, Slack, Discord, Telegram, and PagerDuty. The FAQ says that only Webhook and Slack are supported. This contradiction can cause users to configure unsupported integrations.

  • README.es.md#L48-L50: document only implemented channels, or add documentation for the additional channels.
  • README.es.md#L371-L379: align the alerting overview with actual channel support.
  • README.es.md#L634-L637: align the test-coverage claims with implemented channels.
  • README.es.md#L668-L670: update the FAQ or remove unsupported channels from the earlier sections.
📍 Affects 1 file
  • README.es.md#L48-L50 (this comment)
  • README.es.md#L371-L379
  • README.es.md#L634-L637
  • README.es.md#L668-L670
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es.md` around lines 48 - 50, Reconcile the documented alert-channel
support across README.es.md:48-50, README.es.md:371-379, README.es.md:634-637,
and README.es.md:668-670. Ensure the overview, alerting section, test-coverage
claims, and FAQ consistently list only implemented channels, or add the missing
channel documentation and support; do not leave claims that Webhook and Slack
are the only supported integrations while other channels are advertised.

Comment thread README.es.md
- **Seguimiento de Costos y Recursos** — Rastrea el historial de extensiones, costos en XLM, proyecciones a 30 días, registros de uso de recursos e impone presupuestos mensuales configurables para evitar gastos descontrolados
- **Inspección** — Inspecciona el estado en la cadena, analiza saldos de tokens SAC y compara cambios de estado
- **Canales** — Gestiona cuentas de canal financiadas para envíos de transacciones concurrentes sin cuellos de botella en la secuencia
- **Local Primero** — Todo el estado se almacena en una cola respaldada por una base de datos SQLite. Sin servicios externos más allá de un endpoint RPC de Stellar

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Describe SQLite as the state store.

Line [54] says that all state is stored in a queue backed by SQLite. A queue is only one subsystem. This contradicts Line [521]. Use: Todo el estado se almacena localmente en una base de datos SQLite.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es.md` at line 54, Update the “Local Primero” description in
README.es.md to state that all state is stored locally in a SQLite database,
replacing the claim that it is stored in a queue while preserving the existing
Stellar RPC endpoint qualifier.

Comment thread README.es.md
Comment on lines +132 to +144
```
$ sorokeep watch CDLZFC3S...CYSC --network testnet --name "XLM Native Token"

✔ Contract XLM Native Token registered successfully.

Contract: XLM Native Token (CDLZFC3S...CYSC)
Network: testnet
Entries: 1 discovered
Instance TTL: 113,918 ledgers (~7d 6h) OK

Run 'sorokeep status CDLZFC3S...CYSC' to check TTLs anytime.
Run 'sorokeep guard CDLZFC3S...CYSC' to enable auto-extension.
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add language tags to the fenced blocks.

markdownlint reports MD040 for these blocks. Add text to the fences.

  • README.es.md#L132-L144: output example.
  • README.es.md#L421-L423: webhook header example.
  • README.es.md#L549-L590: project tree.
🧰 Tools
🪛 markdownlint-cli2 (0.23.2)

[warning] 132-132: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

📍 Affects 1 file
  • README.es.md#L132-L144 (this comment)
  • README.es.md#L421-L423
  • README.es.md#L549-L590
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es.md` around lines 132 - 144, README.es.md requires language tags on
all three fenced blocks: add the text language identifier to the fences for the
output example at lines 132-144, webhook header example at lines 421-423, and
project tree at lines 549-590.

Source: Linters/SAST tools

Comment thread README.es.md
Comment on lines +430 to +434
function verifySignature(payload, signature, secret) {
const expected = "sha256=" + createHmac("sha256", secret)
.update(payload)
.digest("hex");
return signature === expected;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate README files and relevant excerpt:"
fd -a '^README\.es\.md$' . | sed 's#^\./##'
echo
if [ -f README.es.md ]; then
  wc -l README.es.md
  sed -n '410,445p' README.es.md | nl -ba -v410
fi

echo
echo "Search for similar webhook signature examples in README files:"
rg -n "verifySignature|sha256=|timingSafeEqual|createHmac" README* || true

echo
echo "Check Node crypto timingSafeEqual availability (no repo code execution):"
node - <<'JS'
const { createHmac, timingSafeEqual } = require('node:crypto');
console.log('timingSafeEqual exported:', typeof timingSafeEqual === 'function');
const secret = 'abc';
const payload = 'xyz';
const expected = 'sha256=' + createHmac('sha256', secret).update(payload).digest('hex');
const validSig = expected;
const invalidSig = expected.slice(0, 64) + '000000000000000000000000000000000000000000000000';
const formatUnsafe = 'sha256=' + expected.slice('sha256='.length, 50) + '0000000000000000000000000000000000000000000000000000000000000000';
console.log('valid ===:', validSig === expected);
console.log('invalid ===:', invalidSig === expected);
console.log('valid timingSafeEqual:', timingSafeEqual(Buffer.from(validSig.slice(7), 'hex'), Buffer.from(expected.slice(7), 'hex')));
console.log('invalid timingSafeEqual:', timingSafeEqual(Buffer.from(invalidSig.slice(7), 'hex'), Buffer.from(expected.slice(7), 'hex')));
console.log('formatUnsafe ===:', formatUnsafe === expected);
try {
  timingSafeEqual(Buffer.from(formatUnsafe.slice(7), 'hex'), Buffer.from(expected.slice(7), 'hex'));
  console.log('formatUnsafe timingSafeEqual:', true);
} catch (e) {
  console.log('formatUnsafe timingSafeEqual error:', e.name + ': ' + e.message);
}
JS

Repository: AbdulmalikAlayande/sorokeep

Length of output: 297


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Inspect surrounding README context for webhook secret guidance:"
sed -n '1,90p' README.es.md | nl -ba -v1
echo "---"
sed -n '340,460p' README.es.md | nl -ba -v340

Repository: AbdulmalikAlayande/sorokeep

Length of output: 269


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "README.es.md excerpt around webhook example:"
sed -n '410,448p' README.es.md

echo
echo "Search for related signature/secret guidance:"
rg -n "verifySignature|sha256=|timingSafeEqual|createHmac|webhook|secre|secret" README.es.m* || true

echo
echo "Node crypto timingSafeEqual behavior:"
node - <<'JS'
const { createHmac, timingSafeEqual } = require('node:crypto');
const secret = 'abc';
const payload = 'xyz';
const expected = 'sha256=' + createHmac('sha256', secret).update(payload).digest('hex');
const validSig = expected;
const invalidSig = expected.slice(0, 64) + '000000000000000000000000000000000000000000000000';
const formatUnsafe = 'sha256=' + expected.slice('sha256='.length, 50) + '0000000000000000000000000000000000000000000000000000000000000000';
console.log('timingSafeEqual exported:', typeof timingSafeEqual === 'function');
console.log('valid ===:', validSig === expected);
console.log('invalid ===:', invalidSig === expected);
console.log('valid timingSafeEqual:', timingSafeEqual(Buffer.from(validSig.slice(7), 'hex'), Buffer.from(expected.slice(7), 'hex')));
console.log('invalid timingSafeEqual:', timingSafeEqual(Buffer.from(invalidSig.slice(7), 'hex'), Buffer.from(expected.slice(7), 'hex')));
console.log('formatUnsafe ===:', formatUnsafe === expected);
try {
  timingSafeEqual(Buffer.from(formatUnsafe.slice(7), 'hex'), Buffer.from(expected.slice(7), 'hex'));
  console.log('formatUnsafe timingSafeEqual:', true);
} catch (e) {
  console.log('formatUnsafe timingSafeEqual error:', e.name + ': ' + e.message);
}
JS

Repository: AbdulmalikAlayande/sorokeep

Length of output: 5764


Use a timing-safe webhook signature comparison.

The verifier returns early on bad sha256= formatting, which leaks validation time. Use a fixed-length MAC extraction, then compare only the 32 MAC bytes with crypto.timingSafeEqual.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es.md` around lines 430 - 434, Update verifySignature to extract the
fixed-length 32-byte SHA-256 MAC from the signature, reject invalid formatting
without comparing variable-length values, and use crypto.timingSafeEqual for the
MAC comparison. Ensure the comparison only occurs when both extracted and
expected MAC buffers are exactly 32 bytes.

Comment thread README.es.md
Comment on lines +594 to +596
- **Comandos** (`src/commands/`) — Capa fina de la CLI. Analiza argumentos, llama al núcleo (core), formatea la salida en la terminal. Sin lógica de negocio.
- **Núcleo** (`src/core/`) — Lógica de negocio pura. Probable sin red o CLI. El demonio reutiliza las mismas funciones.
- **RPC** (`src/rpc/`) — Envoltura del SDK de Stellar. Todas las llamadas de red pasan por aquí. Maneja la creación, simulación, firma y envío de transacciones.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the Spanish grammar in the architecture description.

Line [595] says Probable sin red o CLI. Use Probablemente sin red ni CLI.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es.md` around lines 594 - 596, Correct the Spanish wording in the
Núcleo architecture description by replacing “Probable sin red o CLI” with
“Probablemente sin red ni CLI”, while leaving the surrounding architecture
descriptions unchanged.

AbdulmalikAlayande added a commit that referenced this pull request Aug 8, 2026
Adds README.es.md and a language-switcher link in README.md. Ported
the contributor's translation of PR #666 (the cleaner of two
duplicate submissions — #665 carried unrelated stale-branch commits).

Their translation was based on a slightly older README.md (43 of 46
sections) — missing Global Options, the 'contracts' command, and the
Supported Channels Comparison table, and the Alerting intro paragraph
still listed only 5 of the 11 now-supported channels. Translated the
missing sections and corrected the channel list to bring it to full
parity with the issue's "every section, no drops" acceptance
criterion, keeping the contributor's translation for everything else
unchanged. Added tests/docs/readme-spanish.test.ts mirroring the
existing readme-portuguese.test.ts coverage pattern.
@AbdulmalikAlayande

Copy link
Copy Markdown
Collaborator

Merged via 7dc567a on main. Thanks for this — the translation quality and register were solid.

Your fork was based on a slightly older README.md, so it was missing 3 sections that landed since: Global Options, the contracts command, and the Supported Channels Comparison table (the Alerting intro paragraph also still listed only 5 of the now-11 channels). I translated those missing pieces and corrected the channel list to bring it to full parity with the "every section, no drops" acceptance criterion, keeping everything else exactly as you wrote it. Also added README.md's language-switcher link (now lists Español + Português) and a test file mirroring the existing Portuguese README test coverage.

Went with your branch over #665 since it was a single clean commit off current main rather than carrying unrelated stale history — closing that one as a duplicate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: translate README into Spanish

2 participants