@jant/core 0.1.2 → 0.2.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 (288) hide show
  1. package/dist/app.d.ts +34 -0
  2. package/dist/app.d.ts.map +1 -0
  3. package/dist/app.js +474 -0
  4. package/dist/assets/datastar.min.js +1775 -0
  5. package/dist/auth.d.ts +23 -0
  6. package/dist/auth.d.ts.map +1 -0
  7. package/dist/auth.js +34 -0
  8. package/{src/client.ts → dist/client.d.ts} +1 -1
  9. package/dist/client.d.ts.map +1 -0
  10. package/dist/client.js +4 -0
  11. package/dist/db/index.d.ts +10 -0
  12. package/dist/db/index.d.ts.map +1 -0
  13. package/dist/db/index.js +10 -0
  14. package/dist/db/schema.d.ts +1507 -0
  15. package/dist/db/schema.d.ts.map +1 -0
  16. package/dist/db/schema.js +183 -0
  17. package/{src/i18n/Trans.tsx → dist/i18n/Trans.d.ts} +4 -10
  18. package/dist/i18n/Trans.d.ts.map +1 -0
  19. package/dist/i18n/Trans.js +24 -0
  20. package/dist/i18n/context.d.ts +69 -0
  21. package/dist/i18n/context.d.ts.map +1 -0
  22. package/dist/i18n/context.js +61 -0
  23. package/dist/i18n/detect.d.ts +31 -0
  24. package/dist/i18n/detect.d.ts.map +1 -0
  25. package/dist/i18n/detect.js +77 -0
  26. package/{src/i18n/i18n.ts → dist/i18n/i18n.d.ts} +5 -25
  27. package/dist/i18n/i18n.d.ts.map +1 -0
  28. package/dist/i18n/i18n.js +55 -0
  29. package/dist/i18n/index.d.ts +41 -0
  30. package/dist/i18n/index.d.ts.map +1 -0
  31. package/{src/i18n/index.ts → dist/i18n/index.js} +3 -24
  32. package/dist/i18n/locales/en.d.ts +3 -0
  33. package/dist/i18n/locales/en.d.ts.map +1 -0
  34. package/dist/i18n/locales/en.js +1 -0
  35. package/dist/i18n/locales/zh-Hans.d.ts +3 -0
  36. package/dist/i18n/locales/zh-Hans.d.ts.map +1 -0
  37. package/dist/i18n/locales/zh-Hans.js +1 -0
  38. package/dist/i18n/locales/zh-Hant.d.ts +3 -0
  39. package/dist/i18n/locales/zh-Hant.d.ts.map +1 -0
  40. package/dist/i18n/locales/zh-Hant.js +1 -0
  41. package/dist/i18n/locales.d.ts +11 -0
  42. package/dist/i18n/locales.d.ts.map +1 -0
  43. package/dist/i18n/locales.js +13 -0
  44. package/dist/i18n/middleware.d.ts +24 -0
  45. package/dist/i18n/middleware.d.ts.map +1 -0
  46. package/dist/i18n/middleware.js +41 -0
  47. package/dist/index.d.ts +16 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/{src/index.ts → dist/index.js} +1 -28
  50. package/dist/lib/assets.d.ts +19 -0
  51. package/dist/lib/assets.d.ts.map +1 -0
  52. package/dist/lib/assets.js +33 -0
  53. package/dist/lib/constants.d.ts +36 -0
  54. package/dist/lib/constants.d.ts.map +1 -0
  55. package/dist/lib/constants.js +50 -0
  56. package/{src/lib/image.ts → dist/lib/image.d.ts} +13 -47
  57. package/dist/lib/image.d.ts.map +1 -0
  58. package/dist/lib/image.js +77 -0
  59. package/{src/lib/index.ts → dist/lib/index.d.ts} +1 -1
  60. package/dist/lib/index.d.ts.map +1 -0
  61. package/dist/lib/index.js +7 -0
  62. package/dist/lib/markdown.d.ts +60 -0
  63. package/dist/lib/markdown.d.ts.map +1 -0
  64. package/{src/lib/markdown.ts → dist/lib/markdown.js} +16 -26
  65. package/dist/lib/schemas.d.ts +113 -0
  66. package/dist/lib/schemas.d.ts.map +1 -0
  67. package/dist/lib/schemas.js +71 -0
  68. package/dist/lib/sqid.d.ts +60 -0
  69. package/dist/lib/sqid.d.ts.map +1 -0
  70. package/{src/lib/sqid.ts → dist/lib/sqid.js} +15 -22
  71. package/dist/lib/sse.d.ts +95 -0
  72. package/dist/lib/sse.d.ts.map +1 -0
  73. package/dist/lib/sse.js +81 -0
  74. package/dist/lib/time.d.ts +90 -0
  75. package/dist/lib/time.d.ts.map +1 -0
  76. package/{src/lib/time.ts → dist/lib/time.js} +20 -33
  77. package/{src/lib/url.ts → dist/lib/url.d.ts} +5 -30
  78. package/dist/lib/url.d.ts.map +1 -0
  79. package/dist/lib/url.js +89 -0
  80. package/dist/middleware/auth.d.ts +24 -0
  81. package/dist/middleware/auth.d.ts.map +1 -0
  82. package/dist/middleware/auth.js +52 -0
  83. package/dist/routes/api/posts.d.ts +13 -0
  84. package/dist/routes/api/posts.d.ts.map +1 -0
  85. package/dist/routes/api/posts.js +124 -0
  86. package/dist/routes/api/search.d.ts +13 -0
  87. package/dist/routes/api/search.d.ts.map +1 -0
  88. package/dist/routes/api/search.js +49 -0
  89. package/dist/routes/api/upload.d.ts +16 -0
  90. package/dist/routes/api/upload.d.ts.map +1 -0
  91. package/dist/routes/api/upload.js +227 -0
  92. package/dist/routes/dash/collections.d.ts +13 -0
  93. package/dist/routes/dash/collections.d.ts.map +1 -0
  94. package/dist/routes/dash/collections.js +512 -0
  95. package/dist/routes/dash/index.d.ts +15 -0
  96. package/dist/routes/dash/index.d.ts.map +1 -0
  97. package/dist/routes/dash/index.js +117 -0
  98. package/dist/routes/dash/media.d.ts +16 -0
  99. package/dist/routes/dash/media.d.ts.map +1 -0
  100. package/dist/routes/dash/media.js +589 -0
  101. package/dist/routes/dash/pages.d.ts +15 -0
  102. package/dist/routes/dash/pages.d.ts.map +1 -0
  103. package/dist/routes/dash/pages.js +290 -0
  104. package/dist/routes/dash/posts.d.ts +13 -0
  105. package/dist/routes/dash/posts.d.ts.map +1 -0
  106. package/dist/routes/dash/posts.js +226 -0
  107. package/dist/routes/dash/redirects.d.ts +13 -0
  108. package/dist/routes/dash/redirects.d.ts.map +1 -0
  109. package/dist/routes/dash/redirects.js +237 -0
  110. package/dist/routes/dash/settings.d.ts +13 -0
  111. package/dist/routes/dash/settings.d.ts.map +1 -0
  112. package/dist/routes/dash/settings.js +154 -0
  113. package/dist/routes/feed/rss.d.ts +13 -0
  114. package/dist/routes/feed/rss.d.ts.map +1 -0
  115. package/dist/routes/feed/rss.js +95 -0
  116. package/dist/routes/feed/sitemap.d.ts +13 -0
  117. package/dist/routes/feed/sitemap.d.ts.map +1 -0
  118. package/dist/routes/feed/sitemap.js +59 -0
  119. package/dist/routes/pages/archive.d.ts +15 -0
  120. package/dist/routes/pages/archive.d.ts.map +1 -0
  121. package/dist/routes/pages/archive.js +255 -0
  122. package/dist/routes/pages/collection.d.ts +13 -0
  123. package/dist/routes/pages/collection.d.ts.map +1 -0
  124. package/dist/routes/pages/collection.js +93 -0
  125. package/dist/routes/pages/home.d.ts +13 -0
  126. package/dist/routes/pages/home.d.ts.map +1 -0
  127. package/dist/routes/pages/home.js +122 -0
  128. package/dist/routes/pages/page.d.ts +15 -0
  129. package/dist/routes/pages/page.d.ts.map +1 -0
  130. package/dist/routes/pages/page.js +69 -0
  131. package/dist/routes/pages/post.d.ts +13 -0
  132. package/dist/routes/pages/post.d.ts.map +1 -0
  133. package/dist/routes/pages/post.js +90 -0
  134. package/dist/routes/pages/search.d.ts +13 -0
  135. package/dist/routes/pages/search.d.ts.map +1 -0
  136. package/dist/routes/pages/search.js +180 -0
  137. package/dist/services/collection.d.ts +31 -0
  138. package/dist/services/collection.d.ts.map +1 -0
  139. package/dist/services/collection.js +108 -0
  140. package/dist/services/index.d.ts +28 -0
  141. package/dist/services/index.d.ts.map +1 -0
  142. package/dist/services/index.js +20 -0
  143. package/dist/services/media.d.ts +27 -0
  144. package/dist/services/media.d.ts.map +1 -0
  145. package/dist/services/media.js +62 -0
  146. package/dist/services/post.d.ts +31 -0
  147. package/dist/services/post.d.ts.map +1 -0
  148. package/dist/services/post.js +191 -0
  149. package/dist/services/redirect.d.ts +15 -0
  150. package/dist/services/redirect.d.ts.map +1 -0
  151. package/dist/services/redirect.js +48 -0
  152. package/dist/services/search.d.ts +26 -0
  153. package/dist/services/search.d.ts.map +1 -0
  154. package/dist/services/search.js +61 -0
  155. package/dist/services/settings.d.ts +17 -0
  156. package/dist/services/settings.d.ts.map +1 -0
  157. package/dist/services/settings.js +65 -0
  158. package/dist/theme/components/ActionButtons.d.ts +43 -0
  159. package/dist/theme/components/ActionButtons.d.ts.map +1 -0
  160. package/dist/theme/components/ActionButtons.js +50 -0
  161. package/dist/theme/components/CrudPageHeader.d.ts +23 -0
  162. package/dist/theme/components/CrudPageHeader.d.ts.map +1 -0
  163. package/dist/theme/components/CrudPageHeader.js +22 -0
  164. package/dist/theme/components/DangerZone.d.ts +36 -0
  165. package/dist/theme/components/DangerZone.d.ts.map +1 -0
  166. package/dist/theme/components/DangerZone.js +39 -0
  167. package/dist/theme/components/EmptyState.d.ts +27 -0
  168. package/dist/theme/components/EmptyState.d.ts.map +1 -0
  169. package/dist/theme/components/EmptyState.js +27 -0
  170. package/dist/theme/components/ListItemRow.d.ts +15 -0
  171. package/dist/theme/components/ListItemRow.d.ts.map +1 -0
  172. package/dist/theme/components/ListItemRow.js +21 -0
  173. package/dist/theme/components/PageForm.d.ts +14 -0
  174. package/dist/theme/components/PageForm.d.ts.map +1 -0
  175. package/dist/theme/components/PageForm.js +173 -0
  176. package/dist/theme/components/Pagination.d.ts +46 -0
  177. package/dist/theme/components/Pagination.d.ts.map +1 -0
  178. package/dist/theme/components/Pagination.js +159 -0
  179. package/dist/theme/components/PostForm.d.ts +12 -0
  180. package/dist/theme/components/PostForm.d.ts.map +1 -0
  181. package/dist/theme/components/PostForm.js +230 -0
  182. package/dist/theme/components/PostList.d.ts +10 -0
  183. package/dist/theme/components/PostList.d.ts.map +1 -0
  184. package/dist/theme/components/PostList.js +73 -0
  185. package/dist/theme/components/ThreadView.d.ts +15 -0
  186. package/dist/theme/components/ThreadView.d.ts.map +1 -0
  187. package/dist/theme/components/ThreadView.js +111 -0
  188. package/dist/theme/components/TypeBadge.d.ts +12 -0
  189. package/dist/theme/components/TypeBadge.d.ts.map +1 -0
  190. package/dist/theme/components/TypeBadge.js +39 -0
  191. package/dist/theme/components/VisibilityBadge.d.ts +12 -0
  192. package/dist/theme/components/VisibilityBadge.d.ts.map +1 -0
  193. package/dist/theme/components/VisibilityBadge.js +37 -0
  194. package/{src/theme/components/index.ts → dist/theme/components/index.d.ts} +1 -0
  195. package/dist/theme/components/index.d.ts.map +1 -0
  196. package/dist/theme/components/index.js +12 -0
  197. package/dist/theme/index.d.ts +21 -0
  198. package/dist/theme/index.d.ts.map +1 -0
  199. package/{src/theme/index.ts → dist/theme/index.js} +1 -4
  200. package/dist/theme/layouts/BaseLayout.d.ts +16 -0
  201. package/dist/theme/layouts/BaseLayout.d.ts.map +1 -0
  202. package/dist/theme/layouts/BaseLayout.js +58 -0
  203. package/dist/theme/layouts/DashLayout.d.ts +15 -0
  204. package/dist/theme/layouts/DashLayout.d.ts.map +1 -0
  205. package/dist/theme/layouts/DashLayout.js +139 -0
  206. package/{src/theme/layouts/index.ts → dist/theme/layouts/index.d.ts} +1 -0
  207. package/dist/theme/layouts/index.d.ts.map +1 -0
  208. package/dist/theme/layouts/index.js +2 -0
  209. package/dist/theme/styles/main.css +2 -0
  210. package/dist/types.d.ts +179 -0
  211. package/dist/types.d.ts.map +1 -0
  212. package/dist/types.js +19 -0
  213. package/package.json +26 -26
  214. package/drizzle.config.ts +0 -10
  215. package/lingui.config.ts +0 -16
  216. package/src/app.tsx +0 -377
  217. package/src/assets/datastar.min.js +0 -8
  218. package/src/auth.ts +0 -38
  219. package/src/db/index.ts +0 -14
  220. package/src/db/migrations/0000_solid_moon_knight.sql +0 -118
  221. package/src/db/migrations/0001_add_search_fts.sql +0 -40
  222. package/src/db/migrations/0002_collection_path.sql +0 -2
  223. package/src/db/migrations/0003_collection_path_nullable.sql +0 -21
  224. package/src/db/migrations/0004_media_uuid.sql +0 -35
  225. package/src/db/migrations/meta/0000_snapshot.json +0 -784
  226. package/src/db/migrations/meta/_journal.json +0 -41
  227. package/src/db/schema.ts +0 -159
  228. package/src/i18n/EXAMPLES.md +0 -235
  229. package/src/i18n/README.md +0 -296
  230. package/src/i18n/context.tsx +0 -101
  231. package/src/i18n/detect.ts +0 -100
  232. package/src/i18n/locales/en.po +0 -875
  233. package/src/i18n/locales/en.ts +0 -1
  234. package/src/i18n/locales/zh-Hans.po +0 -875
  235. package/src/i18n/locales/zh-Hans.ts +0 -1
  236. package/src/i18n/locales/zh-Hant.po +0 -875
  237. package/src/i18n/locales/zh-Hant.ts +0 -1
  238. package/src/i18n/locales.ts +0 -14
  239. package/src/i18n/middleware.ts +0 -59
  240. package/src/lib/assets.ts +0 -47
  241. package/src/lib/constants.ts +0 -67
  242. package/src/lib/schemas.ts +0 -92
  243. package/src/lib/sse.ts +0 -152
  244. package/src/middleware/auth.ts +0 -59
  245. package/src/routes/api/posts.ts +0 -127
  246. package/src/routes/api/search.ts +0 -53
  247. package/src/routes/api/upload.ts +0 -240
  248. package/src/routes/dash/collections.tsx +0 -341
  249. package/src/routes/dash/index.tsx +0 -89
  250. package/src/routes/dash/media.tsx +0 -551
  251. package/src/routes/dash/pages.tsx +0 -245
  252. package/src/routes/dash/posts.tsx +0 -202
  253. package/src/routes/dash/redirects.tsx +0 -155
  254. package/src/routes/dash/settings.tsx +0 -93
  255. package/src/routes/feed/rss.ts +0 -119
  256. package/src/routes/feed/sitemap.ts +0 -75
  257. package/src/routes/pages/archive.tsx +0 -223
  258. package/src/routes/pages/collection.tsx +0 -79
  259. package/src/routes/pages/home.tsx +0 -93
  260. package/src/routes/pages/page.tsx +0 -64
  261. package/src/routes/pages/post.tsx +0 -81
  262. package/src/routes/pages/search.tsx +0 -162
  263. package/src/services/collection.ts +0 -180
  264. package/src/services/index.ts +0 -40
  265. package/src/services/media.ts +0 -97
  266. package/src/services/post.ts +0 -279
  267. package/src/services/redirect.ts +0 -74
  268. package/src/services/search.ts +0 -117
  269. package/src/services/settings.ts +0 -76
  270. package/src/theme/components/ActionButtons.tsx +0 -98
  271. package/src/theme/components/CrudPageHeader.tsx +0 -48
  272. package/src/theme/components/DangerZone.tsx +0 -77
  273. package/src/theme/components/EmptyState.tsx +0 -56
  274. package/src/theme/components/ListItemRow.tsx +0 -24
  275. package/src/theme/components/PageForm.tsx +0 -114
  276. package/src/theme/components/Pagination.tsx +0 -196
  277. package/src/theme/components/PostForm.tsx +0 -122
  278. package/src/theme/components/PostList.tsx +0 -68
  279. package/src/theme/components/ThreadView.tsx +0 -118
  280. package/src/theme/components/TypeBadge.tsx +0 -28
  281. package/src/theme/components/VisibilityBadge.tsx +0 -33
  282. package/src/theme/layouts/BaseLayout.tsx +0 -49
  283. package/src/theme/layouts/DashLayout.tsx +0 -108
  284. package/src/theme/styles/main.css +0 -52
  285. package/src/types.ts +0 -222
  286. package/tsconfig.json +0 -16
  287. package/vite.config.ts +0 -82
  288. package/wrangler.toml +0 -21
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBhB,CAAC;AAMH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYhB,CAAC;AAMH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOtB,CAAC;AAMH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAY3B,CAAC;AAMF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMpB,CAAC;AAMH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAInB,CAAC;AAOH,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASf,CAAC;AAEH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWlB,CAAC;AAEH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBlB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOvB,CAAC"}
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Drizzle Schema
3
+ *
4
+ * Database schema for Jant
5
+ */ import { sqliteTable, text, integer, primaryKey } from "drizzle-orm/sqlite-core";
6
+ // =============================================================================
7
+ // Posts
8
+ // =============================================================================
9
+ export const posts = sqliteTable("posts", {
10
+ id: integer("id").primaryKey({
11
+ autoIncrement: true
12
+ }),
13
+ type: text("type", {
14
+ enum: [
15
+ "note",
16
+ "article",
17
+ "link",
18
+ "quote",
19
+ "image",
20
+ "page"
21
+ ]
22
+ }).notNull(),
23
+ visibility: text("visibility", {
24
+ enum: [
25
+ "featured",
26
+ "quiet",
27
+ "unlisted",
28
+ "draft"
29
+ ]
30
+ }).notNull().default("quiet"),
31
+ title: text("title"),
32
+ path: text("path"),
33
+ content: text("content"),
34
+ contentHtml: text("content_html"),
35
+ sourceUrl: text("source_url"),
36
+ sourceName: text("source_name"),
37
+ sourceDomain: text("source_domain"),
38
+ replyToId: integer("reply_to_id"),
39
+ threadId: integer("thread_id"),
40
+ deletedAt: integer("deleted_at"),
41
+ publishedAt: integer("published_at").notNull(),
42
+ createdAt: integer("created_at").notNull(),
43
+ updatedAt: integer("updated_at").notNull()
44
+ });
45
+ // =============================================================================
46
+ // Media
47
+ // =============================================================================
48
+ export const media = sqliteTable("media", {
49
+ id: text("id").primaryKey(),
50
+ postId: integer("post_id").references(()=>posts.id),
51
+ filename: text("filename").notNull(),
52
+ originalName: text("original_name").notNull(),
53
+ mimeType: text("mime_type").notNull(),
54
+ size: integer("size").notNull(),
55
+ r2Key: text("r2_key").notNull(),
56
+ width: integer("width"),
57
+ height: integer("height"),
58
+ alt: text("alt"),
59
+ createdAt: integer("created_at").notNull()
60
+ });
61
+ // =============================================================================
62
+ // Collections
63
+ // =============================================================================
64
+ export const collections = sqliteTable("collections", {
65
+ id: integer("id").primaryKey({
66
+ autoIncrement: true
67
+ }),
68
+ path: text("path").unique(),
69
+ title: text("title").notNull(),
70
+ description: text("description"),
71
+ createdAt: integer("created_at").notNull(),
72
+ updatedAt: integer("updated_at").notNull()
73
+ });
74
+ // =============================================================================
75
+ // Post-Collections (Many-to-Many)
76
+ // =============================================================================
77
+ export const postCollections = sqliteTable("post_collections", {
78
+ postId: integer("post_id").notNull().references(()=>posts.id),
79
+ collectionId: integer("collection_id").notNull().references(()=>collections.id),
80
+ addedAt: integer("added_at").notNull()
81
+ }, (table)=>[
82
+ primaryKey({
83
+ columns: [
84
+ table.postId,
85
+ table.collectionId
86
+ ]
87
+ })
88
+ ]);
89
+ // =============================================================================
90
+ // Redirects
91
+ // =============================================================================
92
+ export const redirects = sqliteTable("redirects", {
93
+ id: integer("id").primaryKey({
94
+ autoIncrement: true
95
+ }),
96
+ fromPath: text("from_path").notNull().unique(),
97
+ toPath: text("to_path").notNull(),
98
+ type: integer("type", {
99
+ mode: "number"
100
+ }).notNull().default(301),
101
+ createdAt: integer("created_at").notNull()
102
+ });
103
+ // =============================================================================
104
+ // Settings (Key-Value)
105
+ // =============================================================================
106
+ export const settings = sqliteTable("settings", {
107
+ key: text("key").primaryKey(),
108
+ value: text("value").notNull(),
109
+ updatedAt: integer("updated_at").notNull()
110
+ });
111
+ // =============================================================================
112
+ // better-auth tables
113
+ // Note: Using { mode: "timestamp" } so drizzle auto-converts Date <-> integer
114
+ // =============================================================================
115
+ export const user = sqliteTable("user", {
116
+ id: text("id").primaryKey(),
117
+ name: text("name").notNull(),
118
+ email: text("email").notNull().unique(),
119
+ emailVerified: integer("email_verified", {
120
+ mode: "boolean"
121
+ }).notNull().default(false),
122
+ image: text("image"),
123
+ role: text("role").default("admin"),
124
+ createdAt: integer("created_at", {
125
+ mode: "timestamp"
126
+ }).notNull(),
127
+ updatedAt: integer("updated_at", {
128
+ mode: "timestamp"
129
+ }).notNull()
130
+ });
131
+ export const session = sqliteTable("session", {
132
+ id: text("id").primaryKey(),
133
+ expiresAt: integer("expires_at", {
134
+ mode: "timestamp"
135
+ }).notNull(),
136
+ token: text("token").notNull().unique(),
137
+ createdAt: integer("created_at", {
138
+ mode: "timestamp"
139
+ }).notNull(),
140
+ updatedAt: integer("updated_at", {
141
+ mode: "timestamp"
142
+ }).notNull(),
143
+ ipAddress: text("ip_address"),
144
+ userAgent: text("user_agent"),
145
+ userId: text("user_id").notNull().references(()=>user.id)
146
+ });
147
+ export const account = sqliteTable("account", {
148
+ id: text("id").primaryKey(),
149
+ accountId: text("account_id").notNull(),
150
+ providerId: text("provider_id").notNull(),
151
+ userId: text("user_id").notNull().references(()=>user.id),
152
+ accessToken: text("access_token"),
153
+ refreshToken: text("refresh_token"),
154
+ idToken: text("id_token"),
155
+ accessTokenExpiresAt: integer("access_token_expires_at", {
156
+ mode: "timestamp"
157
+ }),
158
+ refreshTokenExpiresAt: integer("refresh_token_expires_at", {
159
+ mode: "timestamp"
160
+ }),
161
+ scope: text("scope"),
162
+ password: text("password"),
163
+ createdAt: integer("created_at", {
164
+ mode: "timestamp"
165
+ }).notNull(),
166
+ updatedAt: integer("updated_at", {
167
+ mode: "timestamp"
168
+ }).notNull()
169
+ });
170
+ export const verification = sqliteTable("verification", {
171
+ id: text("id").primaryKey(),
172
+ identifier: text("identifier").notNull(),
173
+ value: text("value").notNull(),
174
+ expiresAt: integer("expires_at", {
175
+ mode: "timestamp"
176
+ }).notNull(),
177
+ createdAt: integer("created_at", {
178
+ mode: "timestamp"
179
+ }),
180
+ updatedAt: integer("updated_at", {
181
+ mode: "timestamp"
182
+ })
183
+ });
@@ -4,14 +4,11 @@
4
4
  * Simple implementation that just renders children directly.
