Agent Skills: Language Specialist

|

UncategorizedID: Spectaculous-Code/raamattu-nyt/language-specialist

Install this agent skill to your local

pnpm dlx add-skill https://github.com/Spectaculous-Code/raamattu-nyt/tree/HEAD/.claude/skills/language-specialist

Skill Files

Browse the full folder contents for language-specialist.

Download Skill

Loading file tree…

.claude/skills/language-specialist/SKILL.md

Skill Metadata

Name
language-specialist
Description
|

Language Specialist

Expert assistant for all i18n/l10n work in the Raamattu Nyt project.

Architecture Overview

packages/shared-i18n/          # Shared i18n package
├── src/
│   ├── config.ts              # i18next initialization
│   ├── types.ts               # SupportedLanguage, LANGUAGE_INFO
│   ├── provider.tsx           # I18nProvider component
│   ├── hooks/useLanguage.ts   # Language preference hook
│   └── utils/
│       ├── setLanguage.ts     # Simple language switcher
│       └── dateLocale.ts      # date-fns locale helper

apps/raamattu-nyt/public/locales/   # Translation files (lazy-loaded)
├── fi/
│   ├── common.json            # Shared UI strings
│   └── profile.json           # Profile page strings
└── en/
    ├── common.json
    └── profile.json

Quick Reference

Add translation to existing namespace

  1. Add key to both locale files:
// public/locales/fi/common.json
{ "myKey": "Suomeksi" }

// public/locales/en/common.json
{ "myKey": "In English" }
  1. Use in component:
import { useTranslation } from '@shared-i18n/index';

const { t } = useTranslation('common');
return <span>{t('myKey')}</span>;

Create new namespace

  1. Add namespace to packages/shared-i18n/src/config.ts:
ns: ['common', 'profile', 'newNamespace'],
  1. Create files: public/locales/{fi,en}/newNamespace.json

  2. Use: const { t } = useTranslation('newNamespace');

Add new language

  1. Update packages/shared-i18n/src/types.ts:
export type SupportedLanguage = 'fi' | 'en' | 'sv';
export const SUPPORTED_LANGUAGES = ['fi', 'en', 'sv'] as const;
export const LANGUAGE_INFO = {
  fi: { code: 'fi', name: 'Finnish', nativeName: 'Suomi' },
  en: { code: 'en', name: 'English', nativeName: 'English' },
  sv: { code: 'sv', name: 'Swedish', nativeName: 'Svenska' },
};
  1. Update DB constraint in new migration:
ALTER TABLE public.profiles
DROP CONSTRAINT profiles_language_preference_check,
ADD CONSTRAINT profiles_language_preference_check
CHECK (language_preference IN ('fi', 'en', 'sv'));
  1. Create locale files: public/locales/sv/*.json

  2. Update dateLocale.ts with new locale import

Translation Patterns

Interpolation

{ "greeting": "Hello, {{name}}!" }
t('greeting', { name: 'John' })

Pluralization

{
  "item_one": "{{count}} item",
  "item_other": "{{count}} items"
}
t('item', { count: 5 })

Nested keys

{ "nav": { "home": "Home", "settings": "Settings" } }
t('nav.home')

Trans component (JSX interpolation)

import { Trans } from '@shared-i18n/index';

<Trans i18nKey="terms" t={t}>
  By continuing you agree to our <Link to="/terms">terms</Link>.
</Trans>

Migration Workflow

When migrating a component to i18n:

  1. Identify all user-visible strings
  2. Create translation keys (use descriptive, nested structure)
  3. Add to appropriate namespace (common for shared, feature-specific otherwise)
  4. Replace inline strings with t() calls
  5. Test both languages

Example migration:

// Before
<Button>Tallenna</Button>

// After
const { t } = useTranslation('common');
<Button>{t('common.save')}</Button>

Cross-cutting learnings: See .claude/LEARNINGS.md → "i18n/Translations" section for namespace patterns and useTranslation gotchas.

Files Reference

For detailed API and patterns, see references/i18n-api.md.