@geenius/i18n 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/README.md +134 -1
  2. package/package.json +16 -3
  3. package/packages/convex/dist/index.d.ts +62 -0
  4. package/packages/convex/dist/index.js +157 -0
  5. package/packages/convex/dist/index.js.map +1 -0
  6. package/packages/react/README.md +1 -1
  7. package/packages/react/dist/index.d.ts +100 -0
  8. package/packages/react/dist/index.js +284 -0
  9. package/packages/react/dist/index.js.map +1 -0
  10. package/packages/react-css/README.md +1 -1
  11. package/packages/react-css/dist/index.d.ts +34 -0
  12. package/packages/react-css/dist/index.js +134 -0
  13. package/packages/react-css/dist/index.js.map +1 -0
  14. package/packages/shared/README.md +1 -1
  15. package/packages/shared/dist/index.d.ts +77 -0
  16. package/packages/shared/dist/index.js +158 -0
  17. package/packages/shared/dist/index.js.map +1 -0
  18. package/packages/solidjs/README.md +1 -1
  19. package/packages/solidjs/dist/index.d.ts +105 -0
  20. package/packages/solidjs/dist/index.js +328 -0
  21. package/packages/solidjs/dist/index.js.map +1 -0
  22. package/packages/solidjs-css/README.md +1 -1
  23. package/packages/solidjs-css/dist/index.d.ts +59 -0
  24. package/packages/solidjs-css/dist/index.js +244 -0
  25. package/packages/solidjs-css/dist/index.js.map +1 -0
  26. package/.changeset/config.json +0 -11
  27. package/.github/CODEOWNERS +0 -1
  28. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
  29. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
  30. package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
  31. package/.github/dependabot.yml +0 -11
  32. package/.github/workflows/ci.yml +0 -23
  33. package/.github/workflows/release.yml +0 -29
  34. package/.nvmrc +0 -1
  35. package/.project/ACCOUNT.yaml +0 -4
  36. package/.project/IDEAS.yaml +0 -7
  37. package/.project/PROJECT.yaml +0 -11
  38. package/.project/ROADMAP.yaml +0 -15
  39. package/CODE_OF_CONDUCT.md +0 -16
  40. package/CONTRIBUTING.md +0 -26
  41. package/SECURITY.md +0 -15
  42. package/SUPPORT.md +0 -8
  43. package/packages/convex/package.json +0 -42
  44. package/packages/convex/src/index.ts +0 -3
  45. package/packages/convex/src/mutations.ts +0 -65
  46. package/packages/convex/src/queries.ts +0 -54
  47. package/packages/convex/src/schema.ts +0 -26
  48. package/packages/convex/tsconfig.json +0 -18
  49. package/packages/convex/tsup.config.ts +0 -17
  50. package/packages/react/package.json +0 -51
  51. package/packages/react/src/components/index.tsx +0 -87
  52. package/packages/react/src/hooks/index.ts +0 -4
  53. package/packages/react/src/hooks/useI18n.tsx +0 -50
  54. package/packages/react/src/hooks/useI18nAdmin.ts +0 -12
  55. package/packages/react/src/hooks/useLocaleDetect.ts +0 -10
  56. package/packages/react/src/hooks/useTranslations.ts +0 -11
  57. package/packages/react/src/index.tsx +0 -8
  58. package/packages/react/src/pages/I18nAdminPage.tsx +0 -42
  59. package/packages/react/src/pages/LocalePreviewPage.tsx +0 -54
  60. package/packages/react/src/pages/index.ts +0 -2
  61. package/packages/react/tsconfig.json +0 -19
  62. package/packages/react/tsup.config.ts +0 -12
  63. package/packages/react-css/package.json +0 -36
  64. package/packages/react-css/src/components/index.tsx +0 -66
  65. package/packages/react-css/src/hooks/index.ts +0 -4
  66. package/packages/react-css/src/index.tsx +0 -4
  67. package/packages/react-css/src/pages/LocaleSettingsPage.tsx +0 -74
  68. package/packages/react-css/src/pages/TranslationsPage.tsx +0 -98
  69. package/packages/react-css/src/styles.css +0 -210
  70. package/packages/react-css/tsconfig.json +0 -19
  71. package/packages/react-css/tsup.config.ts +0 -10
  72. package/packages/shared/package.json +0 -44
  73. package/packages/shared/src/__tests__/i18n.test.ts +0 -78
  74. package/packages/shared/src/config.ts +0 -344
  75. package/packages/shared/src/index.ts +0 -106
  76. package/packages/shared/src/types.ts +0 -51
  77. package/packages/shared/tsconfig.json +0 -18
  78. package/packages/shared/tsup.config.ts +0 -11
  79. package/packages/shared/vitest.config.ts +0 -4
  80. package/packages/solidjs/package.json +0 -47
  81. package/packages/solidjs/src/components/LocaleCard.tsx +0 -44
  82. package/packages/solidjs/src/components/LocaleStatsCard.tsx +0 -35
  83. package/packages/solidjs/src/components/LocaleSwitcher.tsx +0 -65
  84. package/packages/solidjs/src/components/MissingKeyAlert.tsx +0 -21
  85. package/packages/solidjs/src/components/RTLWrapper.tsx +0 -13
  86. package/packages/solidjs/src/components/TranslationKeyRow.tsx +0 -41
  87. package/packages/solidjs/src/components/index.ts +0 -6
  88. package/packages/solidjs/src/index.tsx +0 -8
  89. package/packages/solidjs/src/pages/I18nAdminPage.tsx +0 -188
  90. package/packages/solidjs/src/pages/LocalePreviewPage.tsx +0 -99
  91. package/packages/solidjs/src/pages/index.ts +0 -2
  92. package/packages/solidjs/src/primitives/I18nProvider.tsx +0 -56
  93. package/packages/solidjs/src/primitives/createI18nAdmin.ts +0 -7
  94. package/packages/solidjs/src/primitives/createLocaleDetect.ts +0 -8
  95. package/packages/solidjs/src/primitives/createTranslations.ts +0 -22
  96. package/packages/solidjs/src/primitives/index.ts +0 -4
  97. package/packages/solidjs/tsconfig.json +0 -20
  98. package/packages/solidjs/tsup.config.ts +0 -12
  99. package/packages/solidjs-css/package.json +0 -33
  100. package/packages/solidjs-css/src/components/LocaleCard.tsx +0 -45
  101. package/packages/solidjs-css/src/components/LocaleStatsCard.tsx +0 -43
  102. package/packages/solidjs-css/src/components/LocaleSwitcher.tsx +0 -51
  103. package/packages/solidjs-css/src/components/MissingKeyAlert.tsx +0 -24
  104. package/packages/solidjs-css/src/components/RTLWrapper.tsx +0 -16
  105. package/packages/solidjs-css/src/components/TranslationKeyRow.tsx +0 -47
  106. package/packages/solidjs-css/src/components/index.ts +0 -6
  107. package/packages/solidjs-css/src/i18n.css +0 -1322
  108. package/packages/solidjs-css/src/index.tsx +0 -3
  109. package/packages/solidjs-css/src/pages/I18nAdminPage.tsx +0 -134
  110. package/packages/solidjs-css/src/pages/LocalePreviewPage.tsx +0 -116
  111. package/packages/solidjs-css/src/pages/index.ts +0 -2
  112. package/packages/solidjs-css/src/primitives/index.ts +0 -1
  113. package/packages/solidjs-css/tsconfig.json +0 -20
  114. package/packages/solidjs-css/tsup.config.bundled_dcjc4sct21j.mjs +0 -18
  115. package/packages/solidjs-css/tsup.config.ts +0 -14
  116. package/pnpm-workspace.yaml +0 -2
  117. package/tsconfig.json +0 -23