5
5
  * For complex translations with embedded JSX, use the t() function with placeholders.
6
6
  */
7
-
8
7
  import type { FC, PropsWithChildren } from "hono/jsx";
9
-
10
8
  export interface TransProps extends PropsWithChildren {
11
- comment?: string;
12
- id?: string;
9
+ comment?: string;
10
+ id?: string;
13
11
  }
14
-
15
12
  /**
16
13
  * Trans component - renders children as-is
17
14
  * Note: This is a simplified implementation. For translations with embedded JSX,
@@ -24,8 +21,5 @@ export interface TransProps extends PropsWithChildren {
24
21
  * </Trans>
25
22
  * ```
26
23
  */
27
- export const Trans: FC<TransProps> = ({ children }) => {
28
- // In a full implementation, this would extract and translate the content
29
- // For now, we just render children as-is (works for English/default locale)
30
- return <>{children}</>;
31
- };
24
+ export declare const Trans: FC<TransProps>;
25
+ //# sourceMappingURL=Trans.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Trans.d.ts","sourceRoot":"","sources":["../../src/i18n/Trans.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAEtD,MAAM,WAAW,UAAW,SAAQ,iBAAiB;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,KAAK,EAAE,EAAE,CAAC,UAAU,CAIhC,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Trans Component for Hono JSX
3
+ *
4
+ * Simple implementation that just renders children directly.
5
+ * For complex translations with embedded JSX, use the t() function with placeholders.
6
+ */ import { jsx as _jsx, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
7
+ /**
8
+ * Trans component - renders children as-is
9
+ * Note: This is a simplified implementation. For translations with embedded JSX,
10
+ * it's recommended to use t() with placeholders instead.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * <Trans comment="@context: Help text">
15
+ * Visit the <a href="/docs">documentation</a>
16
+ * </Trans>
17
+ * ```
18
+ */ export const Trans = ({ children })=>{
19
+ // In a full implementation, this would extract and translate the content
20
+ // For now, we just render children as-is (works for English/default locale)
21
+ return /*#__PURE__*/ _jsx(_Fragment, {
22
+ children: children
23
+ });
24
+ };
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Hono JSX i18n Context System
3
+ *
4
+ * Mimics React's Context API for Hono JSX to provide i18n without prop drilling
5
+ */
6
+ import type { Context } from "hono";
7
+ import type { FC, PropsWithChildren } from "hono/jsx";
8
+ import type { I18n } from "@lingui/core";
9
+ /**
10
+ * Message descriptor that accepts both pre-macro (without id) and post-macro (with id) formats
11
+ * This allows TypeScript to accept t({ message, comment }) before macro transformation
12
+ */
13
+ type TranslationDescriptor = {
14
+ id?: string;
15
+ message: string;
16
+ comment?: string;
17
+ values?: Record<string, any>;
18
+ };
19
+ /**
20
+ * I18nProvider - wraps your app to provide i18n context
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * import { I18nProvider } from "@/i18n";
25
+ *
26
+ * return c.html(
27
+ * <I18nProvider c={c}>
28
+ * <YourApp />
29
+ * </I18nProvider>
30
+ * );
31
+ * ```
32
+ */
33
+ export interface I18nProviderProps extends PropsWithChildren {
34
+ c: Context;
35
+ }
36
+ export declare const I18nProvider: FC<I18nProviderProps>;
37
+ /**
38
+ * useLingui hook - get i18n instance and translation function
39
+ * Mimics @lingui/react's useLingui() API
40
+ *
41
+ * @example
42
+ * ```tsx
43
+ * import { t } from "@lingui/core/macro";
44
+ * import { useLingui } from "@/i18n";
45
+ *
46
+ * function MyComponent() {
47
+ * const { t: _ } = useLingui(); // Use _ to avoid conflict with macro
48
+ *
49
+ * return (
50
+ * <div>
51
+ * <h1>{_(t({ message: "Dashboard", comment: "@context: Page title" }))}</h1>
52
+ * </div>
53
+ * );
54
+ * }
55
+ * ```
56
+ *
57
+ * Or use the i18n instance directly:
58
+ * ```tsx
59
+ * const { i18n } = useLingui();
60
+ * i18n._(t({ message: "Dashboard", comment: "@context: Page title" }))
61
+ * ```
62
+ */
63
+ export declare function useLingui(): {
64
+ i18n: I18n;
65
+ t: (descriptor: TranslationDescriptor) => string;
66
+ _: (descriptor: TranslationDescriptor) => string;
67
+ };
68
+ export {};
69
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/i18n/context.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,cAAc,CAAC;AAG5D;;;GAGG;AACH,KAAK,qBAAqB,GAAG;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B,CAAC;AAKF;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,CAAC,EAAE,OAAO,CAAC;CACZ;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAM9C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS;;oBASQ,qBAAqB;oBAArB,qBAAqB;EAcrD"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Hono JSX i18n Context System
3
+ *
4
+ * Mimics React's Context API for Hono JSX to provide i18n without prop drilling
5
+ */ import { jsx as _jsx, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
6
+ import { getI18n as getI18nFromContext } from "./i18n.js";
7
+ // Store i18n instance during render
8
+ let currentI18n = null;
9
+ export const I18nProvider = ({ c, children })=>{
10
+ // Set current i18n for this render
11
+ // Note: In Hono JSX, rendering is synchronous and single-threaded per request
12
+ // so we can safely set global context without cleanup
13
+ currentI18n = getI18nFromContext(c);
14
+ return /*#__PURE__*/ _jsx(_Fragment, {
15
+ children: children
16
+ });
17
+ };
18
+ /**
19
+ * useLingui hook - get i18n instance and translation function
20
+ * Mimics @lingui/react's useLingui() API
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * import { t } from "@lingui/core/macro";
25
+ * import { useLingui } from "@/i18n";
26
+ *
27
+ * function MyComponent() {
28
+ * const { t: _ } = useLingui(); // Use _ to avoid conflict with macro
29
+ *
30
+ * return (
31
+ * <div>
32
+ * <h1>{_(t({ message: "Dashboard", comment: "@context: Page title" }))}</h1>
33
+ * </div>
34
+ * );
35
+ * }
36
+ * ```
37
+ *
38
+ * Or use the i18n instance directly:
39
+ * ```tsx
40
+ * const { i18n } = useLingui();
41
+ * i18n._(t({ message: "Dashboard", comment: "@context: Page title" }))
42
+ * ```
43
+ */ export function useLingui() {
44
+ if (!currentI18n) {
45
+ throw new Error("useLingui() called outside of I18nProvider. " + "Make sure your component is wrapped in <I18nProvider c={c}>...</I18nProvider>");
46
+ }
47
+ // Create translation function that accepts both pre-macro and post-macro formats
48
+ const translate = (descriptor)=>{
49
+ // The macro will add the id, or it's already present
50
+ // At runtime, we pass it to i18n._ which handles the descriptor with values
51
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- currentI18n is checked above
52
+ return currentI18n._(descriptor);
53
+ };
54
+ return {
55
+ i18n: currentI18n,
56
+ // t function - can be used with t macro from @lingui/core/macro
57
+ t: translate,
58
+ // _ is an alias for t (shorter)
59
+ _: translate
60
+ };
61
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Language Detection Utilities
3
+ */
4
+ import type { Context } from "hono";
5
+ import { type Locale } from "./locales.js";
6
+ export declare const LANGUAGE_COOKIE_NAME = "lang";
7
+ /**
8
+ * Get display name for a language code
9
+ */
10
+ export declare function getLanguageDisplayName(locale: Locale): string;
11
+ /**
12
+ * Get all supported languages with display names
13
+ */
14
+ export declare function getSupportedLanguages(): Array<{
15
+ code: Locale;
16
+ name: string;
17
+ }>;
18
+ /**
19
+ * Check if a language code is valid
20
+ */
21
+ export declare function isValidLanguage(lang: unknown): lang is Locale;
22
+ /**
23
+ * Parse Accept-Language header and return best matching locale
24
+ */
25
+ export declare function parseAcceptLanguage(header: string | null): Locale;
26
+ /**
27
+ * Detect user's preferred language from Hono context
28
+ * Priority: Cookie > Accept-Language header > Default
29
+ */
30
+ export declare function detectLanguage(c: Context): Locale;
31
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/i18n/detect.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAiC,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE1E,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAE3C;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAO7D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAK7E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAE7D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAwCjE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAYjD"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Language Detection Utilities
3
+ */ import { locales, baseLocale, isLocale } from "./locales.js";
4
+ export const LANGUAGE_COOKIE_NAME = "lang";
5
+ /**
6
+ * Get display name for a language code
7
+ */ export function getLanguageDisplayName(locale) {
8
+ const names = {
9
+ en: "English",
10
+ "zh-Hans": "简体中文",
11
+ "zh-Hant": "繁體中文"
12
+ };
13
+ return names[locale];
14
+ }
15
+ /**
16
+ * Get all supported languages with display names
17
+ */ export function getSupportedLanguages() {
18
+ return locales.map((code)=>({
19
+ code,
20
+ name: getLanguageDisplayName(code)
21
+ }));
22
+ }
23
+ /**
24
+ * Check if a language code is valid
25
+ */ export function isValidLanguage(lang) {
26
+ return isLocale(lang);
27
+ }
28
+ /**
29
+ * Parse Accept-Language header and return best matching locale
30
+ */ export function parseAcceptLanguage(header) {
31
+ if (!header) return baseLocale;
32
+ // Parse "en-US,en;q=0.9,zh-CN;q=0.8" format
33
+ const languages = header.split(",").map((part)=>{
34
+ const [lang, qPart] = part.trim().split(";");
35
+ const q = qPart ? parseFloat(qPart.replace("q=", "")) : 1;
36
+ return {
37
+ lang: lang?.trim() ?? "",
38
+ q
39
+ };
40
+ }).sort((a, b)=>b.q - a.q);
41
+ for (const { lang } of languages){
42
+ // Direct match
43
+ if (isLocale(lang)) {
44
+ return lang;
45
+ }
46
+ // Map common variants
47
+ const normalized = lang.toLowerCase();
48
+ if (normalized.startsWith("zh-cn") || normalized.startsWith("zh-hans")) {
49
+ return "zh-Hans";
50
+ }
51
+ if (normalized.startsWith("zh-tw") || normalized.startsWith("zh-hk") || normalized.startsWith("zh-hant")) {
52
+ return "zh-Hant";
53
+ }
54
+ if (normalized.startsWith("zh")) {
55
+ return "zh-Hans"; // Default Chinese to Simplified
56
+ }
57
+ if (normalized.startsWith("en")) {
58
+ return "en";
59
+ }
60
+ }
61
+ return baseLocale;
62
+ }
63
+ /**
64
+ * Detect user's preferred language from Hono context
65
+ * Priority: Cookie > Accept-Language header > Default
66
+ */ export function detectLanguage(c) {
67
+ // 1. Check cookie (using getCookie helper)
68
+ const cookies = c.req.raw.headers.get("Cookie") ?? "";
69
+ const cookieMatch = cookies.match(new RegExp(`${LANGUAGE_COOKIE_NAME}=([^;]+)`));
70
+ const cookieLang = cookieMatch?.[1];
71
+ if (cookieLang && isLocale(cookieLang)) {
72
+ return cookieLang;
73
+ }
74
+ // 2. Check Accept-Language header
75
+ const acceptLang = c.req.header("Accept-Language") ?? null;
76
+ return parseAcceptLanguage(acceptLang);
77
+ }
@@ -15,37 +15,16 @@
15
15
  *
16
16
  * The msg macro generates hash-based IDs at compile time, which match the compiled catalogs.
17
17
  */
18
-
19
18
  import { I18n } from "@lingui/core";
20
19
  import { locales, baseLocale, isLocale, type Locale } from "./locales.js";
21
- import { messages as messagesEn } from "./locales/en.js";
22
- import { messages as messagesZhHans } from "./locales/zh-Hans.js";
23
- import { messages as messagesZhHant } from "./locales/zh-Hant.js";
24
-
25
20
  export { locales, baseLocale, isLocale, type Locale };
26
-
27
- // Export I18n type for convenience
28
21
  export type { I18n };
29
-
30
22
  /**
31
23
  * Create a new i18n instance for a specific locale.
32
24
  * IMPORTANT: In Cloudflare Workers (concurrent environment), we must create
33
25
  * a new instance per request to avoid race conditions. Never use a global instance!
34
26
  */
35
- export function createI18n(locale: Locale): I18n {
36
- const i18n = new I18n({});
37
-
38
- // Load all catalogs with English as fallback
39
- i18n.load("en", messagesEn);
40
- i18n.load("zh-Hans", { ...messagesEn, ...messagesZhHans });
41
- i18n.load("zh-Hant", { ...messagesEn, ...messagesZhHant });
42
-
43
- // Activate locale after loading messages to avoid warnings
44
- i18n.activate(locale);
45
-
46
- return i18n;
47
- }
48
-
27
+ export declare function createI18n(locale: Locale): I18n;
49
28
  /**
50
29
  * Helper to get the per-request i18n instance from Hono context.
51
30
  * Use this in route handlers.
@@ -57,6 +36,7 @@ export function createI18n(locale: Locale): I18n {
57
36
  * const i18n = getI18n(c);
58
37
  * const title = i18n._(msg({ message: "Dashboard", comment: "@context: Page title" }));
59
38
  */
60
- export function getI18n(c: { get(key: "i18n"): I18n }): I18n {
61
- return c.get("i18n");
62
- }
39
+ export declare function getI18n(c: {
40
+ get(key: "i18n"): I18n;
41
+ }): I18n;
42
+ //# sourceMappingURL=i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/i18n/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAK1E,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;AAGtD,YAAY,EAAE,IAAI,EAAE,CAAC;AAErB;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAY/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE;IAAE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAE3D"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * i18n Runtime using @lingui/core with Lingui macros
3
+ *
4
+ * Usage:
5
+ * import { msg } from "@lingui/core/macro";
6
+ * import { bindI18n } from "@/i18n";
7
+ *
8
+ * const { i18n } = bindI18n(c.get("i18n"));
9
+ *
10
+ * // Simple message
11
+ * i18n._(msg({ message: "Hello", comment: "@context: Greeting" }))
12
+ *
13
+ * // With interpolation
14
+ * i18n._(msg({ message: "Welcome, {name}!", comment: "@context: Welcome" }), { name })
15
+ *
16
+ * The msg macro generates hash-based IDs at compile time, which match the compiled catalogs.
17
+ */ import { I18n } from "@lingui/core";
18
+ import { locales, baseLocale, isLocale } from "./locales.js";
19
+ import { messages as messagesEn } from "./locales/en.js";
20
+ import { messages as messagesZhHans } from "./locales/zh-Hans.js";
21
+ import { messages as messagesZhHant } from "./locales/zh-Hant.js";
22
+ export { locales, baseLocale, isLocale };
23
+ /**
24
+ * Create a new i18n instance for a specific locale.
25
+ * IMPORTANT: In Cloudflare Workers (concurrent environment), we must create
26
+ * a new instance per request to avoid race conditions. Never use a global instance!
27
+ */ export function createI18n(locale) {
28
+ const i18n = new I18n({});
29
+ // Load all catalogs with English as fallback
30
+ i18n.load("en", messagesEn);
31
+ i18n.load("zh-Hans", {
32
+ ...messagesEn,
33
+ ...messagesZhHans
34
+ });
35
+ i18n.load("zh-Hant", {
36
+ ...messagesEn,
37
+ ...messagesZhHant
38
+ });
39
+ // Activate locale after loading messages to avoid warnings
40
+ i18n.activate(locale);
41
+ return i18n;
42
+ }
43
+ /**
44
+ * Helper to get the per-request i18n instance from Hono context.
45
+ * Use this in route handlers.
46
+ *
47
+ * @example
48
+ * import { msg } from "@lingui/core/macro";
49
+ * import { getI18n } from "@/i18n";
50
+ *
51
+ * const i18n = getI18n(c);
52
+ * const title = i18n._(msg({ message: "Dashboard", comment: "@context: Page title" }));
53
+ */ export function getI18n(c) {
54
+ return c.get("i18n");
55
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * i18n Module
3
+ *
4
+ * IMPORTANT: This module is designed for concurrent environments (Cloudflare Workers).
5
+ * We create a new i18n instance per request to avoid race conditions.
6
+ *
7
+ * This is a custom implementation compatible with Hono JSX (SSR), not React.
8
+ * It provides a React-like API using Lingui macros with a custom context system.
9
+ *
10
+ * Usage:
11
+ * ```tsx
12
+ * import { useLingui, Trans, I18nProvider } from "@/i18n";
13
+ *
14
+ * // Wrap your app in I18nProvider (automatically done by BaseLayout when c is provided)
15
+ * c.html(
16
+ * <I18nProvider c={c}>
17
+ * <MyApp />
18
+ * </I18nProvider>
19
+ * );
20
+ *
21
+ * // Inside components, use useLingui() hook
22
+ * function MyApp() {
23
+ * const { t } = useLingui();
24
+ *
25
+ * return (
26
+ * <div>
27
+ * <h1>{t({ message: "Dashboard", comment: "@context: Page title" })}</h1>
28
+ * <Trans comment="@context: Help text">
29
+ * Read the <a href="/docs">documentation</a>
30
+ * </Trans>
31
+ * </div>
32
+ * );
33
+ * }
34
+ * ```
35
+ */
36
+ export { createI18n, getI18n, locales, baseLocale, isLocale, type Locale, type I18n, } from "./i18n.js";
37
+ export { I18nProvider, useLingui } from "./context.js";
38
+ export { Trans } from "./Trans.js";
39
+ export { detectLanguage, isValidLanguage, parseAcceptLanguage, getLanguageDisplayName, getSupportedLanguages, LANGUAGE_COOKIE_NAME, } from "./detect.js";
40
+ export { i18nMiddleware } from "./middleware.js";
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/i18n/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,EACL,UAAU,EACV,OAAO,EACP,OAAO,EACP,UAAU,EACV,QAAQ,EACR,KAAK,MAAM,EACX,KAAK,IAAI,GACV,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGvD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EACL,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}