Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
5a55f38
Merge pull request #188 from openscan-explorer/main
AugustoL Jan 29, 2026
2d1b6e2
chore: bump version to 1.2.0-alpha
AugustoL Jan 30, 2026
ccb797e
feat: add Bitcoin network support and migrate to networkId-based system
AugustoL Jan 30, 2026
8740645
build: publish from ./dist and use OIDC
MatiasOS Jan 30, 2026
c290b95
Merge pull request #191 from MatiasOS/fix-npm-publish
MatiasOS Jan 31, 2026
92e8aa6
feat(bitcoin): add block, transaction, and address detail pages
AugustoL Jan 31, 2026
52c2a79
refactor(navbar): simplify navigation with network dropdown
AugustoL Jan 31, 2026
51db1b2
fix(config): update Bitcoin logo path to use metadata package
AugustoL Jan 31, 2026
8b11f35
feat(bitcoin): add blocks and transactions list pages
AugustoL Jan 31, 2026
9da7937
chore: update @openscan/network-connectors to v1.3.0
MatiasOS Jan 31, 2026
1a15cd1
feat(rpc): implement race (first-resolved) RPC strategy
MatiasOS Jan 31, 2026
d865361
fix(address): fix receipt status display and race strategy receipt loss
MatiasOS Jan 31, 2026
86a15c8
Merge pull request #189 from AugustoL/chore/bump-version-1.2.0-a
AugustoL Feb 2, 2026
f9b1bcb
refactor(bitcoin): extract shared utilities from components
AugustoL Feb 2, 2026
cf031bc
refactor(routing): simplify with explicit Bitcoin routes
AugustoL Feb 2, 2026
0941984
fix(bitcoin): use network.slug for links and add SearchBox
AugustoL Feb 2, 2026
ba29986
feat(bitcoin): add testnet4 support and mempool navbar link
AugustoL Feb 2, 2026
e19738b
feat(bitcoin): add mempool page with pagination
AugustoL Feb 2, 2026
f21fcf4
Merge pull request #194 from MatiasOS/feat/race-rpc-strategy
MatiasOS Feb 2, 2026
8d8636f
fix(bitcoin): fix network routing and block transaction count
AugustoL Feb 2, 2026
eafada4
refactor(routing): remove NetworkAwareRouters in favor of explicit ro…
AugustoL Feb 2, 2026
a8cbc93
refactor(pages): organize EVM pages into evm/ subfolder
AugustoL Feb 2, 2026
868c7a6
docs: add Bitcoin network support to README
AugustoL Feb 2, 2026
e0aedb2
test(bitcoin): add e2e tests for Bitcoin network pages
AugustoL Feb 2, 2026
dba75d9
ci: add separate GitHub Actions workflow for Bitcoin e2e tests
AugustoL Feb 3, 2026
9c09188
refactor: improve Bitcoin block display layout and format imports
AugustoL Feb 3, 2026
e0f7766
fix(bitcoin): add separate loading state for transactions
AugustoL Feb 3, 2026
0f6268c
feat(bitcoin): add View All links to dashboard blocks and transaction…
AugustoL Feb 3, 2026
5799cc7
fix(bitcoin): skip leading zeros when displaying block hashes
AugustoL Feb 3, 2026
2d5c456
feat: add super user mode to show/hide advanced features
AugustoL Feb 3, 2026
6ee8f7d
docs: emphasize PR template requirement in workflow rules
AugustoL Feb 3, 2026
90ccd52
fix: mobile layout for Settings page RPC badges overflow
AugustoL Feb 3, 2026
6e6b9ef
Merge pull request #201 from openscan-explorer/dev
AugustoL Feb 3, 2026
3c2189f
Merge pull request #199 from AugustoL/feat/187-super-user-mode
AugustoL Feb 3, 2026
1efaf8f
fix(settings): hide metamask button and RPC count on mobile
AugustoL Feb 4, 2026
3ad8036
merge: sync with release/v1.2.0-a
AugustoL Feb 5, 2026
2429933
merge: sync with release/v1.2.0-a
AugustoL Feb 5, 2026
9bdec21
Merge pull request #190 from AugustoL/feat/bitcoin-network-integration
AugustoL Feb 5, 2026
eea794c
test(e2e): restructure e2e tests and fix test reliability
AugustoL Feb 4, 2026
8eb75b3
merge: sync with release/v1.2.0-a
AugustoL Feb 5, 2026
3a0f1eb
feat(meta): improve SEO metadata and fix manifest icons
AugustoL Feb 5, 2026
b4e0d31
feat(seo): add structured data and static HTML for AI/crawler indexing
AugustoL Feb 5, 2026
fe19fb3
Merge pull request #204 from AugustoL/feat/improve-metadata
AugustoL Feb 5, 2026
8c4040f
Merge pull request #203 from AugustoL/fix/e2e-tests
AugustoL Feb 5, 2026
2f4ad4e
Merge pull request #200 from AugustoL/fix/193-mobile-settings-rpc-badges
AugustoL Feb 5, 2026
528c76a
feat(address): auto-search recent transactions on page load
AugustoL Feb 5, 2026
7b647f7
feat(search): exponential search algorithm and abort on navigation
AugustoL Feb 5, 2026
5a86b3b
fix(html): remove static preload content from root div
AugustoL Feb 5, 2026
bff7535
fix(search): review fixes for auto-search and abort handling
AugustoL Feb 5, 2026
8f76567
feat(search): semaphore rate limiting and UI improvements
AugustoL Feb 5, 2026
f9a28d9
feat(search): show live progress with block ranges during search
AugustoL Feb 5, 2026
299ef23
Merge pull request #206 from AugustoL/fix/remove-static-preload-html
AugustoL Feb 6, 2026
4b29123
Merge pull request #205 from AugustoL/feat/auto-search-recent-txs
AugustoL Feb 6, 2026
334c59a
chore: add i18n dependencies
MatiasOS Feb 3, 2026
bf4d747
feat(i18n): scaffolding and setup
MatiasOS Feb 3, 2026
927b590
refactor(i18n): translate Address page and components
MatiasOS Feb 6, 2026
3e4d06e
refactor(i18n): translate Blocks pages
MatiasOS Feb 6, 2026
6a38354
refactor(i18n): translate devtools page
MatiasOS Feb 6, 2026
7434844
refactor(i18n): translate txs pages
MatiasOS Feb 6, 2026
1fecad9
refactor(i18n): translate settings page
MatiasOS Feb 6, 2026
de83f65
refactor(i18n): translate Home pages
MatiasOS Feb 6, 2026
a0727b0
refactor(i18n): translate Network components
MatiasOS Feb 6, 2026
7d6ad8e
refactor(i18n): translate TokenDetails page and components
MatiasOS Feb 6, 2026
80510b5
refactor(i18n): translate common and shared components
MatiasOS Feb 6, 2026
a7d8caf
fix(i18n): add missing translations
MatiasOS Feb 6, 2026
f83ceac
docs(claude): add rules for i18n
MatiasOS Feb 6, 2026
0a20f42
Merge pull request #207 from MatiasOS/130-feat-implement-i18n-infrast…
MatiasOS Feb 7, 2026
ab5c0fb
feat(logger): add logger utility with environment-aware log levels
MatiasOS Feb 6, 2026
c8e753d
refactor(utils): migrate console statements to logger
MatiasOS Feb 6, 2026
9d5ecec
refactor(services): migrate console statements to logger
MatiasOS Feb 6, 2026
6d74eb5
refactor(hooks): migrate console statements to logger
MatiasOS Feb 6, 2026
f2c7b1e
refactor(context): migrate console statements to logger
MatiasOS Feb 6, 2026
06f0150
refactor(components): migrate console statements to logger
MatiasOS Feb 6, 2026
23a9b87
refactor(config): migrate console statement to logger
MatiasOS Feb 6, 2026
8e8bdf2
docs(claude): add logger utility documentation
MatiasOS Feb 6, 2026
d595f13
fix(i18n): remove not used translations
MatiasOS Feb 7, 2026
68b235e
feat(i18n): translate gasTracker
MatiasOS Feb 7, 2026
4c3894a
Merge pull request #208 from MatiasOS/186-feat-implement-logging-util…
AugustoL Feb 9, 2026
b5202bd
Merge pull request #209 from MatiasOS/i18n-fixes
AugustoL Feb 9, 2026
0b6412f
Merge pull request #195 from openscan-explorer/release/v1.2.0-a
AugustoL Feb 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ Detailed instructions are organized in the rules directory:
@.claude/rules/code-style.md - Code style, formatting, and quality requirements
@.claude/rules/workflow.md - Git workflow, branches, PRs, and issues
@.claude/rules/patterns.md - Important coding patterns for this codebase
@.claude/rules/i18n.md - Internationalization guidelines and best practices
16 changes: 15 additions & 1 deletion .claude/rules/code-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@
- **React 19** with functional components and hooks
- No class components

## Internationalization (i18n)

- **NEVER hardcode user-facing strings** - All text visible to users must use the i18n system
- Use `useTranslation()` hook from react-i18next in all components with user-facing text
- See @.claude/rules/i18n.md for complete guidelines on:
- Choosing the right namespace
- Adding new translation keys
- Variable interpolation and pluralization
- Supporting new languages

## CSS

- All styles should be in `src/styles` folder
Expand Down Expand Up @@ -49,7 +59,11 @@ npm run lint:fix
# 3. Verify type safety
npm run typecheck

# 4. Run tests (if applicable)
# 4. Verify i18n compliance
# - Ensure no hardcoded user-facing strings
# - Test in both English and Spanish if you added translations

# 5. Run tests (if applicable)
npm run test:run
```

Expand Down
341 changes: 341 additions & 0 deletions .claude/rules/i18n.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,341 @@
# Internationalization (i18n)

## Core Principle

**NEVER hardcode user-facing strings.** All text visible to users must use the i18n system.

## Library and Configuration

- **Library**: react-i18next (v16.5.4) with i18next (v25.8.0)
- **Configuration**: `src/i18n.ts`
- **Type Definitions**: `src/i18next.d.ts` (provides TypeScript autocomplete)
- **Supported Languages**: English (en), Spanish (es)
- **Language Detection**: Auto-detects from browser or localStorage (`openScan_language`)

## When to Use i18n

✅ **ALWAYS use i18n for**:
- UI labels and buttons
- Page titles and headings
- Error messages
- Success/info messages
- Form labels and placeholders
- Tooltips and aria-labels
- Toast notifications
- Modal content
- Loading states
- Empty states

❌ **DO NOT use i18n for**:
- Code comments
- Console.log statements
- Developer-only debug messages
- Variable names
- URLs (unless they're user-facing link text)
- File paths
- API endpoints

## Available Namespaces

Choose the appropriate namespace based on the component location:

1. **common** - Navigation, footer, shared UI elements, general errors, wallet, RPC indicator
2. **home** - Home page content
3. **settings** - Settings page (appearance, language, cache, RPC, API keys)
4. **address** - Address page (contract verification, tokens, NFTs, transactions, ENS)
5. **block** - Blocks and Block details page
6. **transaction** - Transactions and Transaction details page (status, gas, events, traces, L2 fields)
7. **network** - Network statistics and information
8. **devtools** - Developer tools page
9. **errors** - Error messages (if not in common)
10. **tokenDetails** - Token detail pages (ERC20, ERC721, ERC1155)

## Basic Usage

### Import and Setup

```tsx
import { useTranslation } from "react-i18next";