package/README.md CHANGED
@@ -1 +1,134 @@
1
- # geenius-i18n\n\n> Geenius I18n — Internationalization for Convex apps (React + SolidJS)\n\n---\n\n## Overview\nBuilt with Steve Jobs-level minimalism and Jony Ive-level craftsmanship, this package is designed to deliver unparalleled developer experience (DX) and rock-solid performance.\n\n## Installation\n\n```bash\npnpm add geenius-i18n\n```\n\n## Usage\n\n```typescript\nimport { init } from 'geenius-i18n';\n\n// Initialize the module with absolute precision\ninit({\n mode: 'premium',\n});\n```\n\n## Architecture\n- **Zero-config**: It just works.\n- **Strictly Typed**: Fully written in TypeScript for flawless IntelliSense.\n- **Framework Agnostic**: seamlessly integrates into the Geenius ecosystem.\n\n---\n\n*Designed by Antigravity HQ*\n
1
+ # @geenius/i18n
2
+
3
+ Internationalization for Convex apps with React and SolidJS support.
4
+
5
+ ## Features
6
+
7
+ - 14 built-in locales with metadata (name, native name, direction, flag)
8
+ - RTL detection for Arabic and Hebrew
9
+ - Pluralization with `_zero`, `_one`, `_other` suffixes
10
+ - `{{variable}}` interpolation
11
+ - Intl-based date, number, and currency formatting
12
+ - localStorage locale persistence and browser detection
13
+ - Convex backend schema for translation management
14
+ - Admin dashboard components (Tailwind and vanilla CSS variants)
15
+
16
+ ## Packages
17
+
18
+ | Package | Description |
19
+ |---------|-------------|
20
+ | `@geenius/i18n-shared` | Core types, utilities, locale data |
21
+ | `@geenius/i18n-convex` | Convex schema and query/mutation factories |
22
+ | `@geenius/i18n-react` | React hooks, components, admin pages (Tailwind) |
23
+ | `@geenius/i18n-solidjs` | SolidJS primitives, components, admin pages |
24
+ | `@geenius/i18n-react-css` | React components (vanilla CSS) |
25
+ | `@geenius/i18n-solidjs-css` | SolidJS components (vanilla CSS) |
26
+
27
+ ## Quick Start
28
+
29
+ ### React
30
+
31
+ ```tsx
32
+ import { I18nProvider, useI18n } from '@geenius/i18n/react'
33
+
34
+ const translations = {
35
+ greeting: 'Hello {{name}}!',
36
+ items_zero: 'No items',
37
+ items_one: '1 item',
38
+ items_other: '{{count}} items',
39
+ }
40
+
41
+ function App() {
42
+ return (
43
+ <I18nProvider
44
+ config={{ defaultLocale: 'en', supportedLocales: ['en', 'es', 'fr'], persistLocale: true, detectBrowser: true }}
45
+ translations={translations}
46
+ >
47
+ <Dashboard />
48
+ </I18nProvider>
49
+ )
50
+ }
51
+
52
+ function Dashboard() {
53
+ const { t, locale, setLocale, formatDate, formatCurrency, isRTL } = useI18n()
54
+
55
+ return (
56
+ <div dir={isRTL ? 'rtl' : 'ltr'}>
57
+ <h1>{t('greeting', { name: 'Mehdi' })}</h1>
58
+ <p>{formatDate(new Date())}</p>
59
+ <p>{formatCurrency(49.99, 'USD')}</p>
60
+ <button onClick={() => setLocale('es')}>Switch to Spanish</button>
61
+ </div>
62
+ )
63
+ }
64
+ ```
65
+
66
+ ### SolidJS
67
+
68
+ ```tsx
69
+ import { I18nProvider, createI18n } from '@geenius/i18n/solidjs'
70
+
71
+ function Dashboard() {
72
+ const { t, locale, setLocale } = createI18n()
73
+ return <h1>{t('greeting', { name: 'Mehdi' })}</h1>
74
+ }
75
+ ```
76
+
77
+ ### Core Utilities
78
+
79
+ ```ts
80
+ import { interpolate, t, plural, isRTL, formatDate, formatNumber, formatCurrency, detectLocale } from '@geenius/i18n/shared'
81
+
82
+ interpolate('Hello {{name}}!', { name: 'Alice' }) // "Hello Alice!"
83
+ isRTL('ar') // true
84
+ formatCurrency(42.99, 'EUR', 'de') // "42,99 €"
85
+ ```
86
+
87
+ ### Convex Backend
88
+
89
+ ```ts
90
+ import { schema, createI18nQueries, createI18nMutations } from '@geenius/i18n/convex'
91
+ import { query, mutation } from './_generated/server'
92
+
93
+ // Wire into your Convex project
94
+ const { listTranslations, searchTranslations } = createI18nQueries(query)
95
+ const { upsertTranslation, importTranslations } = createI18nMutations(mutation)
96
+
97
+ export { listTranslations, searchTranslations, upsertTranslation, importTranslations }
98
+ ```
99
+
100
+ ### Config Builder
101
+
102
+ ```ts
103
+ import { createI18nConfig, i18nPresets } from '@geenius/i18n/shared'
104
+
105
+ // Builder pattern
106
+ const config = createI18nConfig()
107
+ .withDefaultLocale('en')
108
+ .withSupportedLocales(['en', 'fr', 'de', 'es'])
109
+ .withFallbackLocale('en')
110
+ .withDebug(true)
111
+ .build()
112
+
113
+ // Or use presets
114
+ const simple = i18nPresets.simple('en')
115
+ const multi = i18nPresets.multi()
116
+ const global = i18nPresets.global()
117
+ const dev = i18nPresets.development()
118
+ ```
119
+
120
+ ## Supported Locales
121
+
122
+ English, French, German, Spanish, Portuguese, Italian, Dutch, Russian, Chinese, Japanese, Korean, Arabic (RTL), Hebrew (RTL), Turkish
123
+
124
+ ## Development
125
+
126
+ ```bash
127
+ pnpm install
128
+ pnpm build # Build all packages
129
+ pnpm test # Run tests
130
+ ```
131
+
132
+ ## License
133
+
134
+ MIT
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@geenius/i18n",
3
3
  "type": "module",
4
- "version": "0.1.0",
4
+ "version": "0.3.0",
5
5
  "description": "Geenius I18n — Internationalization for Convex apps (React + SolidJS)",
6
6
  "author": "Antigravity HQ",
7
7
  "license": "MIT",
@@ -19,19 +19,32 @@
19
19
  "solidjs",
20
20
  "geenius"
21
21
  ],
22
+ "files": [
23
+ "packages/shared/dist",
24
+ "packages/react/dist",
25
+ "packages/solidjs/dist",
26
+ "packages/convex/dist",
27
+ "packages/react-css/dist",
28
+ "packages/solidjs-css/dist",
29
+ "README.md",
30
+ "LICENSE",
31
+ "CHANGELOG.md"
32
+ ],
22
33
  "scripts": {
23
34
  "dev": "pnpm -r --parallel type-check",
24
35
  "build": "pnpm -r build",
25
36
  "clean": "pnpm -r clean",
26
37
  "lint": "pnpm -r --parallel type-check",
27
- "test": "echo \"No tests configured yet\" && exit 0",
38
+ "test": "pnpm -r test",
28
39
  "type-check": "pnpm -r type-check",
29
40
  "format": "prettier --write \"packages/*/src/**/*.{ts,tsx}\"",
30
41
  "version:patch": "pnpm -r exec -- npm version patch --no-git-tag-version && npm version patch -m 'v%s'",
31
42
  "version:minor": "pnpm -r exec -- npm version minor --no-git-tag-version && npm version minor -m 'v%s'",
32
43
  "version:major": "pnpm -r exec -- npm version major --no-git-tag-version && npm version major -m 'v%s'",
33
44
  "release": "git push && git push --tags",
34
- "publish:all": "pnpm -r publish --access public"
45
+ "publish:all": "pnpm -r publish --access public",
46
+ "publish:root": "npm publish --access public",
47
+ "prepublishOnly": "pnpm build"
35
48
  },
36
49
  "devDependencies": {
37
50
  "prettier": "^3.8.1",
@@ -0,0 +1,62 @@
1
+ import * as convex_server from 'convex/server';
2
+ import * as convex_values from 'convex/values';
3
+
4
+ declare const _default: convex_server.SchemaDefinition<{
5
+ i18n_translations: convex_server.TableDefinition<convex_values.VObject<{
6
+ lastEditedBy?: string | undefined;
7
+ locale: string;
8
+ namespace: string;
9
+ key: string;
10
+ value: string;
11
+ updatedAt: string;
12
+ createdAt: string;
13
+ }, {
14
+ locale: convex_values.VString<string, "required">;
15
+ namespace: convex_values.VString<string, "required">;
16
+ key: convex_values.VString<string, "required">;
17
+ value: convex_values.VString<string, "required">;
18
+ lastEditedBy: convex_values.VString<string | undefined, "optional">;
19
+ updatedAt: convex_values.VString<string, "required">;
20
+ createdAt: convex_values.VString<string, "required">;
21
+ }, "required", "locale" | "namespace" | "key" | "value" | "lastEditedBy" | "updatedAt" | "createdAt">, {
22
+ by_locale_ns: ["locale", "namespace", "_creationTime"];
23
+ by_key: ["key", "_creationTime"];
24
+ }, {}, {}>;
25
+ i18n_missing_keys: convex_server.TableDefinition<convex_values.VObject<{
26
+ locale: string;
27
+ namespace: string;
28
+ key: string;
29
+ detectedAt: string;
30
+ count: number;
31
+ }, {
32
+ locale: convex_values.VString<string, "required">;
33
+ namespace: convex_values.VString<string, "required">;
34
+ key: convex_values.VString<string, "required">;
35
+ detectedAt: convex_values.VString<string, "required">;
36
+ count: convex_values.VFloat64<number, "required">;
37
+ }, "required", "locale" | "namespace" | "key" | "detectedAt" | "count">, {
38
+ by_locale: ["locale", "_creationTime"];
39
+ by_key: ["key", "_creationTime"];
40
+ }, {}, {}>;
41
+ }, true>;
42
+
43
+ type QueryFn = (...args: any[]) => any;
44
+ declare function createI18nQueries(query: QueryFn): {
45
+ listTranslations: any;
46
+ getTranslation: any;
47
+ listLocaleStats: any;
48
+ listMissingKeys: any;
49
+ searchTranslations: any;
50
+ };
51
+
52
+ type MutationFn = (...args: any[]) => any;
53
+ declare function createI18nMutations(mutation: MutationFn): {
54
+ upsertTranslation: any;
55
+ deleteTranslation: any;
56
+ importTranslations: any;
57
+ reportMissingKey: any;
58
+ clearMissingKey: any;
59
+ bulkUpsert: any;
60
+ };
61
+
62
+ export { createI18nMutations, createI18nQueries, _default as schema };
@@ -0,0 +1,157 @@
1
+ // src/schema.ts
2
+ import { defineSchema, defineTable } from "convex/server";
3
+ import { v } from "convex/values";
4
+ var schema_default = defineSchema({
5
+ i18n_translations: defineTable({
6
+ locale: v.string(),
7
+ namespace: v.string(),
8
+ key: v.string(),
9
+ value: v.string(),
10
+ lastEditedBy: v.optional(v.string()),
11
+ updatedAt: v.string(),
12
+ createdAt: v.string()
13
+ }).index("by_locale_ns", ["locale", "namespace"]).index("by_key", ["key"]),
14
+ i18n_missing_keys: defineTable({
15
+ locale: v.string(),
16
+ namespace: v.string(),
17
+ key: v.string(),
18
+ detectedAt: v.string(),
19
+ count: v.number()
20
+ }).index("by_locale", ["locale"]).index("by_key", ["key"])
21
+ });
22
+
23
+ // src/queries.ts
24
+ import { v as v2 } from "convex/values";
25
+ function createI18nQueries(query) {
26
+ const listTranslations = query({
27
+ args: { locale: v2.string(), namespace: v2.optional(v2.string()) },
28
+ handler: async (ctx, args) => {
29
+ if (args.namespace) return ctx.db.query("i18n_translations").withIndex("by_locale_ns", (q) => q.eq("locale", args.locale).eq("namespace", args.namespace)).collect();
30
+ return ctx.db.query("i18n_translations").withIndex("by_locale_ns", (q) => q.eq("locale", args.locale)).collect();
31
+ }
32
+ });
33
+ const getTranslation = query({
34
+ args: { locale: v2.string(), key: v2.string(), namespace: v2.optional(v2.string()) },
35
+ handler: async (ctx, args) => {
36
+ const results = await ctx.db.query("i18n_translations").withIndex("by_key", (q) => q.eq("key", args.key)).collect();
37
+ return results.find((r) => r.locale === args.locale && (!args.namespace || r.namespace === args.namespace)) ?? null;
38
+ }
39
+ });
40
+ const listLocaleStats = query({
41
+ args: {},
42
+ handler: async (ctx) => {
43
+ const all = await ctx.db.query("i18n_translations").collect();
44
+ const missing = await ctx.db.query("i18n_missing_keys").collect();
45
+ const localeMap = /* @__PURE__ */ new Map();
46
+ const missingMap = /* @__PURE__ */ new Map();
47
+ for (const t of all) localeMap.set(t.locale, (localeMap.get(t.locale) ?? 0) + 1);
48
+ for (const m of missing) missingMap.set(m.locale, (missingMap.get(m.locale) ?? 0) + 1);
49
+ const stats = [];
50
+ for (const [locale, total] of localeMap) {
51
+ const miss = missingMap.get(locale) ?? 0;
52
+ stats.push({ locale, totalKeys: total, missingKeys: miss, coverage: total > 0 ? Math.round((total - miss) / total * 100) : 0 });
53
+ }
54
+ return stats;
55
+ }
56
+ });
57
+ const listMissingKeys = query({
58
+ args: { locale: v2.optional(v2.string()), limit: v2.optional(v2.number()) },
59
+ handler: async (ctx, args) => {
60
+ if (args.locale) return ctx.db.query("i18n_missing_keys").withIndex("by_locale", (q) => q.eq("locale", args.locale)).take(args.limit ?? 100);
61
+ return ctx.db.query("i18n_missing_keys").order("desc").take(args.limit ?? 100);
62
+ }
63
+ });
64
+ const searchTranslations = query({
65
+ args: { query: v2.string(), locale: v2.optional(v2.string()) },
66
+ handler: async (ctx, args) => {
67
+ let items = await ctx.db.query("i18n_translations").collect();
68
+ if (args.locale) items = items.filter((i) => i.locale === args.locale);
69
+ const q = args.query.toLowerCase();
70
+ return items.filter((i) => i.key.toLowerCase().includes(q) || i.value.toLowerCase().includes(q)).slice(0, 50);
71
+ }
72
+ });
73
+ return { listTranslations, getTranslation, listLocaleStats, listMissingKeys, searchTranslations };
74
+ }
75
+
76
+ // src/mutations.ts
77
+ import { v as v3 } from "convex/values";
78
+ function createI18nMutations(mutation) {
79
+ const upsertTranslation = mutation({
80
+ args: { locale: v3.string(), namespace: v3.string(), key: v3.string(), value: v3.string(), editedBy: v3.optional(v3.string()) },
81
+ handler: async (ctx, args) => {
82
+ const existing = await ctx.db.query("i18n_translations").withIndex("by_key", (q) => q.eq("key", args.key)).collect();
83
+ const match = existing.find((e) => e.locale === args.locale && e.namespace === args.namespace);
84
+ const now = (/* @__PURE__ */ new Date()).toISOString();
85
+ if (match) {
86
+ await ctx.db.patch(match._id, { value: args.value, lastEditedBy: args.editedBy, updatedAt: now });
87
+ } else {
88
+ await ctx.db.insert("i18n_translations", { locale: args.locale, namespace: args.namespace, key: args.key, value: args.value, lastEditedBy: args.editedBy, updatedAt: now, createdAt: now });
89
+ }
90
+ }
91
+ });
92
+ const deleteTranslation = mutation({
93
+ args: { locale: v3.string(), key: v3.string(), namespace: v3.optional(v3.string()) },
94
+ handler: async (ctx, args) => {
95
+ const items = await ctx.db.query("i18n_translations").withIndex("by_key", (q) => q.eq("key", args.key)).collect();
96
+ for (const item of items) {
97
+ if (item.locale === args.locale && (!args.namespace || item.namespace === args.namespace)) await ctx.db.delete(item._id);
98
+ }
99
+ }
100
+ });
101
+ const importTranslations = mutation({
102
+ args: { locale: v3.string(), namespace: v3.string(), dict: v3.any() },
103
+ handler: async (ctx, args) => {
104
+ const now = (/* @__PURE__ */ new Date()).toISOString();
105
+ const entries = args.dict;
106
+ for (const [key, value] of Object.entries(entries)) {
107
+ const existing = await ctx.db.query("i18n_translations").withIndex("by_key", (q) => q.eq("key", key)).collect();
108
+ const match = existing.find((e) => e.locale === args.locale && e.namespace === args.namespace);
109
+ if (match) {
110
+ await ctx.db.patch(match._id, { value, updatedAt: now });
111
+ } else {
112
+ await ctx.db.insert("i18n_translations", { locale: args.locale, namespace: args.namespace, key, value, updatedAt: now, createdAt: now });
113
+ }
114
+ }
115
+ }
116
+ });
117
+ const reportMissingKey = mutation({
118
+ args: { locale: v3.string(), namespace: v3.string(), key: v3.string() },
119
+ handler: async (ctx, args) => {
120
+ const existing = await ctx.db.query("i18n_missing_keys").withIndex("by_key", (q) => q.eq("key", args.key)).collect();
121
+ const match = existing.find((e) => e.locale === args.locale && e.namespace === args.namespace);
122
+ if (match) {
123
+ await ctx.db.patch(match._id, { count: match.count + 1 });
124
+ } else {
125
+ await ctx.db.insert("i18n_missing_keys", { ...args, detectedAt: (/* @__PURE__ */ new Date()).toISOString(), count: 1 });
126
+ }
127
+ }
128
+ });
129
+ const clearMissingKey = mutation({
130
+ args: { id: v3.id("i18n_missing_keys") },
131
+ handler: async (ctx, args) => {
132
+ await ctx.db.delete(args.id);
133
+ }
134
+ });
135
+ const bulkUpsert = mutation({
136
+ args: { items: v3.array(v3.object({ locale: v3.string(), namespace: v3.string(), key: v3.string(), value: v3.string() })) },
137
+ handler: async (ctx, args) => {
138
+ const now = (/* @__PURE__ */ new Date()).toISOString();
139
+ for (const item of args.items) {
140
+ const existing = await ctx.db.query("i18n_translations").withIndex("by_key", (q) => q.eq("key", item.key)).collect();
141
+ const match = existing.find((e) => e.locale === item.locale && e.namespace === item.namespace);
142
+ if (match) {
143
+ await ctx.db.patch(match._id, { value: item.value, updatedAt: now });
144
+ } else {
145
+ await ctx.db.insert("i18n_translations", { ...item, updatedAt: now, createdAt: now });
146
+ }
147
+ }
148
+ }
149
+ });
150
+ return { upsertTranslation, deleteTranslation, importTranslations, reportMissingKey, clearMissingKey, bulkUpsert };
151
+ }
152
+ export {
153
+ createI18nMutations,
154
+ createI18nQueries,
155
+ schema_default as schema
156
+ };
157
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema.ts","../src/queries.ts","../src/mutations.ts"],"sourcesContent":["import { defineSchema, defineTable } from 'convex/server'\nimport { v } from 'convex/values'\n\nexport default defineSchema({\n i18n_translations: defineTable({\n locale: v.string(),\n namespace: v.string(),\n key: v.string(),\n value: v.string(),\n lastEditedBy: v.optional(v.string()),\n updatedAt: v.string(),\n createdAt: v.string(),\n })\n .index('by_locale_ns', ['locale', 'namespace'])\n .index('by_key', ['key']),\n\n i18n_missing_keys: defineTable({\n locale: v.string(),\n namespace: v.string(),\n key: v.string(),\n detectedAt: v.string(),\n count: v.number(),\n })\n .index('by_locale', ['locale'])\n .index('by_key', ['key']),\n})\n","import { v } from 'convex/values'\n\ntype QueryFn = (...args: any[]) => any\n\nexport function createI18nQueries(query: QueryFn) {\n const listTranslations = query({\n args: { locale: v.string(), namespace: v.optional(v.string()) },\n handler: async (ctx: any, args: { locale: string; namespace?: string }) => {\n if (args.namespace) return ctx.db.query('i18n_translations').withIndex('by_locale_ns', (q: any) => q.eq('locale', args.locale).eq('namespace', args.namespace!)).collect()\n return ctx.db.query('i18n_translations').withIndex('by_locale_ns', (q: any) => q.eq('locale', args.locale)).collect()\n },\n })\n\n const getTranslation = query({\n args: { locale: v.string(), key: v.string(), namespace: v.optional(v.string()) },\n handler: async (ctx: any, args: { locale: string; key: string; namespace?: string }) => {\n const results = await ctx.db.query('i18n_translations').withIndex('by_key', (q: any) => q.eq('key', args.key)).collect()\n return results.find((r: any) => r.locale === args.locale && (!args.namespace || r.namespace === args.namespace)) ?? null\n },\n })\n\n const listLocaleStats = query({\n args: {},\n handler: async (ctx: any) => {\n const all = await ctx.db.query('i18n_translations').collect()\n const missing = await ctx.db.query('i18n_missing_keys').collect()\n const localeMap = new Map<string, number>()\n const missingMap = new Map<string, number>()\n for (const t of all) localeMap.set(t.locale, (localeMap.get(t.locale) ?? 0) + 1)\n for (const m of missing) missingMap.set(m.locale, (missingMap.get(m.locale) ?? 0) + 1)\n const stats: { locale: string; totalKeys: number; missingKeys: number; coverage: number }[] = []\n for (const [locale, total] of localeMap) {\n const miss = missingMap.get(locale) ?? 0\n stats.push({ locale, totalKeys: total, missingKeys: miss, coverage: total > 0 ? Math.round(((total - miss) / total) * 100) : 0 })\n }\n return stats\n },\n })\n\n const listMissingKeys = query({\n args: { locale: v.optional(v.string()), limit: v.optional(v.number()) },\n handler: async (ctx: any, args: { locale?: string; limit?: number }) => {\n if (args.locale) return ctx.db.query('i18n_missing_keys').withIndex('by_locale', (q: any) => q.eq('locale', args.locale!)).take(args.limit ?? 100)\n return ctx.db.query('i18n_missing_keys').order('desc').take(args.limit ?? 100)\n },\n })\n\n const searchTranslations = query({\n args: { query: v.string(), locale: v.optional(v.string()) },\n handler: async (ctx: any, args: { query: string; locale?: string }) => {\n let items = await ctx.db.query('i18n_translations').collect()\n if (args.locale) items = items.filter((i: any) => i.locale === args.locale)\n const q = args.query.toLowerCase()\n return items.filter((i: any) => i.key.toLowerCase().includes(q) || i.value.toLowerCase().includes(q)).slice(0, 50)\n },\n })\n\n return { listTranslations, getTranslation, listLocaleStats, listMissingKeys, searchTranslations }\n}\n","import { v } from 'convex/values'\n\ntype MutationFn = (...args: any[]) => any\n\nexport function createI18nMutations(mutation: MutationFn) {\n const upsertTranslation = mutation({\n args: { locale: v.string(), namespace: v.string(), key: v.string(), value: v.string(), editedBy: v.optional(v.string()) },\n handler: async (ctx: any, args: { locale: string; namespace: string; key: string; value: string; editedBy?: string }) => {\n const existing = await ctx.db.query('i18n_translations').withIndex('by_key', (q: any) => q.eq('key', args.key)).collect()\n const match = existing.find((e: any) => e.locale === args.locale && e.namespace === args.namespace)\n const now = new Date().toISOString()\n if (match) { await ctx.db.patch(match._id, { value: args.value, lastEditedBy: args.editedBy, updatedAt: now }) }\n else { await ctx.db.insert('i18n_translations', { locale: args.locale, namespace: args.namespace, key: args.key, value: args.value, lastEditedBy: args.editedBy, updatedAt: now, createdAt: now }) }\n },\n })\n\n const deleteTranslation = mutation({\n args: { locale: v.string(), key: v.string(), namespace: v.optional(v.string()) },\n handler: async (ctx: any, args: { locale: string; key: string; namespace?: string }) => {\n const items = await ctx.db.query('i18n_translations').withIndex('by_key', (q: any) => q.eq('key', args.key)).collect()\n for (const item of items) {\n if (item.locale === args.locale && (!args.namespace || item.namespace === args.namespace)) await ctx.db.delete(item._id)\n }\n },\n })\n\n const importTranslations = mutation({\n args: { locale: v.string(), namespace: v.string(), dict: v.any() },\n handler: async (ctx: any, args: { locale: string; namespace: string; dict: any }) => {\n const now = new Date().toISOString()\n const entries = args.dict as Record<string, string>\n for (const [key, value] of Object.entries(entries)) {\n const existing = await ctx.db.query('i18n_translations').withIndex('by_key', (q: any) => q.eq('key', key)).collect()\n const match = existing.find((e: any) => e.locale === args.locale && e.namespace === args.namespace)\n if (match) { await ctx.db.patch(match._id, { value, updatedAt: now }) }\n else { await ctx.db.insert('i18n_translations', { locale: args.locale, namespace: args.namespace, key, value, updatedAt: now, createdAt: now }) }\n }\n },\n })\n\n const reportMissingKey = mutation({\n args: { locale: v.string(), namespace: v.string(), key: v.string() },\n handler: async (ctx: any, args: { locale: string; namespace: string; key: string }) => {\n const existing = await ctx.db.query('i18n_missing_keys').withIndex('by_key', (q: any) => q.eq('key', args.key)).collect()\n const match = existing.find((e: any) => e.locale === args.locale && e.namespace === args.namespace)\n if (match) { await ctx.db.patch(match._id, { count: match.count + 1 }) }\n else { await ctx.db.insert('i18n_missing_keys', { ...args, detectedAt: new Date().toISOString(), count: 1 }) }\n },\n })\n\n const clearMissingKey = mutation({\n args: { id: v.id('i18n_missing_keys') },\n handler: async (ctx: any, args: { id: any }) => { await ctx.db.delete(args.id) },\n })\n\n const bulkUpsert = mutation({\n args: { items: v.array(v.object({ locale: v.string(), namespace: v.string(), key: v.string(), value: v.string() })) },\n handler: async (ctx: any, args: { items: Array<{ locale: string; namespace: string; key: string; value: string }> }) => {\n const now = new Date().toISOString()\n for (const item of args.items) {\n const existing = await ctx.db.query('i18n_translations').withIndex('by_key', (q: any) => q.eq('key', item.key)).collect()\n const match = existing.find((e: any) => e.locale === item.locale && e.namespace === item.namespace)\n if (match) { await ctx.db.patch(match._id, { value: item.value, updatedAt: now }) }\n else { await ctx.db.insert('i18n_translations', { ...item, updatedAt: now, createdAt: now }) }\n }\n },\n })\n\n return { upsertTranslation, deleteTranslation, importTranslations, reportMissingKey, clearMissingKey, bulkUpsert }\n}\n"],"mappings":"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","names":["v","v"]}
@@ -1 +1 @@
1
- # ✦ @geenius-i18n/react\n\n> Geenius I18n — React components & hooks\n\n---\n\n## Overview\nBuilt with Steve Jobs-level minimalism and Jony Ive-level craftsmanship, this package is designed to deliver unparalleled developer experience (DX) and rock-solid performance.\n\n## Installation\n\n```bash\npnpm add @geenius-i18n/react\n```\n\n## Usage\n\n```typescript\nimport { init } from '@geenius-i18n/react';\n\n// Initialize the module with absolute precision\ninit({\n mode: 'premium',\n});\n```\n\n## Architecture\n- **Zero-config**: It just works.\n- **Strictly Typed**: Fully written in TypeScript for flawless IntelliSense.\n- **Framework Agnostic**: seamlessly integrates into the Geenius ecosystem.\n\n---\n\n*Designed by Antigravity HQ*\n
1
+ # ✦ @geenius/i18n-react\n\n> Geenius I18n — React components & hooks\n\n---\n\n## Overview\nBuilt with Steve Jobs-level minimalism and Jony Ive-level craftsmanship, this package is designed to deliver unparalleled developer experience (DX) and rock-solid performance.\n\n## Installation\n\n```bash\npnpm add @geenius/i18n-react\n```\n\n## Usage\n\n```typescript\nimport { init } from '@geenius/i18n-react';\n\n// Initialize the module with absolute precision\ninit({\n mode: 'premium',\n});\n```\n\n## Architecture\n- **Zero-config**: It just works.\n- **Strictly Typed**: Fully written in TypeScript for flawless IntelliSense.\n- **Framework Agnostic**: seamlessly integrates into the Geenius ecosystem.\n\n---\n\n*Designed by Antigravity HQ*\n
@@ -0,0 +1,100 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as react from 'react';
3
+ import react__default from 'react';
4
+ import * as _geenius_i18n_shared from '@geenius/i18n-shared';
5
+ import { I18nConfig, TranslationDict, Locale, Direction, I18nNamespace, TranslationEntry, MissingKey, LocaleStat } from '@geenius/i18n-shared';
6
+ export { Direction, I18nConfig, I18nNamespace, Locale, LocaleInfo, LocaleStat, MissingKey, TranslationDict, TranslationEntry } from '@geenius/i18n-shared';
7
+
8
+ interface I18nContextValue {
9
+ locale: Locale;
10
+ direction: Direction;
11
+ isRTL: boolean;
12
+ setLocale: (l: Locale) => void;
13
+ t: (key: string, params?: Record<string, string | number>) => string;
14
+ formatDate: (date: Date | string, opts?: Intl.DateTimeFormatOptions) => string;
15
+ formatNumber: (n: number, opts?: Intl.NumberFormatOptions) => string;
16
+ formatCurrency: (amount: number, currency: string) => string;
17
+ }
18
+ declare function I18nProvider({ children, config, translations }: {
19
+ children: react__default.ReactNode;
20
+ config: I18nConfig;
21
+ translations?: TranslationDict;
22
+ }): react_jsx_runtime.JSX.Element;
23
+ declare function useI18n(): I18nContextValue;
24
+
25
+ declare function useLocaleDetect(supportedLocales: Locale[]): {
26
+ detectedLocale: Locale;
27
+ isDetecting: boolean;
28
+ };
29
+
30
+ declare function useTranslations(locale: Locale, namespace: I18nNamespace): {
31
+ dict: TranslationDict;
32
+ isLoading: boolean;
33
+ t: (key: string, params?: Record<string, string | number>) => string;
34
+ };
35
+
36
+ declare function useI18nAdmin(data: {
37
+ translations?: TranslationEntry[];
38
+ missingKeys?: MissingKey[];
39
+ localeStats?: LocaleStat[];
40
+ }, mutations: {
41
+ upsert: (locale: string, ns: string, key: string, value: string) => Promise<void>;
42
+ deleteKey: (locale: string, key: string) => Promise<void>;
43
+ importDict: (locale: string, ns: string, dict: Record<string, string>) => Promise<void>;
44
+ clearMissing: (id: string) => Promise<void>;
45
+ }): {
46
+ upsert: (locale: string, ns: string, key: string, value: string) => Promise<void>;
47
+ deleteKey: (locale: string, key: string) => Promise<void>;
48
+ importDict: (locale: string, ns: string, dict: Record<string, string>) => Promise<void>;
49
+ clearMissing: (id: string) => Promise<void>;
50
+ translations: TranslationEntry[];
51
+ missingKeys: MissingKey[];
52
+ localeStats: LocaleStat[];
53
+ search: string;
54
+ setSearch: react.Dispatch<react.SetStateAction<string>>;
55
+ isLoading: boolean;
56
+ };
57
+
58
+ declare function LocaleSwitcher({ locales, current, onChange }: {
59
+ locales: Locale[];
60
+ current: Locale;
61
+ onChange: (l: Locale) => void;
62
+ }): react_jsx_runtime.JSX.Element;
63
+ declare function RTLWrapper({ children, locale }: {
64
+ children: react__default.ReactNode;
65
+ locale?: Locale;
66
+ }): react_jsx_runtime.JSX.Element;
67
+ declare function TranslationEditor({ onSave, initialKey, initialLocale, namespaces }: {
68
+ onSave: (locale: string, ns: string, key: string, value: string) => void;
69
+ initialKey?: string;
70
+ initialLocale?: Locale;
71
+ namespaces?: string[];
72
+ }): react_jsx_runtime.JSX.Element;
73
+ declare function TranslationTable({ translations, locale, onUpdate, onDelete }: {
74
+ translations: TranslationEntry[];
75
+ locale: Locale;
76
+ onUpdate?: (key: string, value: string) => void;
77
+ onDelete?: (key: string) => void;
78
+ }): react_jsx_runtime.JSX.Element;
79
+ declare function MissingKeyAlert({ count, locale }: {
80
+ count: number;
81
+ locale: Locale;
82
+ }): react_jsx_runtime.JSX.Element | null;
83
+ declare function LocaleStatsCard({ stats }: {
84
+ stats: LocaleStat[];
85
+ }): react_jsx_runtime.JSX.Element;
86
+
87
+ interface I18nAdminPageProps {
88
+ translations?: TranslationEntry[];
89
+ missingKeys?: MissingKey[];
90
+ localeStats?: LocaleStat[];
91
+ mutations: Parameters<typeof useI18nAdmin>[1];
92
+ }
93
+ declare function I18nAdminPage({ translations, missingKeys, localeStats, mutations }: I18nAdminPageProps): react_jsx_runtime.JSX.Element;
94
+
95
+ declare function LocalePreviewPage({ config, translations }: {
96
+ config?: Partial<_geenius_i18n_shared.I18nConfig>;
97
+ translations?: TranslationDict;
98
+ }): react_jsx_runtime.JSX.Element;
99
+
100
+ export { I18nAdminPage, I18nProvider, LocalePreviewPage, LocaleStatsCard, LocaleSwitcher, MissingKeyAlert, RTLWrapper, TranslationEditor, TranslationTable, useI18n, useI18nAdmin, useLocaleDetect, useTranslations };