Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Client I18n

ASecurity

How to use @owlmeans/client-i18n — React i18n context built on i18next. Auto-invoked when setting up translation in a React app, using translation hooks, or working with language switching.

3 stars
0 votes
0 copies
0 views
Added 9/22/2026
developmenttypescriptreact

Works with

cli

Security Analysis

A100/100

Scanned 9/22/2026

Install to Claude Code

$npx -y skills add owlmeans/common --skill client-i18n --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Client I18n?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Client I18n
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/owlmeans-client-i18n/badge)](https://www.skillsdirectory.com/skills/owlmeans-client-i18n)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: client-i18n
description: How to use @owlmeans/client-i18n — React i18n context built on i18next. Auto-invoked when setting up translation in a React app, using translation hooks, or working with language switching.
user-invocable: false
---

# @owlmeans/client-i18n

**Layer:** Client (React)
**Install:** `"@owlmeans/client-i18n": "^0.1.18-rc.32"` in `dependencies`

## Purpose

Wraps i18next + react-i18next, lazily loads registered bundles from `@owlmeans/i18n` storage into the i18next instance, and provides hooks for translating strings.

## Key Exports

| Export | Description |
|--------|-------------|
| `I18nContext` | Provider component — wraps the React tree with an i18next instance |
| `useI18nLib(resource, prefix?)` | Hook for library strings (ns=`'lib'`) |
| `useI18nApp(resource?, prefix?)` | Hook for app strings (ns=resource name; defaults to `context.cfg.service`) |
| `useI18n(resource, ns?, prefix?)` | Low-level hook with explicit ns — use when ns ≠ resource |
| `useLanguage()` | `[currentLng, setLng]` — read and switch the active language |
| `composePrefix(parent?, child?)` | Canonical dot-join for prefix chaining; never call manually in panel code — used internally |
| `I18nBaseProps` | `{ resource?, ns?, prefix?, suppress? }` |
| `I18nProps` | `{ i18n?: I18nBaseProps }` |
| `I18nContextProps` | `{ config: ClientConfig }` — what the provider takes |

## Subpath: `./utils`

The instance itself, for a host that has to configure i18next before the tree renders.

| Export | Description |
|---|---|
| `useI18nInstance(config)` | The i18next instance for this application, memoised for the mount |
| `getI18nInstance(config)` | The same instance outside React |
| `setLanguage(lng)` | Persist and switch, without a component — what `useLanguage`'s setter calls |

**There is exactly one instance per document**, created on first request and reused by every later
call whatever config is passed. So configuration is read once, at the first creation, and a plugin
is installed on the instance rather than passed to a second factory:

```tsx
import { useI18nInstance } from '@owlmeans/client-i18n/utils'
import detector from 'i18next-browser-languagedetector'

const instance = useI18nInstance(context.cfg)
instance.use(detector)
```

`@owlmeans/web-panel`'s `render` already does exactly this, so an application on the panel family
needs none of it.

## Setup (app root)

```tsx
import { I18nContext } from '@owlmeans/client-i18n'

function App() {
  return (
    <I18nContext config={clientConfig}>
      <Routes />
    </I18nContext>
  )
}
```

`clientConfig.i18n` is optional; it defaults to `SUPPORTED_LNGS` and `'en'` fallback.

## Language persistence

The active language is persisted in `localStorage` under `owlmeans-lng` and restored on init — but
only when it is in `supportedLngs`, so a stored value that a later release dropped falls back to
`fallbackLng` instead of resolving nothing. Every storage access is guarded, so a browser that
refuses site data still renders.

```tsx
function LangSwitch() {
  const [lng, setLng] = useLanguage()
  return (
    <select value={lng} onChange={e => setLng(e.target.value)}>
      {['en','pl','ru','be','uk','es','de'].map(l => (
        <option key={l} value={l}>{l}</option>
      ))}
    </select>
  )
}
```

## Hooks

### useI18nLib — library packages

```typescript
// In a React component inside a library package
const t = useI18nLib('errors')          // loads lib:errors
const t = useI18nLib('errors', 'form')  // keyPrefix = errors.form
t('minLength')  // → lib:errors.form.minLength
```

### useI18nApp — app-level / project packages

```typescript
const t = useI18nApp()                       // uses context.cfg.service as resource+ns
const t = useI18nApp('my-app', 'home-screen') // explicit resource + prefix
t('title')  // → my-app:my-app.home-screen.title
```

### useI18n — explicit resource + ns

```typescript
// When ns and resource differ (e.g. DID namespace)
const t = useI18n('wallet', 'did', 'createKey')
t('title')  // → did:wallet.createKey.title
```

## Key resolution path

`useI18nLib('res', 'prefix')` → `t('key')`
→ i18next lookup: namespace=`lib`, keyPath=`res.prefix.key`
→ bundle was loaded as `{ res: jsonData }` into namespace `lib`
→ resolved value is `jsonData.prefix.key`

## App-level override of library strings

Import the library's i18n registration **and** register your own version at App tier **in the
library's namespace**:
```typescript
import '@owlmeans/error'               // the library bundle, registered by side effect
import { addI18nApp, LIB_NAMESPACE } from '@owlmeans/i18n'
import myErrors from './i18n/en.json' with { type: 'json' }

// App tier merges last within (ns, resource, lng) — these override the library's 'errors' strings
addI18nApp('en', 'errors', myErrors, { ns: LIB_NAMESPACE })
```

`{ ns: LIB_NAMESPACE }` is what makes it an override. `addI18nApp` defaults the namespace to the
**resource** name, so without it the bundle lands in namespace `errors` while `useI18nLib('errors')`
reads namespace `lib` — nothing errors, nothing merges, and the library strings keep rendering.

A package registers its strings from its own root: `src/i18n.ts` is re-exported by `src/index.ts`,
so importing the package is what loads them. No package publishes an `./i18n` subpath.

## Resource JSON format

The shared instance runs i18next's **v4** JSON format — `compatibilityJSON` is not set and must
not be, because i18next >= 26 accepts only `'v4'` and rejects `'v3'` at compile time. Plurals
therefore use Intl.PluralRules suffixes (`key_one` / `key_other`), never the v3 `key_plural` /
`key_0` / `key_1` forms. No resource in the ecosystem carries a plural-suffixed key today;
`{{count}}` in a message is plain interpolation and is unaffected.

Keep `i18next` and `react-i18next` in step — `react-i18next@17` requires `i18next >= 26.2.0`, and
a dependabot bump of one without the other leaves an unmet peer that installs fine and only
misbehaves at runtime.

## Depends On

`@owlmeans/i18n`, `@owlmeans/client`, `@owlmeans/client-context`, `i18next` (>= 26.2),
`react-i18next` (>= 17), `react` (the one peer). `@owlmeans/client` is what `useI18nApp` reads the
current context from, to default the resource to `context.cfg.service`.

Attribution

owlmeansowlmeans
View sourceMore from owlmeans →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

284072 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2192 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →