@agent-native/core 0.75.5 → 0.76.1

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 (460) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +48 -0
  3. package/corpus/core/docs/AGENTS.md +1 -0
  4. package/corpus/core/docs/content/client.md +15 -0
  5. package/corpus/core/docs/content/internationalization.md +145 -0
  6. package/corpus/core/docs/content/locales/ar-SA/internationalization.md +102 -0
  7. package/corpus/core/docs/content/locales/de-DE/internationalization.md +102 -0
  8. package/corpus/core/docs/content/locales/es-ES/internationalization.md +102 -0
  9. package/corpus/core/docs/content/locales/fr-FR/internationalization.md +102 -0
  10. package/corpus/core/docs/content/locales/hi-IN/internationalization.md +102 -0
  11. package/corpus/core/docs/content/locales/ja-JP/internationalization.md +114 -0
  12. package/corpus/core/docs/content/locales/ko-KR/internationalization.md +102 -0
  13. package/corpus/core/docs/content/locales/pt-BR/internationalization.md +102 -0
  14. package/corpus/core/docs/content/locales/zh-CN/internationalization.md +102 -0
  15. package/corpus/core/docs/content/skills-guide.md +19 -18
  16. package/corpus/core/package.json +7 -1
  17. package/corpus/core/src/agent/durable-background.ts +38 -2
  18. package/corpus/core/src/agent/production-agent.ts +54 -0
  19. package/corpus/core/src/agent/run-manager.ts +27 -0
  20. package/corpus/core/src/agent/run-store.ts +185 -4
  21. package/corpus/core/src/client/CommandMenu.tsx +16 -0
  22. package/corpus/core/src/client/app-providers.tsx +26 -1
  23. package/corpus/core/src/client/i18n.tsx +605 -0
  24. package/corpus/core/src/client/index.ts +28 -0
  25. package/corpus/core/src/index.browser.ts +25 -0
  26. package/corpus/core/src/localization/actions/get-localization-preference.ts +23 -0
  27. package/corpus/core/src/localization/actions/set-localization-preference.ts +30 -0
  28. package/corpus/core/src/localization/index.ts +2 -0
  29. package/corpus/core/src/localization/server.ts +131 -0
  30. package/corpus/core/src/localization/shared.ts +163 -0
  31. package/corpus/core/src/server/action-discovery.ts +8 -0
  32. package/corpus/core/src/server/agent-chat-plugin.ts +71 -0
  33. package/corpus/core/src/server/auth.ts +13 -0
  34. package/corpus/core/src/server/index.ts +8 -0
  35. package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  36. package/corpus/core/src/templates/default/.agents/skills/internationalization/SKILL.md +77 -0
  37. package/corpus/core/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +6 -0
  38. package/corpus/core/src/templates/default/AGENTS.md +16 -15
  39. package/corpus/core/src/templates/default/app/i18n/en-US.ts +29 -0
  40. package/corpus/core/src/templates/default/app/i18n/index.ts +13 -0
  41. package/corpus/core/src/templates/default/app/root.tsx +20 -1
  42. package/corpus/core/src/templates/default/app/routes/_index.tsx +24 -9
  43. package/corpus/core/src/templates/default/app/routes/settings.tsx +67 -0
  44. package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  45. package/corpus/core/src/templates/workspace-core/.agents/skills/internationalization/SKILL.md +77 -0
  46. package/corpus/core/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +6 -0
  47. package/corpus/core/src/vite/action-types-plugin.ts +10 -0
  48. package/corpus/templates/analytics/.agents/skills/self-modifying-code/SKILL.md +6 -0
  49. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +12 -12
  50. package/corpus/templates/analytics/app/components/layout/Header.tsx +18 -15
  51. package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -5
  52. package/corpus/templates/analytics/app/components/layout/MobileNav.tsx +9 -3
  53. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +28 -26
  54. package/corpus/templates/analytics/app/i18n/ar-SA.ts +3 -0
  55. package/corpus/templates/analytics/app/i18n/de-DE.ts +3 -0
  56. package/corpus/templates/analytics/app/i18n/en-US.ts +3 -0
  57. package/corpus/templates/analytics/app/i18n/es-ES.ts +3 -0
  58. package/corpus/templates/analytics/app/i18n/fr-FR.ts +3 -0
  59. package/corpus/templates/analytics/app/i18n/hi-IN.ts +3 -0
  60. package/corpus/templates/analytics/app/i18n/index.ts +31 -0
  61. package/corpus/templates/analytics/app/i18n/ja-JP.ts +3 -0
  62. package/corpus/templates/analytics/app/i18n/ko-KR.ts +3 -0
  63. package/corpus/templates/analytics/app/i18n/pt-BR.ts +3 -0
  64. package/corpus/templates/analytics/app/i18n/zh-CN.ts +3 -0
  65. package/corpus/templates/analytics/app/i18n-data.ts +433 -0
  66. package/corpus/templates/analytics/app/pages/Settings.tsx +50 -16
  67. package/corpus/templates/analytics/app/pages/analyses/AnalysesList.tsx +2 -2
  68. package/corpus/templates/analytics/app/root.tsx +14 -1
  69. package/corpus/templates/analytics/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  70. package/corpus/templates/analytics/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  71. package/corpus/templates/assets/.agents/skills/self-modifying-code/SKILL.md +6 -0
  72. package/corpus/templates/assets/app/components/layout/Header.tsx +17 -8
  73. package/corpus/templates/assets/app/components/layout/Layout.tsx +10 -6
  74. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +40 -23
  75. package/corpus/templates/assets/app/i18n/ar-SA.ts +3 -0
  76. package/corpus/templates/assets/app/i18n/de-DE.ts +3 -0
  77. package/corpus/templates/assets/app/i18n/en-US.ts +3 -0
  78. package/corpus/templates/assets/app/i18n/es-ES.ts +3 -0
  79. package/corpus/templates/assets/app/i18n/fr-FR.ts +3 -0
  80. package/corpus/templates/assets/app/i18n/hi-IN.ts +3 -0
  81. package/corpus/templates/assets/app/i18n/index.ts +31 -0
  82. package/corpus/templates/assets/app/i18n/ja-JP.ts +3 -0
  83. package/corpus/templates/assets/app/i18n/ko-KR.ts +3 -0
  84. package/corpus/templates/assets/app/i18n/pt-BR.ts +3 -0
  85. package/corpus/templates/assets/app/i18n/zh-CN.ts +3 -0
  86. package/corpus/templates/assets/app/i18n-data.ts +668 -0
  87. package/corpus/templates/assets/app/root.tsx +40 -15
  88. package/corpus/templates/assets/app/routes/_index.tsx +9 -10
  89. package/corpus/templates/assets/app/routes/settings.tsx +37 -6
  90. package/corpus/templates/assets/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  91. package/corpus/templates/assets/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  92. package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +5 -0
  93. package/corpus/templates/brain/.agents/skills/self-modifying-code/SKILL.md +6 -0
  94. package/corpus/templates/brain/app/components/layout/Layout.tsx +12 -8
  95. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +23 -12
  96. package/corpus/templates/brain/app/i18n/ar-SA.ts +3 -0
  97. package/corpus/templates/brain/app/i18n/de-DE.ts +3 -0
  98. package/corpus/templates/brain/app/i18n/en-US.ts +3 -0
  99. package/corpus/templates/brain/app/i18n/es-ES.ts +3 -0
  100. package/corpus/templates/brain/app/i18n/fr-FR.ts +3 -0
  101. package/corpus/templates/brain/app/i18n/hi-IN.ts +3 -0
  102. package/corpus/templates/brain/app/i18n/index.ts +31 -0
  103. package/corpus/templates/brain/app/i18n/ja-JP.ts +3 -0
  104. package/corpus/templates/brain/app/i18n/ko-KR.ts +3 -0
  105. package/corpus/templates/brain/app/i18n/pt-BR.ts +3 -0
  106. package/corpus/templates/brain/app/i18n/zh-CN.ts +3 -0
  107. package/corpus/templates/brain/app/i18n-data.ts +624 -0
  108. package/corpus/templates/brain/app/root.tsx +27 -12
  109. package/corpus/templates/brain/app/routes/knowledge.tsx +6 -6
  110. package/corpus/templates/brain/app/routes/ops.tsx +4 -4
  111. package/corpus/templates/brain/app/routes/search.tsx +4 -4
  112. package/corpus/templates/brain/app/routes/settings.tsx +48 -11
  113. package/corpus/templates/brain/app/routes/sources.tsx +3 -3
  114. package/corpus/templates/brain/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  115. package/corpus/templates/brain/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  116. package/corpus/templates/calendar/.agents/skills/self-modifying-code/SKILL.md +6 -0
  117. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +2 -0
  118. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +16 -9
  119. package/corpus/templates/calendar/app/i18n/ar-SA.ts +57 -0
  120. package/corpus/templates/calendar/app/i18n/de-DE.ts +58 -0
  121. package/corpus/templates/calendar/app/i18n/en-US.ts +57 -0
  122. package/corpus/templates/calendar/app/i18n/es-ES.ts +58 -0
  123. package/corpus/templates/calendar/app/i18n/fr-FR.ts +58 -0
  124. package/corpus/templates/calendar/app/i18n/hi-IN.ts +57 -0
  125. package/corpus/templates/calendar/app/i18n/index.ts +31 -0
  126. package/corpus/templates/calendar/app/i18n/ja-JP.ts +58 -0
  127. package/corpus/templates/calendar/app/i18n/ko-KR.ts +57 -0
  128. package/corpus/templates/calendar/app/i18n/pt-BR.ts +57 -0
  129. package/corpus/templates/calendar/app/i18n/zh-CN.ts +57 -0
  130. package/corpus/templates/calendar/app/i18n-data.ts +516 -0
  131. package/corpus/templates/calendar/app/pages/CalendarView.tsx +2 -0
  132. package/corpus/templates/calendar/app/pages/Settings.tsx +63 -28
  133. package/corpus/templates/calendar/app/root.tsx +78 -7
  134. package/corpus/templates/calendar/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  135. package/corpus/templates/calendar/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  136. package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +5 -0
  137. package/corpus/templates/chat/.agents/skills/self-modifying-code/SKILL.md +6 -0
  138. package/corpus/templates/chat/app/components/layout/Header.tsx +17 -11
  139. package/corpus/templates/chat/app/components/layout/Layout.tsx +12 -8
  140. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +47 -18
  141. package/corpus/templates/chat/app/i18n/ar-SA.ts +62 -0
  142. package/corpus/templates/chat/app/i18n/de-DE.ts +63 -0
  143. package/corpus/templates/chat/app/i18n/en-US.ts +63 -0
  144. package/corpus/templates/chat/app/i18n/es-ES.ts +63 -0
  145. package/corpus/templates/chat/app/i18n/fr-FR.ts +63 -0
  146. package/corpus/templates/chat/app/i18n/hi-IN.ts +63 -0
  147. package/corpus/templates/chat/app/i18n/index.ts +31 -0
  148. package/corpus/templates/chat/app/i18n/ja-JP.ts +63 -0
  149. package/corpus/templates/chat/app/i18n/ko-KR.ts +63 -0
  150. package/corpus/templates/chat/app/i18n/pt-BR.ts +63 -0
  151. package/corpus/templates/chat/app/i18n/zh-CN.ts +61 -0
  152. package/corpus/templates/chat/app/i18n-data.ts +475 -0
  153. package/corpus/templates/chat/app/root.tsx +18 -5
  154. package/corpus/templates/chat/app/routes/_index.tsx +9 -8
  155. package/corpus/templates/chat/app/routes/settings.tsx +86 -0
  156. package/corpus/templates/chat/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  157. package/corpus/templates/chat/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  158. package/corpus/templates/clips/.agents/skills/self-modifying-code/SKILL.md +6 -0
  159. package/corpus/templates/clips/app/components/layout/Header.tsx +23 -17
  160. package/corpus/templates/clips/app/components/library/empty-state.tsx +10 -34
  161. package/corpus/templates/clips/app/components/library/library-layout.tsx +45 -34
  162. package/corpus/templates/clips/app/i18n/ar-SA.ts +182 -0
  163. package/corpus/templates/clips/app/i18n/de-DE.ts +184 -0
  164. package/corpus/templates/clips/app/i18n/en-US.ts +179 -0
  165. package/corpus/templates/clips/app/i18n/es-ES.ts +183 -0
  166. package/corpus/templates/clips/app/i18n/fr-FR.ts +184 -0
  167. package/corpus/templates/clips/app/i18n/hi-IN.ts +180 -0
  168. package/corpus/templates/clips/app/i18n/index.ts +41 -0
  169. package/corpus/templates/clips/app/i18n/ja-JP.ts +180 -0
  170. package/corpus/templates/clips/app/i18n/ko-KR.ts +178 -0
  171. package/corpus/templates/clips/app/i18n/pt-BR.ts +183 -0
  172. package/corpus/templates/clips/app/i18n/zh-CN.ts +173 -0
  173. package/corpus/templates/clips/app/root.tsx +104 -10
  174. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +154 -95
  175. package/corpus/templates/clips/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  176. package/corpus/templates/clips/changelog/2026-06-24-clips-now-includes-a-language-picker-and-simplified-chinese-ui.md +6 -0
  177. package/corpus/templates/clips/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  178. package/corpus/templates/content/.agents/skills/self-modifying-code/SKILL.md +6 -0
  179. package/corpus/templates/content/app/components/EmptyState.tsx +7 -5
  180. package/corpus/templates/content/app/components/ThemeToggle.tsx +4 -2
  181. package/corpus/templates/content/app/components/layout/Header.tsx +2 -0
  182. package/corpus/templates/content/app/components/layout/Layout.tsx +8 -7
  183. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +41 -1
  184. package/corpus/templates/content/app/i18n/ar-SA.ts +3 -0
  185. package/corpus/templates/content/app/i18n/de-DE.ts +3 -0
  186. package/corpus/templates/content/app/i18n/en-US.ts +3 -0
  187. package/corpus/templates/content/app/i18n/es-ES.ts +3 -0
  188. package/corpus/templates/content/app/i18n/fr-FR.ts +3 -0
  189. package/corpus/templates/content/app/i18n/hi-IN.ts +3 -0
  190. package/corpus/templates/content/app/i18n/index.ts +31 -0
  191. package/corpus/templates/content/app/i18n/ja-JP.ts +3 -0
  192. package/corpus/templates/content/app/i18n/ko-KR.ts +3 -0
  193. package/corpus/templates/content/app/i18n/pt-BR.ts +3 -0
  194. package/corpus/templates/content/app/i18n/zh-CN.ts +3 -0
  195. package/corpus/templates/content/app/i18n-data.ts +490 -0
  196. package/corpus/templates/content/app/root.tsx +110 -23
  197. package/corpus/templates/content/app/routes/_app.settings.tsx +84 -0
  198. package/corpus/templates/content/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  199. package/corpus/templates/content/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  200. package/corpus/templates/design/.agents/skills/self-modifying-code/SKILL.md +6 -0
  201. package/corpus/templates/design/app/components/layout/Header.tsx +16 -8
  202. package/corpus/templates/design/app/components/layout/Layout.tsx +8 -6
  203. package/corpus/templates/design/app/components/layout/Sidebar.tsx +25 -9
  204. package/corpus/templates/design/app/i18n/ar-SA.ts +3 -0
  205. package/corpus/templates/design/app/i18n/de-DE.ts +3 -0
  206. package/corpus/templates/design/app/i18n/en-US.ts +3 -0
  207. package/corpus/templates/design/app/i18n/es-ES.ts +3 -0
  208. package/corpus/templates/design/app/i18n/fr-FR.ts +3 -0
  209. package/corpus/templates/design/app/i18n/hi-IN.ts +3 -0
  210. package/corpus/templates/design/app/i18n/index.ts +31 -0
  211. package/corpus/templates/design/app/i18n/ja-JP.ts +3 -0
  212. package/corpus/templates/design/app/i18n/ko-KR.ts +3 -0
  213. package/corpus/templates/design/app/i18n/pt-BR.ts +3 -0
  214. package/corpus/templates/design/app/i18n/zh-CN.ts +3 -0
  215. package/corpus/templates/design/app/i18n-data.ts +350 -0
  216. package/corpus/templates/design/app/root.tsx +40 -15
  217. package/corpus/templates/design/app/routes/settings.tsx +43 -0
  218. package/corpus/templates/design/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  219. package/corpus/templates/design/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  220. package/corpus/templates/dispatch/.agents/skills/self-modifying-code/SKILL.md +6 -0
  221. package/corpus/templates/dispatch/app/i18n/ar-SA.ts +3 -0
  222. package/corpus/templates/dispatch/app/i18n/de-DE.ts +3 -0
  223. package/corpus/templates/dispatch/app/i18n/en-US.ts +3 -0
  224. package/corpus/templates/dispatch/app/i18n/es-ES.ts +3 -0
  225. package/corpus/templates/dispatch/app/i18n/fr-FR.ts +3 -0
  226. package/corpus/templates/dispatch/app/i18n/hi-IN.ts +3 -0
  227. package/corpus/templates/dispatch/app/i18n/index.ts +31 -0
  228. package/corpus/templates/dispatch/app/i18n/ja-JP.ts +3 -0
  229. package/corpus/templates/dispatch/app/i18n/ko-KR.ts +3 -0
  230. package/corpus/templates/dispatch/app/i18n/pt-BR.ts +3 -0
  231. package/corpus/templates/dispatch/app/i18n/zh-CN.ts +3 -0
  232. package/corpus/templates/dispatch/app/i18n-data.ts +267 -0
  233. package/corpus/templates/dispatch/app/root.tsx +18 -4
  234. package/corpus/templates/dispatch/app/routes/settings.tsx +86 -0
  235. package/corpus/templates/dispatch/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  236. package/corpus/templates/dispatch/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  237. package/corpus/templates/forms/.agents/skills/self-modifying-code/SKILL.md +6 -0
  238. package/corpus/templates/forms/app/components/layout/Header.tsx +16 -9
  239. package/corpus/templates/forms/app/components/layout/Layout.tsx +6 -4
  240. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +34 -17
  241. package/corpus/templates/forms/app/i18n/ar-SA.ts +58 -0
  242. package/corpus/templates/forms/app/i18n/de-DE.ts +59 -0
  243. package/corpus/templates/forms/app/i18n/en-US.ts +59 -0
  244. package/corpus/templates/forms/app/i18n/es-ES.ts +59 -0
  245. package/corpus/templates/forms/app/i18n/fr-FR.ts +59 -0
  246. package/corpus/templates/forms/app/i18n/hi-IN.ts +59 -0
  247. package/corpus/templates/forms/app/i18n/index.ts +31 -0
  248. package/corpus/templates/forms/app/i18n/ja-JP.ts +59 -0
  249. package/corpus/templates/forms/app/i18n/ko-KR.ts +59 -0
  250. package/corpus/templates/forms/app/i18n/pt-BR.ts +59 -0
  251. package/corpus/templates/forms/app/i18n/zh-CN.ts +56 -0
  252. package/corpus/templates/forms/app/root.tsx +65 -16
  253. package/corpus/templates/forms/app/routes/_app.settings.tsx +85 -0
  254. package/corpus/templates/forms/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  255. package/corpus/templates/forms/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  256. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +29 -17
  257. package/corpus/templates/macros/app/components/layout/Header.tsx +16 -10
  258. package/corpus/templates/macros/app/i18n/ar-SA.ts +54 -0
  259. package/corpus/templates/macros/app/i18n/de-DE.ts +55 -0
  260. package/corpus/templates/macros/app/i18n/en-US.ts +55 -0
  261. package/corpus/templates/macros/app/i18n/es-ES.ts +55 -0
  262. package/corpus/templates/macros/app/i18n/fr-FR.ts +55 -0
  263. package/corpus/templates/macros/app/i18n/hi-IN.ts +55 -0
  264. package/corpus/templates/macros/app/i18n/index.ts +31 -0
  265. package/corpus/templates/macros/app/i18n/ja-JP.ts +55 -0
  266. package/corpus/templates/macros/app/i18n/ko-KR.ts +55 -0
  267. package/corpus/templates/macros/app/i18n/pt-BR.ts +55 -0
  268. package/corpus/templates/macros/app/i18n/zh-CN.ts +53 -0
  269. package/corpus/templates/macros/app/root.tsx +65 -15
  270. package/corpus/templates/macros/app/routes/settings.tsx +85 -0
  271. package/corpus/templates/macros/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  272. package/corpus/templates/macros/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  273. package/corpus/templates/mail/.agents/skills/self-modifying-code/SKILL.md +6 -0
  274. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +9 -4
  275. package/corpus/templates/mail/app/i18n/ar-SA.ts +33 -0
  276. package/corpus/templates/mail/app/i18n/de-DE.ts +33 -0
  277. package/corpus/templates/mail/app/i18n/en-US.ts +32 -0
  278. package/corpus/templates/mail/app/i18n/es-ES.ts +33 -0
  279. package/corpus/templates/mail/app/i18n/fr-FR.ts +33 -0
  280. package/corpus/templates/mail/app/i18n/hi-IN.ts +32 -0
  281. package/corpus/templates/mail/app/i18n/index.ts +31 -0
  282. package/corpus/templates/mail/app/i18n/ja-JP.ts +32 -0
  283. package/corpus/templates/mail/app/i18n/ko-KR.ts +33 -0
  284. package/corpus/templates/mail/app/i18n/pt-BR.ts +34 -0
  285. package/corpus/templates/mail/app/i18n/zh-CN.ts +32 -0
  286. package/corpus/templates/mail/app/pages/SettingsPage.tsx +67 -13
  287. package/corpus/templates/mail/app/root.tsx +20 -0
  288. package/corpus/templates/mail/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  289. package/corpus/templates/mail/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  290. package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +5 -0
  291. package/corpus/templates/plan/.agents/skills/self-modifying-code/SKILL.md +6 -0
  292. package/corpus/templates/plan/app/components/layout/Header.tsx +19 -12
  293. package/corpus/templates/plan/app/components/layout/Layout.tsx +11 -7
  294. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +41 -28
  295. package/corpus/templates/plan/app/i18n/ar-SA.ts +77 -0
  296. package/corpus/templates/plan/app/i18n/de-DE.ts +78 -0
  297. package/corpus/templates/plan/app/i18n/en-US.ts +78 -0
  298. package/corpus/templates/plan/app/i18n/es-ES.ts +78 -0
  299. package/corpus/templates/plan/app/i18n/fr-FR.ts +78 -0
  300. package/corpus/templates/plan/app/i18n/hi-IN.ts +78 -0
  301. package/corpus/templates/plan/app/i18n/index.ts +31 -0
  302. package/corpus/templates/plan/app/i18n/ja-JP.ts +79 -0
  303. package/corpus/templates/plan/app/i18n/ko-KR.ts +77 -0
  304. package/corpus/templates/plan/app/i18n/pt-BR.ts +78 -0
  305. package/corpus/templates/plan/app/i18n/zh-CN.ts +74 -0
  306. package/corpus/templates/plan/app/root.tsx +45 -8
  307. package/corpus/templates/plan/app/routes/settings.tsx +86 -0
  308. package/corpus/templates/plan/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  309. package/corpus/templates/plan/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  310. package/corpus/templates/slides/.agents/skills/self-modifying-code/SKILL.md +6 -0
  311. package/corpus/templates/slides/app/components/layout/Header.tsx +23 -11
  312. package/corpus/templates/slides/app/components/layout/Layout.tsx +7 -6
  313. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +23 -11
  314. package/corpus/templates/slides/app/i18n/ar-SA.ts +54 -0
  315. package/corpus/templates/slides/app/i18n/de-DE.ts +56 -0
  316. package/corpus/templates/slides/app/i18n/en-US.ts +55 -0
  317. package/corpus/templates/slides/app/i18n/es-ES.ts +55 -0
  318. package/corpus/templates/slides/app/i18n/fr-FR.ts +55 -0
  319. package/corpus/templates/slides/app/i18n/hi-IN.ts +55 -0
  320. package/corpus/templates/slides/app/i18n/index.ts +31 -0
  321. package/corpus/templates/slides/app/i18n/ja-JP.ts +55 -0
  322. package/corpus/templates/slides/app/i18n/ko-KR.ts +55 -0
  323. package/corpus/templates/slides/app/i18n/pt-BR.ts +55 -0
  324. package/corpus/templates/slides/app/i18n/zh-CN.ts +53 -0
  325. package/corpus/templates/slides/app/root.tsx +50 -8
  326. package/corpus/templates/slides/app/routes/settings.tsx +85 -0
  327. package/corpus/templates/slides/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  328. package/corpus/templates/slides/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  329. package/corpus/templates/videos/.agents/skills/self-modifying-code/SKILL.md +6 -0
  330. package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +14 -9
  331. package/corpus/templates/videos/app/components/Sidebar.tsx +16 -9
  332. package/corpus/templates/videos/app/components/StudioHeader.tsx +12 -8
  333. package/corpus/templates/videos/app/components/layout/Header.tsx +21 -15
  334. package/corpus/templates/videos/app/components/layout/Layout.tsx +10 -7
  335. package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +21 -6
  336. package/corpus/templates/videos/app/i18n/ar-SA.ts +73 -0
  337. package/corpus/templates/videos/app/i18n/de-DE.ts +75 -0
  338. package/corpus/templates/videos/app/i18n/en-US.ts +74 -0
  339. package/corpus/templates/videos/app/i18n/es-ES.ts +75 -0
  340. package/corpus/templates/videos/app/i18n/fr-FR.ts +75 -0
  341. package/corpus/templates/videos/app/i18n/hi-IN.ts +74 -0
  342. package/corpus/templates/videos/app/i18n/index.ts +31 -0
  343. package/corpus/templates/videos/app/i18n/ja-JP.ts +74 -0
  344. package/corpus/templates/videos/app/i18n/ko-KR.ts +74 -0
  345. package/corpus/templates/videos/app/i18n/pt-BR.ts +75 -0
  346. package/corpus/templates/videos/app/i18n/zh-CN.ts +72 -0
  347. package/corpus/templates/videos/app/pages/Index.tsx +11 -9
  348. package/corpus/templates/videos/app/root.tsx +45 -7
  349. package/corpus/templates/videos/app/routes/settings.tsx +85 -0
  350. package/corpus/templates/videos/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  351. package/corpus/templates/videos/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  352. package/dist/agent/durable-background.d.ts +15 -0
  353. package/dist/agent/durable-background.d.ts.map +1 -1
  354. package/dist/agent/durable-background.js +28 -2
  355. package/dist/agent/durable-background.js.map +1 -1
  356. package/dist/agent/production-agent.d.ts.map +1 -1
  357. package/dist/agent/production-agent.js +34 -1
  358. package/dist/agent/production-agent.js.map +1 -1
  359. package/dist/agent/run-manager.d.ts +8 -0
  360. package/dist/agent/run-manager.d.ts.map +1 -1
  361. package/dist/agent/run-manager.js +18 -1
  362. package/dist/agent/run-manager.js.map +1 -1
  363. package/dist/agent/run-store.d.ts +99 -0
  364. package/dist/agent/run-store.d.ts.map +1 -1
  365. package/dist/agent/run-store.js +155 -4
  366. package/dist/agent/run-store.js.map +1 -1
  367. package/dist/client/CommandMenu.d.ts +3 -0
  368. package/dist/client/CommandMenu.d.ts.map +1 -1
  369. package/dist/client/CommandMenu.js +9 -0
  370. package/dist/client/CommandMenu.js.map +1 -1
  371. package/dist/client/app-providers.d.ts +8 -1
  372. package/dist/client/app-providers.d.ts.map +1 -1
  373. package/dist/client/app-providers.js +7 -5
  374. package/dist/client/app-providers.js.map +1 -1
  375. package/dist/client/i18n.d.ts +54 -0
  376. package/dist/client/i18n.d.ts.map +1 -0
  377. package/dist/client/i18n.js +354 -0
  378. package/dist/client/i18n.js.map +1 -0
  379. package/dist/client/index.d.ts +2 -1
  380. package/dist/client/index.d.ts.map +1 -1
  381. package/dist/client/index.js +2 -1
  382. package/dist/client/index.js.map +1 -1
  383. package/dist/index.browser.d.ts +1 -1
  384. package/dist/index.browser.d.ts.map +1 -1
  385. package/dist/index.browser.js +1 -1
  386. package/dist/index.browser.js.map +1 -1
  387. package/dist/localization/actions/get-localization-preference.d.ts +4 -0
  388. package/dist/localization/actions/get-localization-preference.d.ts.map +1 -0
  389. package/dist/localization/actions/get-localization-preference.js +16 -0
  390. package/dist/localization/actions/get-localization-preference.js.map +1 -0
  391. package/dist/localization/actions/set-localization-preference.d.ts +6 -0
  392. package/dist/localization/actions/set-localization-preference.d.ts.map +1 -0
  393. package/dist/localization/actions/set-localization-preference.js +24 -0
  394. package/dist/localization/actions/set-localization-preference.js.map +1 -0
  395. package/dist/localization/index.d.ts +3 -0
  396. package/dist/localization/index.d.ts.map +1 -0
  397. package/dist/localization/index.js +3 -0
  398. package/dist/localization/index.js.map +1 -0
  399. package/dist/localization/server.d.ts +25 -0
  400. package/dist/localization/server.d.ts.map +1 -0
  401. package/dist/localization/server.js +69 -0
  402. package/dist/localization/server.js.map +1 -0
  403. package/dist/localization/shared.d.ts +25 -0
  404. package/dist/localization/shared.d.ts.map +1 -0
  405. package/dist/localization/shared.js +134 -0
  406. package/dist/localization/shared.js.map +1 -0
  407. package/dist/server/action-discovery.d.ts.map +1 -1
  408. package/dist/server/action-discovery.js +8 -0
  409. package/dist/server/action-discovery.js.map +1 -1
  410. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  411. package/dist/server/agent-chat-plugin.js +58 -1
  412. package/dist/server/agent-chat-plugin.js.map +1 -1
  413. package/dist/server/auth.d.ts.map +1 -1
  414. package/dist/server/auth.js +12 -0
  415. package/dist/server/auth.js.map +1 -1
  416. package/dist/server/index.d.ts +1 -0
  417. package/dist/server/index.d.ts.map +1 -1
  418. package/dist/server/index.js +1 -0
  419. package/dist/server/index.js.map +1 -1
  420. package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  421. package/dist/templates/default/.agents/skills/internationalization/SKILL.md +77 -0
  422. package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +6 -0
  423. package/dist/templates/default/AGENTS.md +16 -15
  424. package/dist/templates/default/app/i18n/en-US.ts +29 -0
  425. package/dist/templates/default/app/i18n/index.ts +13 -0
  426. package/dist/templates/default/app/root.tsx +20 -1
  427. package/dist/templates/default/app/routes/_index.tsx +24 -9
  428. package/dist/templates/default/app/routes/settings.tsx +67 -0
  429. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  430. package/dist/templates/workspace-core/.agents/skills/internationalization/SKILL.md +77 -0
  431. package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +6 -0
  432. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  433. package/dist/vite/action-types-plugin.js +8 -0
  434. package/dist/vite/action-types-plugin.js.map +1 -1
  435. package/docs/AGENTS.md +1 -0
  436. package/docs/content/client.md +15 -0
  437. package/docs/content/internationalization.md +145 -0
  438. package/docs/content/locales/ar-SA/internationalization.md +102 -0
  439. package/docs/content/locales/de-DE/internationalization.md +102 -0
  440. package/docs/content/locales/es-ES/internationalization.md +102 -0
  441. package/docs/content/locales/fr-FR/internationalization.md +102 -0
  442. package/docs/content/locales/hi-IN/internationalization.md +102 -0
  443. package/docs/content/locales/ja-JP/internationalization.md +114 -0
  444. package/docs/content/locales/ko-KR/internationalization.md +102 -0
  445. package/docs/content/locales/pt-BR/internationalization.md +102 -0
  446. package/docs/content/locales/zh-CN/internationalization.md +102 -0
  447. package/docs/content/skills-guide.md +19 -18
  448. package/package.json +7 -1
  449. package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  450. package/src/templates/default/.agents/skills/internationalization/SKILL.md +77 -0
  451. package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +6 -0
  452. package/src/templates/default/AGENTS.md +16 -15
  453. package/src/templates/default/app/i18n/en-US.ts +29 -0
  454. package/src/templates/default/app/i18n/index.ts +13 -0
  455. package/src/templates/default/app/root.tsx +20 -1
  456. package/src/templates/default/app/routes/_index.tsx +24 -9
  457. package/src/templates/default/app/routes/settings.tsx +67 -0
  458. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  459. package/src/templates/workspace-core/.agents/skills/internationalization/SKILL.md +77 -0
  460. package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +6 -0