const MyComponent = () => {
// Default namespace (common)
const { t } = useTranslation();

// Specific namespace
const { t } = useTranslation("settings");

// Both t function and i18n instance
const { t, i18n } = useTranslation("settings");
};
```

### Simple Translation

```tsx
// ❌ BAD - Hardcoded
<button>Submit</button>

// ✅ GOOD - Using i18n
const { t } = useTranslation("common");
<button>{t("actions.submit")}</button>
```

### Nested Keys

```tsx
// Translation file: src/locales/en/settings.json
{
"cacheData": {
"clearSiteData": {
"confirmMessage": "This will clear all data. Continue?"
}
}
}

// Usage: Dot notation for nested keys
const { t } = useTranslation("settings");
const message = t("cacheData.clearSiteData.confirmMessage");
```

## Variable Interpolation

Use `{{variableName}}` syntax for dynamic values:

```tsx
// Translation file
{
"footer": {
"versionLabel": "v{{version}} {{hash}}"
}
}

// Usage
const { t } = useTranslation("common");
<span>{t("footer.versionLabel", { version: "1.0.0", hash: "abc123" })}</span>
// Output: "v1.0.0 abc123"
```

## Pluralization

Use `_other` suffix for plural forms:

```tsx
// Translation file
{
"item": "{{count}} item",
"item_other": "{{count}} items"
}

// Usage
const { t } = useTranslation();
<p>{t("item", { count: 1 })}</p> // "1 item"
<p>{t("item", { count: 5 })}</p> // "5 items"
```

## Language Switching

```tsx
const { i18n } = useTranslation();

// Change language
const switchLanguage = (langCode: string) => {
i18n.changeLanguage(langCode);
localStorage.setItem("openScan_language", langCode);
};

// Get current language
const currentLang = i18n.language; // "en" or "es"
```

## Adding New Translation Keys

### Step-by-step Process

1. **Identify the appropriate namespace** based on component location
2. **Add key to English file** (`src/locales/en/{namespace}.json`)
3. **Add same key to Spanish file** (`src/locales/es/{namespace}.json`)
4. **Use TypeScript autocomplete** to verify the key exists
5. **Test in both languages** by switching in Settings

### Example

```bash
# 1. Add to English file
# src/locales/en/address.json
{
"contractVerified": "Contract Verified",
"newKey": "Your new text here" # ← Add this
}

