{"_id":"@c-a-f/i18n","_rev":"2-152432d8d97caa7858b7e571abf23d0a","name":"@c-a-f/i18n","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@c-a-f/i18n","version":"1.0.0","keywords":["clean-architecture-frontend","clean-architecture","caf","i18n","internationalization","translation","i18next","vue-i18n","ngx-translate","react-intl","next-intl"],"author":{"name":"ali aslani","email":"aliaslani.mm@gmail.com"},"license":"MIT","_id":"@c-a-f/i18n@1.0.0","maintainers":[{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"}],"homepage":"https://github.com/ialiaslani/caf#readme","bugs":{"url":"https://github.com/ialiaslani/caf/issues"},"dist":{"shasum":"e9e096e8d711cfd295c9037d3c347a64647ec179","tarball":"https://registry.npmjs.org/@c-a-f/i18n/-/i18n-1.0.0.tgz","fileCount":26,"integrity":"sha512-faE1fHTj7VlLqZmTL0ukhyfbcupev/YjFbcnq1JlnuzaHDyaye06BtzZh+gbaOH0NPHFt6uL6wva0YMr4rTtDA==","signatures":[{"sig":"MEYCIQD5HhoYOdFdo+0ZzEwFzz2tGt0TIUTGq+wGtaxgVQL+UgIhANj1cmDSRHTJmDZX3QaevshRBSaeDras9Lr6Q9afrZke","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":40093},"main":"./.build/index.js","type":"module","types":"./.build/index.d.ts","module":"./.build/index.js","exports":{".":{"node":"./.build/index.js","types":"./.build/index.d.ts","import":"./.build/index.js","default":"./.build/index.js"},"./i18next":{"node":"./.build/src/adapters/i18next.js","types":"./.build/src/adapters/i18next.d.ts","import":"./.build/src/adapters/i18next.js","default":"./.build/src/adapters/i18next.js"},"./intl-api":{"node":"./.build/src/adapters/intl-api.js","types":"./.build/src/adapters/intl-api.d.ts","import":"./.build/src/adapters/intl-api.js","default":"./.build/src/adapters/intl-api.js"},"./vue-i18n":{"node":"./.build/src/adapters/vue-i18n.js","types":"./.build/src/adapters/vue-i18n.d.ts","import":"./.build/src/adapters/vue-i18n.js","default":"./.build/src/adapters/vue-i18n.js"},"./next-intl":{"node":"./.build/src/adapters/next-intl.js","types":"./.build/src/adapters/next-intl.d.ts","import":"./.build/src/adapters/next-intl.js","default":"./.build/src/adapters/next-intl.js"},"./react-intl":{"node":"./.build/src/adapters/react-intl.js","types":"./.build/src/adapters/react-intl.d.ts","import":"./.build/src/adapters/react-intl.js","default":"./.build/src/adapters/react-intl.js"},"./ngx-translate":{"node":"./.build/src/adapters/ngx-translate.js","types":"./.build/src/adapters/ngx-translate.d.ts","import":"./.build/src/adapters/ngx-translate.js","default":"./.build/src/adapters/ngx-translate.js"}},"gitHead":"ca2feba4757534a4a130717ea50c4df2e2ff01e6","scripts":{"test":"vitest run","build":"tsc --build","start":"tsc --watch","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"},"repository":{"url":"git+https://github.com/ialiaslani/caf.git","type":"git"},"_npmVersion":"10.9.2","description":"Framework-agnostic internationalization interfaces and adapters for CAF. Works with i18next, vue-i18n, ngx-translate, react-intl, next-intl, or any i18n library.","directories":{},"_nodeVersion":"22.13.0","dependencies":{"@c-a-f/core":"1.0.3"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.0","@vitest/coverage-v8":"^2.1.0"},"peerDependencies":{"i18next":"*","vue-i18n":"*","next-intl":"*","react-intl":"*","@ngx-translate/core":"*"},"peerDependenciesMeta":{"i18next":{"optional":true},"vue-i18n":{"optional":true},"next-intl":{"optional":true},"react-intl":{"optional":true},"@ngx-translate/core":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/i18n_1.0.0_1771671115296_0.40929698509951007","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@c-a-f/i18n","type":"module","version":"1.0.1","description":"Framework-agnostic internationalization interfaces and adapters for CAF. Works with i18next, vue-i18n, ngx-translate, react-intl, next-intl, or any i18n library.","keywords":["clean-architecture-frontend","clean-architecture","caf","i18n","internationalization","translation","i18next","vue-i18n","ngx-translate","react-intl","next-intl"],"author":{"name":"ali aslani","email":"aliaslani.mm@gmail.com"},"license":"MIT","homepage":"https://docs-caf.vercel.app/docs/packages/i18n","repository":{"type":"git","url":"git+https://github.com/ialiaslani/caf.git"},"main":"./.build/index.js","module":"./.build/index.js","types":"./.build/index.d.ts","exports":{".":{"types":"./.build/index.d.ts","import":"./.build/index.js","node":"./.build/index.js","default":"./.build/index.js"},"./i18next":{"types":"./.build/src/adapters/i18next.d.ts","import":"./.build/src/adapters/i18next.js","node":"./.build/src/adapters/i18next.js","default":"./.build/src/adapters/i18next.js"},"./vue-i18n":{"types":"./.build/src/adapters/vue-i18n.d.ts","import":"./.build/src/adapters/vue-i18n.js","node":"./.build/src/adapters/vue-i18n.js","default":"./.build/src/adapters/vue-i18n.js"},"./ngx-translate":{"types":"./.build/src/adapters/ngx-translate.d.ts","import":"./.build/src/adapters/ngx-translate.js","node":"./.build/src/adapters/ngx-translate.js","default":"./.build/src/adapters/ngx-translate.js"},"./react-intl":{"types":"./.build/src/adapters/react-intl.d.ts","import":"./.build/src/adapters/react-intl.js","node":"./.build/src/adapters/react-intl.js","default":"./.build/src/adapters/react-intl.js"},"./next-intl":{"types":"./.build/src/adapters/next-intl.d.ts","import":"./.build/src/adapters/next-intl.js","node":"./.build/src/adapters/next-intl.js","default":"./.build/src/adapters/next-intl.js"},"./intl-api":{"types":"./.build/src/adapters/intl-api.d.ts","import":"./.build/src/adapters/intl-api.js","node":"./.build/src/adapters/intl-api.js","default":"./.build/src/adapters/intl-api.js"}},"scripts":{"build":"tsc --build","start":"tsc --watch","prepublishOnly":"npm run build","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage"},"dependencies":{"@c-a-f/core":"1.0.3"},"peerDependencies":{"i18next":"*","vue-i18n":"*","@ngx-translate/core":"*","react-intl":"*","next-intl":"*"},"peerDependenciesMeta":{"i18next":{"optional":true},"vue-i18n":{"optional":true},"@ngx-translate/core":{"optional":true},"react-intl":{"optional":true},"next-intl":{"optional":true}},"devDependencies":{"@vitest/coverage-v8":"^2.1.0","vitest":"^2.1.0"},"_id":"@c-a-f/i18n@1.0.1","gitHead":"c754b6d68b1a5b1196bb202e70c962ea7c3de87e","bugs":{"url":"https://github.com/ialiaslani/caf/issues"},"_nodeVersion":"22.13.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-gb0CBy38lpYlcaHxMAiztQZDKJNK4Ml2uz8Fd5MjXlTwUp9qjfE8Dj2K7t/J122qwno7bm1LAsHmZk4ofMhqvw==","shasum":"a5a1d959463c2f521ef688cb8862161db4a0abb7","tarball":"https://registry.npmjs.org/@c-a-f/i18n/-/i18n-1.0.1.tgz","fileCount":26,"unpackedSize":40414,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIA6MpVQ/FHf9PnQrF3eYEdWwf57bIQ8cNZDXiKj4Fd8xAiEA/AFjSYUsL+TrnzNTtavtRGlhlNFsmeMgWe91gvtYNFA="}]},"_npmUser":{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"},"directories":{},"maintainers":[{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/i18n_1.0.1_1771679856866_0.3202819936600856"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-21T10:51:55.219Z","modified":"2026-02-21T13:17:37.135Z","1.0.0":"2026-02-21T10:51:55.441Z","1.0.1":"2026-02-21T13:17:36.991Z"},"bugs":{"url":"https://github.com/ialiaslani/caf/issues"},"author":{"name":"ali aslani","email":"aliaslani.mm@gmail.com"},"license":"MIT","homepage":"https://docs-caf.vercel.app/docs/packages/i18n","keywords":["clean-architecture-frontend","clean-architecture","caf","i18n","internationalization","translation","i18next","vue-i18n","ngx-translate","react-intl","next-intl"],"repository":{"type":"git","url":"git+https://github.com/ialiaslani/caf.git"},"description":"Framework-agnostic internationalization interfaces and adapters for CAF. Works with i18next, vue-i18n, ngx-translate, react-intl, next-intl, or any i18n library.","maintainers":[{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"}],"readme":"# @c-a-f/i18n\r\n\r\nFramework-agnostic internationalization interfaces and adapters for CAF. Works with i18next, vue-i18n, ngx-translate, or any i18n library.\r\n\r\n**Documentation:** [@c-a-f/i18n docs](https://docs-caf.vercel.app/docs/packages/i18n)\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @c-a-f/i18n\r\n```\r\n\r\nFor i18next integration:\r\n```bash\r\nnpm install @c-a-f/i18n i18next\r\n```\r\n\r\nFor vue-i18n integration:\r\n```bash\r\nnpm install @c-a-f/i18n vue-i18n\r\n```\r\n\r\nFor ngx-translate integration:\r\n```bash\r\nnpm install @c-a-f/i18n @ngx-translate/core\r\n```\r\n\r\nFor react-intl integration:\r\n```bash\r\nnpm install @c-a-f/i18n react-intl\r\n```\r\n\r\nFor next-intl integration:\r\n```bash\r\nnpm install @c-a-f/i18n next-intl\r\n```\r\n\r\nNote: The Intl API adapter doesn't require any additional dependencies as it uses native browser APIs.\r\n\r\n## Usage\r\n\r\n### Core Interfaces\r\n\r\nThe package provides framework-agnostic interfaces that work with any i18n library:\r\n\r\n```typescript\r\nimport { ITranslator, TranslationOptions, TranslationManager } from '@c-a-f/i18n';\r\n\r\n// ITranslator interface can be implemented by any i18n library adapter\r\ninterface ITranslator {\r\n  translate(key: string, options?: TranslationOptions): string;\r\n  getCurrentLanguage(): string;\r\n  changeLanguage(language: string): Promise<void> | void;\r\n  exists(key: string): boolean;\r\n}\r\n```\r\n\r\n### Translation Manager\r\n\r\nUse `TranslationManager` to provide convenient methods for translation:\r\n\r\n```typescript\r\nimport { TranslationManager, ITranslator } from '@c-a-f/i18n';\r\n\r\n// Create a translator implementation\r\nclass MyTranslator implements ITranslator {\r\n  translate(key: string, options?: TranslationOptions): string {\r\n    // Your translation logic\r\n  }\r\n  getCurrentLanguage(): string { return 'en'; }\r\n  changeLanguage(language: string): Promise<void> { /* ... */ }\r\n  exists(key: string): boolean { return true; }\r\n}\r\n\r\n// Use TranslationManager\r\nconst translator = new MyTranslator();\r\nconst translationManager = new TranslationManager(translator);\r\n\r\n// Simple translation\r\nconst greeting = translationManager.t('common.greeting');\r\n\r\n// Translation with interpolation\r\nconst welcome = translationManager.translateWithValues('user.welcome', {\r\n  name: 'John',\r\n});\r\n\r\n// Translation with pluralization\r\nconst items = translationManager.translatePlural('cart.items', 5);\r\n\r\n// Change language\r\nawait translationManager.changeLanguage('fa');\r\n```\r\n\r\n## Integration with i18next\r\n\r\n```typescript\r\nimport i18n from 'i18next';\r\nimport { I18nextTranslator } from '@c-a-f/i18n/i18next';\r\nimport { TranslationManager } from '@c-a-f/i18n';\r\n\r\n// Initialize i18next\r\nawait i18n.init({\r\n  resources: {\r\n    en: { translation: { greeting: 'Hello' } },\r\n    fa: { translation: { greeting: 'سلام' } },\r\n  },\r\n  lng: 'en',\r\n});\r\n\r\n// Create translator adapter\r\nconst translator = new I18nextTranslator(i18n);\r\nconst translationManager = new TranslationManager(translator);\r\n\r\n// Use in your application\r\nconst greeting = translationManager.t('greeting');\r\nawait translationManager.changeLanguage('fa');\r\n```\r\n\r\n## Integration with vue-i18n\r\n\r\n```typescript\r\nimport { createI18n } from 'vue-i18n';\r\nimport { VueI18nTranslator } from '@c-a-f/i18n/vue-i18n';\r\nimport { TranslationManager } from '@c-a-f/i18n';\r\n\r\n// Initialize vue-i18n\r\nconst i18n = createI18n({\r\n  locale: 'en',\r\n  messages: {\r\n    en: { greeting: 'Hello' },\r\n    fa: { greeting: 'سلام' },\r\n  },\r\n});\r\n\r\n// Create translator adapter\r\nconst translator = new VueI18nTranslator(i18n.global);\r\nconst translationManager = new TranslationManager(translator);\r\n\r\n// Use in your application\r\nconst greeting = translationManager.t('greeting');\r\nawait translationManager.changeLanguage('fa');\r\n```\r\n\r\n## Integration with ngx-translate\r\n\r\n```typescript\r\nimport { TranslateService } from '@ngx-translate/core';\r\nimport { NgxTranslateTranslator } from '@c-a-f/i18n/ngx-translate';\r\nimport { TranslationManager } from '@c-a-f/i18n';\r\n\r\n// In Angular service/component\r\nexport class MyComponent {\r\n  private translationManager: TranslationManager;\r\n\r\n  constructor(private translate: TranslateService) {\r\n    // Create translator adapter\r\n    const translator = new NgxTranslateTranslator(translate);\r\n    this.translationManager = new TranslationManager(translator);\r\n  }\r\n\r\n  ngOnInit() {\r\n    // Use in your application\r\n    const greeting = this.translationManager.t('greeting');\r\n    this.translationManager.changeLanguage('fa');\r\n  }\r\n}\r\n```\r\n\r\n## Integration with react-intl\r\n\r\n```typescript\r\nimport { IntlProvider, useIntl } from 'react-intl';\r\nimport { ReactIntlTranslator } from '@c-a-f/i18n/react-intl';\r\nimport { TranslationManager } from '@c-a-f/i18n';\r\n\r\n// In your React component\r\nfunction MyComponent() {\r\n  const intl = useIntl();\r\n  const translator = new ReactIntlTranslator(intl);\r\n  const translationManager = new TranslationManager(translator);\r\n\r\n  // Use in your application\r\n  const greeting = translationManager.t('common.greeting');\r\n  const welcome = translationManager.translateWithValues('common.welcome', {\r\n    name: 'John',\r\n  });\r\n\r\n  return <div>{greeting}</div>;\r\n}\r\n\r\n// Wrap your app with IntlProvider\r\nfunction App() {\r\n  return (\r\n    <IntlProvider locale=\"en\" messages={messages}>\r\n      <MyComponent />\r\n    </IntlProvider>\r\n  );\r\n}\r\n```\r\n\r\n## Integration with next-intl\r\n\r\n```typescript\r\nimport { useTranslations } from 'next-intl';\r\nimport { NextIntlTranslator } from '@c-a-f/i18n/next-intl';\r\nimport { TranslationManager } from '@c-a-f/i18n';\r\n\r\n// In your Next.js component\r\nexport default function MyComponent() {\r\n  const t = useTranslations();\r\n  const locale = useLocale(); // from next-intl\r\n  const translator = new NextIntlTranslator(t, locale);\r\n  const translationManager = new TranslationManager(translator);\r\n\r\n  // Use in your application\r\n  const greeting = translationManager.t('common.greeting');\r\n  const welcome = translationManager.translateWithValues('common.welcome', {\r\n    name: 'John',\r\n  });\r\n\r\n  return <div>{greeting}</div>;\r\n}\r\n```\r\n\r\n## Integration with Native Intl API\r\n\r\n```typescript\r\nimport { IntlApiTranslator, TranslationsMap } from '@c-a-f/i18n/intl-api';\r\nimport { TranslationManager } from '@c-a-f/i18n';\r\n\r\n// Define translations map\r\nconst translations: TranslationsMap = {\r\n  en: {\r\n    'common.greeting': 'Hello',\r\n    'common.welcome': 'Welcome {{name}}',\r\n    'cart.items': '{{count}} items',\r\n  },\r\n  fa: {\r\n    'common.greeting': 'سلام',\r\n    'common.welcome': 'خوش آمدید {{name}}',\r\n    'cart.items': '{{count}} مورد',\r\n  },\r\n};\r\n\r\n// Create translator\r\nconst translator = new IntlApiTranslator('en', translations);\r\nconst translationManager = new TranslationManager(translator);\r\n\r\n// Use in your application\r\nconst greeting = translationManager.t('common.greeting');\r\nconst welcome = translationManager.translateWithValues('common.welcome', {\r\n  name: 'John',\r\n});\r\n\r\n// Change language\r\nawait translationManager.changeLanguage('fa');\r\n\r\n// Add translations dynamically\r\ntranslator.addTranslations('fr', {\r\n  'common.greeting': 'Bonjour',\r\n});\r\n\r\n// Get available languages\r\nconst languages = translator.getAvailableLanguages(); // ['en', 'fa', 'fr']\r\n```\r\n\r\n## Custom Translator Implementation\r\n\r\nYou can implement `ITranslator` for any i18n library:\r\n\r\n```typescript\r\nimport { ITranslator, TranslationOptions, TranslationManager } from '@c-a-f/i18n';\r\n\r\nclass CustomTranslator implements ITranslator {\r\n  private currentLanguage = 'en';\r\n  private translations: Record<string, Record<string, string>> = {\r\n    en: { greeting: 'Hello', welcome: 'Welcome {{name}}' },\r\n    fa: { greeting: 'سلام', welcome: 'خوش آمدید {{name}}' },\r\n  };\r\n\r\n  translate(key: string, options?: TranslationOptions): string {\r\n    let text = this.translations[this.currentLanguage]?.[key] || key;\r\n    \r\n    // Simple interpolation\r\n    if (options) {\r\n      Object.keys(options).forEach((k) => {\r\n        if (k !== 'ns' && k !== 'defaultValue' && k !== 'count' && k !== 'returnObjects') {\r\n          text = text.replace(`{{${k}}}`, String(options[k]));\r\n        }\r\n      });\r\n    }\r\n    \r\n    return text;\r\n  }\r\n\r\n  getCurrentLanguage(): string {\r\n    return this.currentLanguage;\r\n  }\r\n\r\n  async changeLanguage(language: string): Promise<void> {\r\n    this.currentLanguage = language;\r\n  }\r\n\r\n  exists(key: string): boolean {\r\n    return !!this.translations[this.currentLanguage]?.[key];\r\n  }\r\n}\r\n\r\n// Use with TranslationManager\r\nconst translator = new CustomTranslator();\r\nconst translationManager = new TranslationManager(translator);\r\nconst greeting = translationManager.t('greeting');\r\n```\r\n\r\n## Usage in Use Cases and Plocs\r\n\r\n```typescript\r\nimport { UseCase, RequestResult, pulse } from '@c-a-f/core';\r\nimport { TranslationManager, ITranslator } from '@c-a-f/i18n';\r\n\r\nclass LoginUser implements UseCase<[{ username: string; password: string }], { token: string }> {\r\n  constructor(\r\n    private loginService: LoginService,\r\n    private translationManager: TranslationManager\r\n  ) {}\r\n\r\n  async execute(args: { username: string; password: string }): Promise<RequestResult<{ token: string }>> {\r\n    try {\r\n      const result = await this.loginService.login(args);\r\n      \r\n      // Use translation in use case\r\n      const successMessage = this.translationManager.t('login.success');\r\n      console.log(successMessage);\r\n      \r\n      return {\r\n        loading: pulse(false),\r\n        data: pulse(result),\r\n        error: pulse(null! as Error),\r\n      };\r\n    } catch (error) {\r\n      const errorMessage = this.translationManager.t('login.error');\r\n      return {\r\n        loading: pulse(false),\r\n        data: pulse(null! as { token: string }),\r\n        error: pulse(new Error(errorMessage)),\r\n      };\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n## Exports\r\n\r\n- `ITranslator` — Interface for translation implementations\r\n- `TranslationOptions` — Interface for translation options (interpolation, pluralization, etc.)\r\n- `TranslationManager` — Utility class for translation\r\n- `I18nextTranslator` — Adapter for i18next (from `@c-a-f/i18n/i18next`)\r\n- `VueI18nTranslator` — Adapter for vue-i18n (from `@c-a-f/i18n/vue-i18n`)\r\n- `NgxTranslateTranslator` — Adapter for ngx-translate (from `@c-a-f/i18n/ngx-translate`)\r\n- `ReactIntlTranslator` — Adapter for react-intl (from `@c-a-f/i18n/react-intl`)\r\n- `NextIntlTranslator` — Adapter for next-intl (from `@c-a-f/i18n/next-intl`)\r\n- `IntlApiTranslator` — Adapter for native Intl API (from `@c-a-f/i18n/intl-api`)\r\n- `TranslationsMap` — Type for translations map structure\r\n\r\n## Dependencies\r\n\r\n- `@c-a-f/core` — Core primitives\r\n\r\n## Peer Dependencies (Optional)\r\n\r\n- `i18next` — For i18next integration\r\n- `vue-i18n` — For vue-i18n integration\r\n- `@ngx-translate/core` — For ngx-translate integration\r\n- `react-intl` — For react-intl integration\r\n- `next-intl` — For next-intl integration\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}