@@ -10,8 +10,10 @@ import {
10
10
  appPath,
11
11
  configureTracking,
12
12
  createAgentNativeQueryClient,
13
+ getLocaleInitScript,
13
14
  getThemeInitScript,
14
15
  useCommandMenuShortcut,
16
+ useT,
15
17
  } from "@agent-native/core/client";
16
18
  import { IconSun, IconMoon } from "@tabler/icons-react";
17
19
  import changelog from "../CHANGELOG.md?raw";
@@ -20,6 +22,7 @@ import { TAB_ID } from "@/lib/tab-id";
20
22
  import { APP_TITLE } from "@/lib/app-config";
21
23
  import type { LinksFunction } from "react-router";
22
24
  import stylesheet from "./global.css?url";
25
+ import { i18nCatalog } from "./i18n";
23
26
 
24
27
  configureTracking({
25
28
  getDefaultProps: (_name, properties) => ({
@@ -33,6 +36,7 @@ export const links: LinksFunction = () => [
33
36
  ];
34
37
 
35
38
  const THEME_INIT_SCRIPT = getThemeInitScript();
39
+ const LOCALE_INIT_SCRIPT = getLocaleInitScript();
36
40
 
37
41
  export function Layout({ children }: { children: React.ReactNode }) {
38
42
  return (
@@ -47,6 +51,11 @@ export function Layout({ children }: { children: React.ReactNode }) {
47
51
  suppressHydrationWarning
48
52
  dangerouslySetInnerHTML={{ __html: THEME_INIT_SCRIPT }}
49
53
  />
54
+ <script
55
+ data-agent-native-locale-init
56
+ suppressHydrationWarning
57
+ dangerouslySetInnerHTML={{ __html: LOCALE_INIT_SCRIPT }}
58
+ />
50
59
  <link rel="manifest" href={appPath("/manifest.json")} />
51
60
  <meta name="theme-color" content="#18181B" />
52
61
  <meta name="mobile-web-app-capable" content="yes" />
@@ -81,6 +90,7 @@ function DbSyncSetup() {
81
90
 
82
91
  function ThemeToggleItem() {
83
92
  const { resolvedTheme, setTheme } = useTheme();
93
+ const t = useT();
84
94
  const isDark = resolvedTheme === "dark";
85
95
  return (
86
96
  <CommandMenu.Item
@@ -88,13 +98,14 @@ function ThemeToggleItem() {
88
98
  keywords={["theme", "dark", "light", "mode"]}
89
99
  >
90
100
  {isDark ? <IconSun size={16} /> : <IconMoon size={16} />}
91
- Toggle {isDark ? "light" : "dark"} mode
101
+ {t("root.toggleTheme")}
92
102
  </CommandMenu.Item>
93
103
  );
94
104
  }
95
105
 
96
106
  function AppContent() {
97
107
  const [cmdkOpen, setCmdkOpen] = useState(false);
108
+ const t = useT();
98
109
  useCommandMenuShortcut(useCallback(() => setCmdkOpen(true), []));
99
110
  return (
100
111
  <>
@@ -104,10 +115,12 @@ function AppContent() {
104
115
  changelog={changelog}
105
116
  changelogKey="chat"
106
117
  >
107
- <CommandMenu.Group heading="Actions">
108
- <CommandMenu.Item onSelect={() => {}}>Search</CommandMenu.Item>
118
+ <CommandMenu.Group heading={t("root.commandActions")}>
119
+ <CommandMenu.Item onSelect={() => {}}>
120
+ {t("root.commandSearch")}
121
+ </CommandMenu.Item>
109
122
  </CommandMenu.Group>
110
- <CommandMenu.Group heading="Appearance">
123
+ <CommandMenu.Group heading={t("root.commandAppearance")}>
111
124
  <ThemeToggleItem />
112
125
  </CommandMenu.Group>
113
126
  </CommandMenu>
@@ -121,7 +134,7 @@ function AppContent() {
121
134
  export default function Root() {
122
135
  const [queryClient] = useState(() => createAgentNativeQueryClient());
123
136
  return (
124
- <AppProviders queryClient={queryClient}>
137
+ <AppProviders queryClient={queryClient} i18n={{ catalog: i18nCatalog }}>
125
138
  <DbSyncSetup />
126
139
  <AppContent />
127
140
  </AppProviders>
@@ -3,6 +3,7 @@ import { useNavigate, useParams } from "react-router";
3
3
  import {
4
4
  AgentChatSurface,
5
5
  markAgentChatHomeHandoff,
6
+ useT,
6
7
  } from "@agent-native/core/client";
7
8
  import { APP_TITLE } from "@/lib/app-config";
8
9
  import { TAB_ID } from "@/lib/tab-id";
@@ -33,6 +34,7 @@ function chatThreadPath(threadId: string | null) {
33
34
  export default function ChatRoute() {
34
35
  const { threadId } = useParams();
35
36
  const navigate = useNavigate();
37
+ const t = useT();
36
38
 
37
39
  useEffect(() => {
38
40
  function handleChatRunning(event: Event) {
@@ -63,23 +65,22 @@ export default function ChatRoute() {
63
65
  showTabBar={false}
64
66
  dynamicSuggestions={false}
65
67
  suggestions={[
66
- "What can you do?",
67
- "Help me customize this chat app",
68
- "Show me the actions and pages I can add",
68
+ t("chat.suggestionCapabilities"),
69
+ t("chat.suggestionCustomize"),
70
+ t("chat.suggestionActions"),
69
71
  ]}
70
- emptyStateText="Ask anything, then customize the app when you need more."
72
+ emptyStateText={t("chat.emptyState")}
71
73
  emptyStateDisplay="hidden"
72
74
  centerComposerWhenEmpty
73
75
  composerLayoutVariant="hero"
74
- composerPlaceholder="Message the agent..."
76
+ composerPlaceholder={t("chat.composerPlaceholder")}
75
77
  composerSlot={
76
78
  <div className="mx-auto mb-5 max-w-xl px-4 text-center">
77
79
  <h1 className="text-2xl font-semibold tracking-normal text-foreground sm:text-3xl">
78
- How can I help?
80
+ {t("chat.heroTitle")}
79
81
  </h1>
80
82
  <p className="mt-2 text-sm leading-6 text-muted-foreground">
81
- Chat about anything. Add actions, components, pages, jobs, or your
82
- own agent backend when you want this app to do more.
83
+ {t("chat.heroDescription")}
83
84
  </p>
84
85
  </div>
85
86
  }
@@ -0,0 +1,86 @@
1
+ import { Link } from "react-router";
2
+ import {
3
+ ChangelogSettingsCard,
4
+ LanguagePicker,
5
+ openAgentSettings,
6
+ useT,
7
+ } from "@agent-native/core/client";
8
+ import { useSetPageTitle } from "@/components/layout/HeaderActions";
9
+ import { Button } from "@/components/ui/button";
10
+ import {
11
+ Card,
12
+ CardContent,
13
+ CardDescription,
14
+ CardHeader,
15
+ CardTitle,
16
+ } from "@/components/ui/card";
17
+ import { Label } from "@/components/ui/label";
18
+ import { APP_TITLE } from "@/lib/app-config";
19
+ import changelog from "../../CHANGELOG.md?raw";
20
+
21
+ export function meta() {
22
+ return [{ title: `Settings - ${APP_TITLE}` }];
23
+ }
24
+
25
+ export default function SettingsRoute() {
26
+ const t = useT();
27
+ useSetPageTitle(t("settings.title"));
28
+
29
+ return (
30
+ <main className="mx-auto w-full max-w-3xl space-y-6 px-4 py-6 sm:px-6 sm:py-10">
31
+ <div className="space-y-1">
32
+ <h1 className="text-2xl font-semibold tracking-tight">
33
+ {t("settings.title")}
34
+ </h1>
35
+ <p className="text-sm leading-6 text-muted-foreground">
36
+ {t("settings.description")}
37
+ </p>
38
+ </div>
39
+
40
+ <Card>
41
+ <CardHeader>
42
+ <CardTitle className="text-base">
43
+ {t("settings.languageTitle")}
44
+ </CardTitle>
45
+ <CardDescription>{t("settings.languageDescription")}</CardDescription>
46
+ </CardHeader>
47
+ <CardContent className="max-w-xs space-y-1.5">
48
+ <Label>{t("settings.languageLabel")}</Label>
49
+ <LanguagePicker label={t("settings.languageLabel")} />
50
+ </CardContent>
51
+ </Card>
52
+
53
+ <Card>
54
+ <CardHeader>
55
+ <CardTitle className="text-base">
56
+ {t("settings.workspaceTitle")}
57
+ </CardTitle>
58
+ <CardDescription>
59
+ {t("settings.workspaceDescription")}
60
+ </CardDescription>
61
+ </CardHeader>
62
+ <CardContent>
63
+ <Button variant="outline" asChild>
64
+ <Link to="/team">{t("settings.openTeamSettings")}</Link>
65
+ </Button>
66
+ </CardContent>
67
+ </Card>
68
+
69
+ <Card>
70
+ <CardHeader>
71
+ <CardTitle className="text-base">
72
+ {t("settings.agentTitle")}
73
+ </CardTitle>
74
+ <CardDescription>{t("settings.agentDescription")}</CardDescription>
75
+ </CardHeader>
76
+ <CardContent>
77
+ <Button variant="outline" onClick={() => openAgentSettings()}>
78
+ {t("settings.openAgentSettings")}
79
+ </Button>
80
+ </CardContent>
81
+ </Card>
82
+
83
+ <ChangelogSettingsCard markdown={changelog} />
84
+ </main>
85
+ );
86
+ }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-06-24
4
+ ---
5
+
6
+ A new Settings page gives quick access to language, workspace, and agent preferences.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-06-24
4
+ ---
5
+
6
+ Added a language picker and localized app chrome for supported languages.
@@ -66,6 +66,11 @@ el.dataset.selectedId = selectedItem?.id || "";
66
66
 
67
67
  **Use configuration-driven rendering** — Extract visual decisions (colors, layouts, sizes) into JSON config files in `data/`. The agent can modify the config (Tier 1) instead of the component source (Tier 2).
68
68
 
69
+ **Keep localized copy in catalogs** — When editing visible UI copy, labels,
70
+ toasts, empty states, prompts, or formatting, read `internationalization` and
71
+ update `app/i18n/en-US.ts` plus existing locale catalogs instead of leaving new
72
+ inline strings in components.
73
+
69
74
  ## Don't
70
75
 
71
76
  - Don't modify `.env` files or files containing secrets
@@ -80,3 +85,4 @@ el.dataset.selectedId = selectedItem?.id || "";
80
85
  - **actions** — The agent can create or modify actions to add new capabilities
81
86
  - **delegate-to-agent** — Self-modification requests come through the agent chat
82
87
  - **real-time-sync** — Database writes trigger change events to update the UI
88
+ - **internationalization** — UI copy, language catalogs, locale switching, and RTL-safe edits
@@ -1,30 +1,35 @@
1
1
  import { useLocation } from "react-router";
2
2
  import { useHeaderTitle, useHeaderActions } from "./HeaderActions";
3
- import { AgentToggleButton } from "@agent-native/core/client";
3
+ import {
4
+ AgentToggleButton,
5
+ LanguagePicker,
6
+ useT,
7
+ } from "@agent-native/core/client";
4
8
 
5
- const pageTitles: Record<string, string> = {
6
- "/": "Library",
7
- "/library": "Library",
8
- "/spaces": "Spaces",
9
- "/archive": "Archive",
10
- "/trash": "Trash",
11
- "/notifications": "Notifications",
12
- "/insights": "Insights",
9
+ const pageTitleKeys: Record<string, string> = {
10
+ "/": "navigation.library",
11
+ "/library": "navigation.library",
12
+ "/spaces": "navigation.spaces",
13
+ "/archive": "navigation.archive",
14
+ "/trash": "navigation.trash",
15
+ "/notifications": "navigation.notifications",
16
+ "/insights": "navigation.insights",
13
17
  };
14
18
 
15
- function resolveTitle(pathname: string): string {
16
- if (pageTitles[pathname]) return pageTitles[pathname];
19
+ function resolveTitle(pathname: string, t: ReturnType<typeof useT>): string {
20
+ if (pageTitleKeys[pathname]) return t(pageTitleKeys[pathname]);
17
21
 
18
- if (pathname.startsWith("/spaces/")) return "Space";
19
- if (pathname.startsWith("/library/folder/")) return "Folder";
20
- if (pathname.startsWith("/settings")) return "Settings";
21
- if (pathname.startsWith("/extensions")) return "Extensions";
22
+ if (pathname.startsWith("/spaces/")) return t("navigation.space");
23
+ if (pathname.startsWith("/library/folder/")) return t("navigation.folder");
24
+ if (pathname.startsWith("/settings")) return t("navigation.settings");
25
+ if (pathname.startsWith("/extensions")) return t("navigation.extensions");
22
26
 
23
- return "Clips";
27
+ return t("navigation.brand");
24
28
  }
25
29
 
26
30
  export function Header() {
27
31
  const location = useLocation();
32
+ const t = useT();
28
33
  const title = useHeaderTitle();
29
34
  const actions = useHeaderActions();
30
35
 
@@ -33,12 +38,13 @@ export function Header() {
33
38
  <div className="flex items-center gap-3 flex-1 min-w-0">
34
39
  {title ?? (
35
40
  <h1 className="text-lg font-semibold tracking-tight truncate">
36
- {resolveTitle(location.pathname)}
41
+ {resolveTitle(location.pathname, t)}
37
42
  </h1>
38
43
  )}
39
44
  </div>
40
45
  <div className="flex items-center gap-2 shrink-0">
41
46
  {actions}
47
+ <LanguagePicker variant="icon" />
42
48
  <AgentToggleButton />
43
49
  </div>
44
50
  </header>
@@ -8,6 +8,7 @@ import {
8
8
  IconPlayerRecord,
9
9
  } from "@tabler/icons-react";
10
10
  import { Button } from "@/components/ui/button";
11
+ import { useT } from "@agent-native/core/client";
11
12
 
12
13
  type EmptyKind =
13
14
  | "library"
@@ -26,35 +27,7 @@ const ICONS: Record<EmptyKind, React.ComponentType<{ className?: string }>> = {
26
27
  search: IconVideo,
27
28
  };
28
29
 
29
- const COPY: Record<EmptyKind, { title: string; body: string; cta?: string }> = {
30
- library: {
31
- title: "Your library is empty",
32
- body: "Capture your first screen recording and it'll land here, ready to share.",
33
- cta: "Record your first Clip",
34
- },
35
- folder: {
36
- title: "This folder is empty",
37
- body: "Drag recordings in, or hit record to start something new in this folder.",
38
- cta: "Record here",
39
- },
40
- space: {
41
- title: "No recordings in this space yet",
42
- body: "Share a recording with the space or record something new — your team will see it here.",
43
- cta: "Record for this space",
44
- },
45
- archive: {
46
- title: "Nothing archived",
47
- body: "Archived recordings are hidden from the library but kept safe. You can always restore them later.",
48
- },
49
- trash: {
50
- title: "Trash is empty",
51
- body: "Deleted recordings appear here for 30 days before being permanently removed.",
52
- },
53
- search: {
54
- title: "No matches",
55
- body: "Try a different search term or check your filters.",
56
- },
57
- };
30
+ const CTA_KINDS = new Set<EmptyKind>(["library", "folder", "space"]);
58
31
 
59
32
  interface EmptyStateProps {
60
33
  kind: EmptyKind;
@@ -70,8 +43,9 @@ export function EmptyState({
70
43
  onCtaClick,
71
44
  }: EmptyStateProps) {
72
45
  const navigate = useNavigate();
46
+ const t = useT();
73
47
  const Icon = ICONS[kind];
74
- const copy = COPY[kind];
48
+ const hasCta = CTA_KINDS.has(kind);
75
49
 
76
50
  const handleCta = () => {
77
51
  if (onCtaClick) {
@@ -91,17 +65,19 @@ export function EmptyState({
91
65
  <Icon className="h-10 w-10 text-primary" />
92
66
  </div>
93
67
  <h2 className="text-base font-semibold text-foreground mb-1">
94
- {copy.title}
68
+ {t(`empty.${kind}.title`)}
95
69
  </h2>
96
- <p className="text-sm text-muted-foreground max-w-sm mb-5">{copy.body}</p>
97
- {copy.cta && (
70
+ <p className="text-sm text-muted-foreground max-w-sm mb-5">
71
+ {t(`empty.${kind}.body`)}
72
+ </p>
73
+ {hasCta && (
98
74
  <Button
99
75
  onClick={handleCta}
100
76
  className="bg-primary text-primary-foreground hover:bg-primary/90 gap-1.5"
101
77
  size="sm"
102
78
  >
103
79
  <IconPlayerRecord className="h-4 w-4" />
104
- {copy.cta}
80
+ {t(`empty.${kind}.cta`)}
105
81
  </Button>
106
82
  )}
107
83
  </div>
@@ -24,6 +24,7 @@ import {
24
24
  FeedbackButton,
25
25
  appPath,
26
26
  getBrowserTabId,
27
+ useT,
27
28
  } from "@agent-native/core/client";
28
29
  import {
29
30
  InvitationBanner,
@@ -91,6 +92,7 @@ function ClipsAgentToggleButton() {
91
92
 
92
93
  export function LibraryLayout({ children }: LibraryLayoutProps) {
93
94
  const location = useLocation();
95
+ const t = useT();
94
96
  // Bind chat to the currently-open recording (`/r/:id`). Library, spaces,
95
97
  // meetings, dictate, and settings stay unscoped — those are list-y views
96
98
  // where deck-style "this recording" framing doesn't apply.
@@ -185,44 +187,44 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
185
187
  }[] = [
186
188
  {
187
189
  to: "/library",
188
- label: "Library",
190
+ label: t("navigation.library"),
189
191
  icon: IconInbox,
190
192
  match: (p) => p.startsWith("/library"),
191
193
  count: libraryCount,
192
194
  },
193
195
  {
194
196
  to: "/spaces",
195
- label: "Spaces",
197
+ label: t("navigation.spaces"),
196
198
  icon: IconUsersGroup,
197
199
  match: (p) => p.startsWith("/spaces"),
198
200
  },
199
201
  {
200
202
  to: "/meetings",
201
- label: "Meetings",
203
+ label: t("navigation.meetings"),
202
204
  icon: IconCalendar,
203
205
  match: (p) => p.startsWith("/meetings"),
204
206
  },
205
207
  {
206
208
  to: "/dictate",
207
- label: "Dictate",
209
+ label: t("navigation.dictate"),
208
210
  icon: IconMicrophone2,
209
211
  match: (p) => p.startsWith("/dictate"),
210
212
  },
211
213
  {
212
214
  to: "/archive",
213
- label: "Archive",
215
+ label: t("navigation.archive"),
214
216
  icon: IconArchive,
215
217
  match: (p) => p.startsWith("/archive"),
216
218
  },
217
219
  {
218
220
  to: "/trash",
219
- label: "Trash",
221
+ label: t("navigation.trash"),
220
222
  icon: IconTrash,
221
223
  match: (p) => p.startsWith("/trash"),
222
224
  },
223
225
  {
224
226
  to: "/settings",
225
- label: "Settings",
227
+ label: t("navigation.settings"),
226
228
  icon: IconSettings,
227
229
  match: (p) => p.startsWith("/settings"),
228
230
  },
@@ -233,11 +235,11 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
233
235
  <AgentSidebar
234
236
  position="right"
235
237
  defaultOpen={!isMobile}
236
- emptyStateText="How can I help with your recordings?"
238
+ emptyStateText={t("navigation.agentEmptyState")}
237
239
  suggestions={[
238
- "Summarize my last recording",
239
- "Find where I mentioned pricing",
240
- "Remove filler words from this clip",
240
+ t("navigation.agentSuggestionSummary"),
241
+ t("navigation.agentSuggestionPricing"),
242
+ t("navigation.agentSuggestionFiller"),
241
243
  ]}
242
244
  scope={recordingScope}
243
245
  browserTabId={getBrowserTabId()}
@@ -288,7 +290,7 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
288
290
  className="hidden h-4 w-auto shrink-0 dark:block"
289
291
  />
290
292
  <span className="truncate text-sm font-semibold text-foreground">
291
- Clips
293
+ {t("navigation.brand")}
292
294
  </span>
293
295
  </>
294
296
  )}
@@ -303,8 +305,8 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
303
305
  className="hidden h-7 w-7 shrink-0 text-muted-foreground hover:text-foreground md:inline-flex"
304
306
  aria-label={
305
307
  showCollapsedSidebar
306
- ? "Expand sidebar"
307
- : "Collapse sidebar"
308
+ ? t("navigation.expandSidebar")
309
+ : t("navigation.collapseSidebar")
308
310
  }
309
311
  aria-expanded={!showCollapsedSidebar}
310
312
  onClick={() => setSidebarCollapsed((value) => !value)}
@@ -317,7 +319,9 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
317
319
  </Button>
318
320
  </TooltipTrigger>
319
321
  <TooltipContent side="right">
320
- {showCollapsedSidebar ? "Expand sidebar" : "Collapse sidebar"}
322
+ {showCollapsedSidebar
323
+ ? t("navigation.expandSidebar")
324
+ : t("navigation.collapseSidebar")}
321
325
  </TooltipContent>
322
326
  </Tooltip>
323
327
  </div>
@@ -329,14 +333,14 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
329
333
  <TooltipTrigger asChild>
330
334
  <NavLink
331
335
  to="/record"
332
- aria-label="New recording"
336
+ aria-label={t("navigation.newRecording")}
333
337
  className="flex h-9 w-9 items-center justify-center rounded-md bg-primary text-primary-foreground shadow-sm hover:bg-primary/90"
334
338
  >
335
339
  <IconPlayerRecord className="h-4 w-4" />
336
340
  </NavLink>
337
341
  </TooltipTrigger>
338
342
  <TooltipContent side="right">
339
- New recording
343
+ {t("navigation.newRecording")}
340
344
  </TooltipContent>
341
345
  </Tooltip>
342
346
  </div>
@@ -375,7 +379,7 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
375
379
  >
376
380
  <NavLink to="/record">
377
381
  <IconPlayerRecord className="h-4 w-4" />
378
- New recording
382
+ {t("navigation.newRecording")}
379
383
  </NavLink>
380
384
  </Button>
381
385
  </div>
@@ -417,20 +421,22 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
417
421
  <div>
418
422
  <div className="flex items-center justify-between px-2 pb-1">
419
423
  <span className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
420
- Folders
424
+ {t("navigation.folders")}
421
425
  </span>
422
426
  <Tooltip>
423
427
  <TooltipTrigger asChild>
424
428
  <button
425
429
  type="button"
426
- aria-label="New folder"
430
+ aria-label={t("navigation.newFolder")}
427
431
  className="rounded p-1 text-muted-foreground hover:bg-accent"
428
432
  onClick={() => setNewFolderOpen(true)}
429
433
  >
430
434
  <IconFolderPlus className="h-3.5 w-3.5" />
431
435
  </button>
432
436
  </TooltipTrigger>
433
- <TooltipContent>New folder</TooltipContent>
437
+ <TooltipContent>
438
+ {t("navigation.newFolder")}
439
+ </TooltipContent>
434
440
  </Tooltip>
435
441
  </div>
436
442
  <FolderTree
@@ -445,20 +451,22 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
445
451
  <div>
446
452
  <div className="flex items-center justify-between px-2 pb-1">
447
453
  <span className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
448
- Spaces
454
+ {t("navigation.spaces")}
449
455
  </span>
450
456
  <Tooltip>
451
457
  <TooltipTrigger asChild>
452
458
  <button
453
459
  type="button"
454
- aria-label="New space"
460
+ aria-label={t("navigation.spaces")}
455
461
  className="rounded p-1 text-muted-foreground hover:bg-accent"
456
462
  onClick={() => setNewSpaceOpen(true)}
457
463
  >
458
464
  <IconPlus className="h-3.5 w-3.5" />
459
465
  </button>
460
466
  </TooltipTrigger>
461
- <TooltipContent>New space</TooltipContent>
467
+ <TooltipContent>
468
+ {t("navigation.spaces")}
469
+ </TooltipContent>
462
470
  </Tooltip>
463
471
  </div>
464
472
  <ul className="space-y-0.5">
@@ -493,7 +501,7 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
493
501
  })}
494
502
  {(spaces?.spaces ?? []).length === 0 && (
495
503
  <li className="px-2 py-1 text-[11px] text-muted-foreground/70">
496
- No spaces yet
504
+ {t("navigation.noSpaces")}
497
505
  </li>
498
506
  )}
499
507
  </ul>
@@ -509,7 +517,7 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
509
517
  {shouldShowSidebarLink && (
510
518
  <CaptureInstallInlineLink className="flex items-center gap-2 rounded px-2 py-1.5 text-xs text-foreground hover:bg-accent/60">
511
519
  <IconAppWindow className="h-4 w-4" />
512
- Get desktop app
520
+ {t("navigation.desktopCta")}
513
521
  </CaptureInstallInlineLink>
514
522
  )}
515
523
  <SearchBar />
@@ -553,10 +561,10 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
553
561
  <IconAppWindow className="h-4 w-4 shrink-0 text-primary" />
554
562
  <div className="min-w-0 flex-1">
555
563
  <span className="font-medium">
556
- Get the Clips desktop app.
564
+ {t("navigation.desktopTitle")}
557
565
  </span>{" "}
558
566
  <span className="text-muted-foreground">
559
- Record from the menu bar, global shortcut, auto-updates.
567
+ {t("navigation.desktopBody")}
560
568
  </span>
561
569
  </div>
562
570
  <CaptureInstallButton size="sm" className="shrink-0">
@@ -590,17 +598,17 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
590
598
  <AlertDialog open={newFolderOpen} onOpenChange={setNewFolderOpen}>
591
599
  <AlertDialogContent>
592
600
  <AlertDialogHeader>
593
- <AlertDialogTitle>New folder</AlertDialogTitle>
601
+ <AlertDialogTitle>{t("navigation.newFolder")}</AlertDialogTitle>
594
602
  </AlertDialogHeader>
595
603
  <input
596
604
  autoFocus
597
605
  value={newFolderName}
598
606
  onChange={(e) => setNewFolderName(e.target.value)}
599
- placeholder="Folder name"
607
+ placeholder={t("navigation.folderNamePlaceholder")}
600
608
  className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30"
601
609
  />
602
610
  <AlertDialogFooter>
603
- <AlertDialogCancel>Cancel</AlertDialogCancel>
611
+ <AlertDialogCancel>{t("common.cancel")}</AlertDialogCancel>
604
612
  <AlertDialogAction
605
613
  onClick={() => {
606
614
  const name = newFolderName.trim();
@@ -614,16 +622,19 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
614
622
  parentId: null,
615
623
  },
616
624
  {
617
- onSuccess: () => toast.success("Folder created"),
625
+ onSuccess: () =>
626
+ toast.success(t("navigation.folderCreated")),
618
627
  onError: (err: any) =>
619
- toast.error(err?.message ?? "Create failed"),
628
+ toast.error(
629
+ err?.message ?? t("navigation.createFolderError"),
630
+ ),
620
631
  },
621
632
  );
622
633
  setNewFolderName("");
623
634
  setNewFolderOpen(false);
624
635
  }}
625
636
  >
626
- Create
637
+ {t("common.create")}
627
638
  </AlertDialogAction>
628
639
  </AlertDialogFooter>
629
640
  </AlertDialogContent>