# 2. Add to Spanish file
# src/locales/es/address.json
{
"contractVerified": "Contrato Verificado",
"newKey": "Tu nuevo texto aquí" # ← Add this
}

# 3. Use in component
const { t } = useTranslation("address");
<span>{t("newKey")}</span> # TypeScript autocomplete will suggest "newKey"
```

## TypeScript Type Safety

The i18n system provides full TypeScript autocomplete and type checking:

```tsx
const { t } = useTranslation("settings");

// ✅ Valid - TypeScript knows this key exists
t("language.title");

// ❌ Invalid - TypeScript error: key doesn't exist
t("nonexistent.key"); // Type error!
```

**Important**: If a translation key doesn't autocomplete, it doesn't exist in the type definitions!

## Common Patterns

### Aria Labels and Accessibility

```tsx
// ❌ BAD
<button aria-label="Close menu">X</button>

// ✅ GOOD
const { t } = useTranslation("common");
<button aria-label={t("nav.closeMenuAriaLabel")}>X</button>
```

### Conditional Messages

```tsx
const { t } = useTranslation("common");
const status = isConnected
? t("rpcIndicator.connected")
: t("rpcIndicator.disconnected");
```

### Loading States

```tsx
// ❌ BAD
<Loader text="Loading NFT metadata..." />

// ✅ GOOD
const { t } = useTranslation("tokenDetails");
<Loader text={t("loading.metadata")} />
```

## HTML in Translations

HTML is allowed in translations (escapeValue is disabled):

```tsx
// Translation file
{
"richText": "Click <strong>here</strong> for more info"
}

// Usage with dangerouslySetInnerHTML
const { t } = useTranslation();
<div dangerouslySetInnerHTML={{ __html: t("richText") }} />
```

**Warning**: Only use HTML in translations from trusted sources you control.

## Adding a New Language

1. **Create language directory**: `src/locales/{langCode}/`
2. **Copy all namespace files** from `en/` to `{langCode}/`
3. **Translate all strings** in each file
4. **Update i18n.ts**: Add language to resources and SUPPORTED_LANGUAGES
5. **Test**: Switch to new language in Settings

Example for French (fr):

```typescript
// src/i18n.ts
export const SUPPORTED_LANGUAGES = [
{ code: "en", name: "English" },
{ code: "es", name: "Español" },
{ code: "fr", name: "Français" }, // ← Add this
];

// Add to resources
resources: {
en: { /* ... */ },
es: { /* ... */ },
fr: { // ← Add this
common: commonFr,
home: homeFr,
// ... all namespaces
},
}
```

## Examples from Codebase

### Good Example - Settings Page

```tsx
// src/components/pages/settings/index.tsx
import { useTranslation } from "react-i18next";

const Settings: React.FC = () => {
const { t, i18n } = useTranslation("settings");

return (
<>
<h1>{t("pageTitle")}</h1>
<p>{t("appearance.description")}</p>
<button onClick={() => i18n.changeLanguage("es")}>
{t("language.label")}
</button>
</>
);
};
```

### Bad Example - Hardcoded Strings (Don't do this!)

```tsx
// ❌ WRONG - Multiple hardcoded strings
<div className="block-display-card">
<div className="block-display-header">
<span className="block-label">ERC-721 NFT</span> {/* ❌ Hardcoded */}
</div>
<Loader text="Loading NFT metadata..." /> {/* ❌ Hardcoded */}
</div>

// ✅ CORRECT - Use i18n
const { t } = useTranslation("tokenDetails");
<div className="block-display-card">
<div className="block-display-header">
<span className="block-label">{t("nft.label")}</span> {/* ✅ i18n */}
</div>
<Loader text={t("loading.metadata")} /> {/* ✅ i18n */}
</div>
```

## Before Committing

When adding or modifying components, ensure:

- [ ] No hardcoded user-facing strings remain
- [ ] All text uses `t()` function from useTranslation
- [ ] Translation keys exist in **both** en/ and es/ directories
- [ ] TypeScript compilation passes (`npm run typecheck`)
- [ ] Tested in both English and Spanish (switch in Settings)

## Checklist for Code Review

When reviewing code, verify:

- [ ] All user-facing strings use i18n
- [ ] Appropriate namespace is selected
- [ ] Translation keys follow existing naming patterns
- [ ] Interpolation variables are properly typed
- [ ] Translations exist in all supported languages
- [ ] No typos in translation keys (TypeScript should catch these)
Loading