{"_id":"@beluga-labs/i18n","_rev":"3-da8c25695c40e791c5f421362e082f86","name":"@beluga-labs/i18n","dist-tags":{"latest":"2.0.1"},"versions":{"2.0.0":{"name":"@beluga-labs/i18n","version":"2.0.0","keywords":["i18n","internationalization","translations","react","react-hooks","nextjs","remix","gatsby","vite","create-react-app","react-framework"],"author":{"name":"beluga labs"},"license":"MIT","_id":"@beluga-labs/i18n@2.0.0","maintainers":[{"name":"beluga-digital","email":"d.baumert96@gmail.com"}],"homepage":"https://github.com/beluga-labs/i18n#readme","bugs":{"url":"https://github.com/beluga-labs/i18n/issues"},"dist":{"shasum":"402560fa047289dc6ea53586a3e82feb76a42db4","tarball":"https://registry.npmjs.org/@beluga-labs/i18n/-/i18n-2.0.0.tgz","fileCount":30,"integrity":"sha512-3jGKOk4quR5L1O6yvDj8KD1nwV4BJo22srIb4r6VhmZBFY5TZY7l1tfeOmWfTDUH/NF3y4lVsoDHJ/3l4XPkYA==","signatures":[{"sig":"MEUCIDIq7XFM0vuGTU4G8UEPyFi11vwWWKR2w1qDcFBemDgSAiEAiQxfTWomDyO1N2sFsKHnW3/PiIxbx4Xt0qgIJrHA/qM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":74121},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"980d1039dccb9eb0b3b92269c395d54206abd32b","scripts":{"test":"vitest run","build":"rm -rf dist && rollup -c","format":"prettier --write \"**/*.{ts,tsx,md}\"","example":"cd example && vite","test:watch":"vitest","format-watch":"onchange \"**/*.{ts,tsx,md}\" -- prettier --write --ignore-unknown {{changed}}"},"_npmUser":{"name":"beluga-digital","email":"d.baumert96@gmail.com"},"repository":{"url":"git+https://github.com/beluga-labs/i18n.git","type":"git"},"_npmVersion":"11.6.2","description":"Internationalization support for React applications with translation management","directories":{},"_nodeVersion":"25.1.0","dependencies":{"react":"^19.2.3","html-react-parser":"^5.2.11"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","jsdom":"^27.3.0","react":"^19.0.0","tslib":"^2.8.1","rollup":"^4.53.5","vitest":"^4.0.16","prettier":"^3.7.4","react-dom":"^19.0.0","typescript":"^5.9.3","@types/react":"^19.0.0","@types/react-dom":"^19.2.3","rollup-plugin-dts":"^6.3.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.0.0","@rollup/plugin-typescript":"^12.3.0","@testing-library/jest-dom":"^6.9.1","@rollup/plugin-node-resolve":"^16.0.3"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/i18n_2.0.0_1766220791607_0.3776035236852098","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Moved to @mantaray0/i18n"},"2.0.1":{"name":"@beluga-labs/i18n","version":"2.0.1","keywords":["i18n","internationalization","translations","react","react-hooks","nextjs","remix","gatsby","vite","create-react-app","react-framework"],"author":{"name":"beluga labs"},"license":"MIT","_id":"@beluga-labs/i18n@2.0.1","maintainers":[{"name":"beluga-digital","email":"d.baumert96@gmail.com"}],"homepage":"https://github.com/beluga-labs/i18n#readme","bugs":{"url":"https://github.com/beluga-labs/i18n/issues"},"dist":{"shasum":"4447ebd2e3fdccb1d1f60456445c66da74bf5e21","tarball":"https://registry.npmjs.org/@beluga-labs/i18n/-/i18n-2.0.1.tgz","fileCount":29,"integrity":"sha512-Q4kVZBO7QBVwz86owAgoqvI7I/rVP95qMJrQ5bWPd7I3Lwr3GcyJ46yYeamlDdCooSTNv9UoRhZbphB3D0R7+g==","signatures":[{"sig":"MEYCIQC9GJrBHLAWR8Vh4Ed5TzUiNThSVTWKMIqcsj7AeOFTQwIhAOS4os/pLanUCOO1Gha5STeDGG51xwJMBLLd7lVPckmG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2094588},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"40238d68f936060e3968016b792769979c3a53a9","scripts":{"test":"vitest run","build":"rm -rf dist && rollup -c","format":"prettier --write .","example":"cd example && vite","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"pnpm build"},"_npmUser":{"name":"beluga-digital","email":"d.baumert96@gmail.com"},"repository":{"url":"git+https://github.com/beluga-labs/i18n.git","type":"git"},"_npmVersion":"11.6.2","description":"Internationalization support for React applications with translation management","directories":{},"_nodeVersion":"25.1.0","dependencies":{"react":"^19.2.3","html-react-parser":"^5.2.11"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.0","jsdom":"^27.3.0","react":"^19.0.0","tslib":"^2.8.1","rollup":"^4.53.5","vitest":"^4.0.16","prettier":"^3.7.4","react-dom":"^19.0.0","typescript":"^5.9.3","@types/react":"^19.0.0","@types/react-dom":"^19.2.3","rollup-plugin-dts":"^6.3.0","@vitejs/plugin-react":"^5.1.2","@testing-library/react":"^16.0.0","@rollup/plugin-commonjs":"^29.0.0","@rollup/plugin-typescript":"^12.3.0","@testing-library/jest-dom":"^6.9.1","@rollup/plugin-node-resolve":"^16.0.3"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/i18n_2.0.1_1766258708495_0.8699136686453057","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Moved to @mantaray0/i18n"}},"time":{"created":"2025-12-20T08:53:11.510Z","modified":"2026-02-13T19:45:58.197Z","2.0.0":"2025-12-20T08:53:11.812Z","2.0.1":"2025-12-20T19:25:08.660Z"},"bugs":{"url":"https://github.com/beluga-labs/i18n/issues"},"author":{"name":"beluga labs"},"license":"MIT","homepage":"https://github.com/beluga-labs/i18n#readme","keywords":["i18n","internationalization","translations","react","react-hooks","nextjs","remix","gatsby","vite","create-react-app","react-framework"],"repository":{"url":"git+https://github.com/beluga-labs/i18n.git","type":"git"},"description":"Internationalization support for React applications with translation management","maintainers":[{"name":"beluga-digital","email":"d.baumert96@gmail.com"}],"readme":"# @beluga-labs/i18n\n\nInternationalization support for React applications with translation management. Works with any React framework including Next.js, Remix, Gatsby, Vite, Create React App, and any other React-based application.\n\n## Features\n\n- **Lightweight**: Minimal bundle size with zero runtime dependencies\n- **Flexible**: Support for nested translation keys and variable interpolation\n- **HTML Support**: Optional HTML parsing for rich text translations\n- **Type Safe**: Full TypeScript support\n- **Dynamic Language Switching**: Change languages at runtime\n- **Simple API**: Clean and intuitive translation hook\n\n## Installation\n\n```bash\nnpm install @beluga-labs/i18n\n# or\npnpm add @beluga-labs/i18n\n# or\nyarn add @beluga-labs/i18n\n```\n\n## What is this package?\n\nWhen building React applications, you often need to support multiple languages. This package provides a simple and flexible way to manage translations with support for:\n\n- Nested translation keys\n- Variable interpolation\n- HTML parsing\n- Dynamic language switching\n- TypeScript support\n\n## Usage\n\n### Basic Setup\n\nWrap your application with the `TranslationProvider`:\n\n```tsx\nimport { TranslationProvider, useTranslation } from '@beluga-labs/i18n';\n\nconst translations = {\n  en: {\n    welcome: 'Welcome to our app!',\n    greeting: 'Hello, {name}!',\n    description: 'This is a <strong>great</strong> app.',\n    nested: {\n      key: 'This is a nested translation'\n    }\n  },\n  de: {\n    welcome: 'Willkommen in unserer App!',\n    greeting: 'Hallo, {name}!',\n    description: 'Das ist eine <strong>tolle</strong> App.',\n    nested: {\n      key: 'Das ist eine verschachtelte Übersetzung'\n    }\n  }\n};\n\nfunction App() {\n  return (\n    <TranslationProvider\n      translations={translations}\n      locale=\"en\">\n      <YourApp />\n    </TranslationProvider>\n  );\n}\n```\n\n### Using Translations\n\nUse the `useTranslation` hook in any component:\n\n```tsx\nimport { useTranslation } from '@beluga-labs/i18n';\n\nfunction WelcomeComponent() {\n  const { t, changeLanguage } = useTranslation();\n\n  return (\n    <div>\n      <h1>{t('welcome')}</h1>\n      <p>{t('greeting', { name: 'John' })}</p>\n      <div>{t('description')}</div>\n      <p>{t('nested.key')}</p>\n\n      <button onClick={() => changeLanguage('de')}>Switch to German</button>\n    </div>\n  );\n}\n```\n\n## API Reference\n\n### TranslationProvider\n\nThe main provider component that wraps your application and provides translation context.\n\n#### Props\n\n| Prop           | Type                  | Required | Description                                                |\n| -------------- | --------------------- | -------- | ---------------------------------------------------------- |\n| `translations` | `Record<string, any>` | ✅       | Object containing translations for all supported languages |\n| `locale`       | `string`              | ✅       | Initial language code (e.g., 'en', 'de', 'fr')             |\n| `reloadKey`    | `string \\| number`    | ❌       | Optional key to force reload translations                  |\n| `children`     | `ReactNode`           | ✅       | Your application components                                |\n\n#### Example\n\n```tsx\n<TranslationProvider\n  translations={translations}\n  locale=\"en\"\n  reloadKey={reloadKey} // Optional\n>\n  {children}\n</TranslationProvider>\n```\n\n### useTranslation Hook\n\nReturns translation functions and language utilities.\n\n#### Returns\n\n| Property         | Type                                                                         | Description                             |\n| ---------------- | ---------------------------------------------------------------------------- | --------------------------------------- |\n| `t`              | `(key: string, variables?: Record<string, any>, parseHtml?: boolean) => any` | Translation function                    |\n| `changeLanguage` | `(lang: string) => void`                                                     | Function to change the current language |\n\n#### Translation Function Parameters\n\n| Parameter   | Type                  | Default | Description                                              |\n| ----------- | --------------------- | ------- | -------------------------------------------------------- |\n| `key`       | `string`              | -       | Translation key (supports nested keys with dot notation) |\n| `variables` | `Record<string, any>` | `{}`    | Variables to interpolate into the translation            |\n| `parseHtml` | `boolean`             | `true`  | Whether to parse HTML in the translation                 |\n\n## Advanced Usage\n\n### Nested Translation Keys\n\nYou can organize your translations in nested objects and access them using dot notation:\n\n```tsx\nconst translations = {\n  en: {\n    common: {\n      buttons: {\n        save: 'Save',\n        cancel: 'Cancel',\n        delete: 'Delete'\n      },\n      messages: {\n        success: 'Operation completed successfully',\n        error: 'An error occurred'\n      }\n    }\n  }\n};\n\n// Usage\nconst { t } = useTranslation();\nt('common.buttons.save'); // \"Save\"\nt('common.messages.success'); // \"Operation completed successfully\"\n```\n\n### Variable Interpolation\n\nYou can include variables in your translations using curly braces:\n\n```tsx\nconst translations = {\n  en: {\n    greeting: 'Hello, {name}!',\n    items: 'You have {count} items in your cart',\n    welcome: 'Welcome back, {firstName} {lastName}!'\n  }\n};\n\n// Usage\nconst { t } = useTranslation();\nt('greeting', { name: 'John' }); // \"Hello, John!\"\nt('items', { count: 5 }); // \"You have 5 items in your cart\"\nt('welcome', { firstName: 'John', lastName: 'Doe' }); // \"Welcome back, John Doe!\"\n```\n\n### HTML Parsing\n\nBy default, HTML in translations is automatically parsed. You can disable this behavior:\n\n```tsx\nconst translations = {\n  en: {\n    description: 'This is a <strong>bold</strong> text with <em>emphasis</em>.',\n    link: 'Click <a href=\"/help\">here</a> for help.'\n  }\n};\n\n// Usage\nconst { t } = useTranslation();\nt('description'); // Renders as HTML: This is a <strong>bold</strong> text with <em>emphasis</em>.\nt('description', {}, false); // Returns raw string: \"This is a <strong>bold</strong> text with <em>emphasis</em>.\"\n```\n\n### Dynamic Language Switching\n\nYou can change the language at runtime:\n\n```tsx\nfunction LanguageSwitcher() {\n  const { changeLanguage } = useTranslation();\n\n  return (\n    <div>\n      <button onClick={() => changeLanguage('en')}>English</button>\n      <button onClick={() => changeLanguage('de')}>Deutsch</button>\n      <button onClick={() => changeLanguage('fr')}>Français</button>\n    </div>\n  );\n}\n```\n\n### Controlled Reloading\n\nUse the `reloadKey` prop to force a reload of translations:\n\n```tsx\nfunction App() {\n  const [reloadKey, setReloadKey] = useState(0);\n\n  const handleReloadTranslations = () => {\n    setReloadKey((prev) => prev + 1);\n  };\n\n  return (\n    <TranslationProvider\n      translations={translations}\n      locale=\"en\"\n      reloadKey={reloadKey}>\n      <YourApp />\n      <button onClick={handleReloadTranslations}>Reload Translations</button>\n    </TranslationProvider>\n  );\n}\n```\n\n## Framework Integration\n\nThis package works with any React framework. Here are examples for popular frameworks:\n\n### Next.js\n\n#### App Router (Next.js 13+)\n\nFor Next.js 13+ with the app directory:\n\n```tsx\n// app/layout.tsx\n'use client';\n\nimport { TranslationProvider } from '@beluga-labs/i18n';\n\nexport default function RootLayout({\n  children\n}: {\n  children: React.ReactNode;\n}) {\n  return (\n    <html lang=\"en\">\n      <body>\n        <TranslationProvider\n          translations={translations}\n          locale=\"en\">\n          {children}\n        </TranslationProvider>\n      </body>\n    </html>\n  );\n}\n```\n\n#### Pages Router\n\nFor traditional Next.js pages:\n\n```tsx\n// pages/_app.tsx\nimport { TranslationProvider } from '@beluga-labs/i18n';\nimport type { AppProps } from 'next/app';\n\nexport default function App({ Component, pageProps }: AppProps) {\n  return (\n    <TranslationProvider\n      translations={translations}\n      locale=\"en\">\n      <Component {...pageProps} />\n    </TranslationProvider>\n  );\n}\n```\n\n### Remix\n\n```tsx\n// app/root.tsx\nimport { TranslationProvider } from '@beluga-labs/i18n';\n\nexport default function App() {\n  return (\n    <html>\n      <body>\n        <TranslationProvider\n          translations={translations}\n          locale=\"en\">\n          <Outlet />\n        </TranslationProvider>\n      </body>\n    </html>\n  );\n}\n```\n\n### Vite / Create React App\n\n```tsx\n// src/main.tsx or src/index.tsx\nimport { TranslationProvider } from '@beluga-labs/i18n';\nimport React from 'react';\nimport ReactDOM from 'react-dom/client';\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n  <React.StrictMode>\n    <TranslationProvider\n      translations={translations}\n      locale=\"en\">\n      <App />\n    </TranslationProvider>\n  </React.StrictMode>\n);\n```\n\n### Gatsby\n\n```tsx\n// gatsby-browser.js or gatsby-ssr.js\nimport { TranslationProvider } from '@beluga-labs/i18n';\nimport React from 'react';\n\nexport const wrapRootElement = ({ element }) => (\n  <TranslationProvider\n    translations={translations}\n    locale=\"en\">\n    {element}\n  </TranslationProvider>\n);\n```\n\n### Any React Application\n\nSince this package is framework-agnostic, you can use it anywhere React components are used:\n\n```tsx\nimport { TranslationProvider } from '@beluga-labs/i18n';\n\nfunction App() {\n  return (\n    <TranslationProvider\n      translations={translations}\n      locale=\"en\">\n      <YourApp />\n    </TranslationProvider>\n  );\n}\n```\n\n## TypeScript Support\n\nFull TypeScript support is included. You can type your translations for better development experience:\n\n```tsx\ninterface Translations {\n  en: {\n    welcome: string;\n    greeting: string;\n    nested: {\n      key: string;\n    };\n  };\n  de: {\n    welcome: string;\n    greeting: string;\n    nested: {\n      key: string;\n    };\n  };\n}\n\nconst translations: Translations = {\n  en: {\n    welcome: 'Welcome!',\n    greeting: 'Hello, {name}!',\n    nested: {\n      key: 'Nested translation'\n    }\n  },\n  de: {\n    welcome: 'Willkommen!',\n    greeting: 'Hallo, {name}!',\n    nested: {\n      key: 'Verschachtelte Übersetzung'\n    }\n  }\n};\n```\n\n## Best Practices\n\n### 1. Organize Your Translations\n\nKeep your translations well-organized and use consistent naming conventions:\n\n```tsx\nconst translations = {\n  en: {\n    common: {\n      buttons: {\n        /* button texts */\n      },\n      messages: {\n        /* status messages */\n      },\n      errors: {\n        /* error messages */\n      }\n    },\n    pages: {\n      home: {\n        /* home page texts */\n      },\n      about: {\n        /* about page texts */\n      }\n    }\n  }\n};\n```\n\n### 2. Use Meaningful Keys\n\nChoose descriptive and consistent translation keys:\n\n```tsx\n// Good\nt('common.buttons.save');\nt('pages.home.welcome.title');\n\n// Avoid\nt('btn1');\nt('text1');\n```\n\n### 3. Missing Translation Handling\n\nThe hook automatically handles missing translations by:\n\n- Returning `[key]` as a fallback when a translation is missing\n- Logging a warning in development (localhost) to help identify missing translations\n- Providing clear visual feedback in the UI\n\n```tsx\nconst { t } = useTranslation();\n\n// If 'welcome.message' is missing, it will return '[welcome.message]'\n// and log a warning in development\nt('welcome.message'); // Returns '[welcome.message]' if missing\n```\n\n### 4. Performance Considerations\n\n- Keep your translation objects as small as possible\n- Consider code-splitting translations by route or feature\n- Use the `reloadKey` prop sparingly\n\n## Migration Guide\n\n### Migrating from 1.0.1 to 2.0.0\n\nVersion 2.0.0 introduces several breaking changes. Follow this guide to update your code:\n\n#### 1. Package Name Change\n\nThe package has been renamed from `beluga-i18n` to `@beluga-labs/i18n`.\n\n**Before:**\n\n```bash\nnpm install beluga-i18n\n```\n\n**After:**\n\n```bash\nnpm install @beluga-labs/i18n\n```\n\n**Update imports:**\n\n```tsx\n// Before\nimport { TranslationsProvider, useTranslation } from 'beluga-i18n';\n\n// After\nimport { TranslationProvider, useTranslation } from '@beluga-labs/i18n';\n```\n\n#### 2. Component Rename\n\nThe main provider component has been renamed from `TranslationsProvider` (plural) to `TranslationProvider` (singular).\n\n**Before:**\n\n```tsx\nimport { TranslationsProvider } from 'beluga-i18n';\n\n<TranslationsProvider\n  translations={translations}\n  locale=\"en\">\n  {children}\n</TranslationsProvider>;\n```\n\n**After:**\n\n```tsx\nimport { TranslationProvider } from '@beluga-labs/i18n';\n\n<TranslationProvider\n  translations={translations}\n  locale=\"en\">\n  {children}\n</TranslationProvider>;\n```\n\n#### 3. Context and Type Names\n\nAll related types and context names have been updated to use singular form:\n\n- `TranslationsContext` → `TranslationContext`\n- `TranslationsContextProps` → `TranslationContextProps`\n- `TranslationsProviderProps` → `TranslationProviderProps`\n\nIf you were using these types directly, update your imports:\n\n```tsx\n// Before\nimport { TranslationsContext, TranslationsProviderProps } from 'beluga-i18n';\n\n// After\nimport {\n  TranslationContext,\n  TranslationProviderProps\n} from '@beluga-labs/i18n';\n```\n\n#### Summary of Changes\n\n| Item               | Before (1.0.1)         | After (2.0.0)         |\n| ------------------ | ---------------------- | --------------------- |\n| Package name       | `beluga-i18n`          | `@beluga-labs/i18n`   |\n| Provider component | `TranslationsProvider` | `TranslationProvider` |\n| Context            | `TranslationsContext`  | `TranslationContext`  |\n| Build system       | `tsup`                 | `rollup`              |\n\n#### Migration Checklist\n\n- [ ] Update package name in `package.json`\n- [ ] Update all imports from `beluga-i18n` to `@beluga-labs/i18n`\n- [ ] Rename `TranslationsProvider` to `TranslationProvider` in all files\n- [ ] Update any direct usage of context or types\n- [ ] Test your application thoroughly\n\n## Contributing\n\nWe welcome contributions! Please see our [contributing guidelines](CONTRIBUTING.md) for more details.\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n","readmeFilename":"README.md"}