@agent-native/core 0.75.5 → 0.76.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 (427) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +7 -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/client/CommandMenu.tsx +16 -0
  18. package/corpus/core/src/client/app-providers.tsx +26 -1
  19. package/corpus/core/src/client/i18n.tsx +605 -0
  20. package/corpus/core/src/client/index.ts +28 -0
  21. package/corpus/core/src/index.browser.ts +25 -0
  22. package/corpus/core/src/localization/actions/get-localization-preference.ts +23 -0
  23. package/corpus/core/src/localization/actions/set-localization-preference.ts +30 -0
  24. package/corpus/core/src/localization/index.ts +2 -0
  25. package/corpus/core/src/localization/server.ts +131 -0
  26. package/corpus/core/src/localization/shared.ts +163 -0
  27. package/corpus/core/src/server/action-discovery.ts +8 -0
  28. package/corpus/core/src/server/index.ts +8 -0
  29. package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  30. package/corpus/core/src/templates/default/.agents/skills/internationalization/SKILL.md +77 -0
  31. package/corpus/core/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +6 -0
  32. package/corpus/core/src/templates/default/AGENTS.md +16 -15
  33. package/corpus/core/src/templates/default/app/i18n/en-US.ts +29 -0
  34. package/corpus/core/src/templates/default/app/i18n/index.ts +13 -0
  35. package/corpus/core/src/templates/default/app/root.tsx +20 -1
  36. package/corpus/core/src/templates/default/app/routes/_index.tsx +24 -9
  37. package/corpus/core/src/templates/default/app/routes/settings.tsx +67 -0
  38. package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  39. package/corpus/core/src/templates/workspace-core/.agents/skills/internationalization/SKILL.md +77 -0
  40. package/corpus/core/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +6 -0
  41. package/corpus/core/src/vite/action-types-plugin.ts +10 -0
  42. package/corpus/templates/analytics/.agents/skills/self-modifying-code/SKILL.md +6 -0
  43. package/corpus/templates/analytics/app/components/layout/Header.tsx +18 -15
  44. package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -5
  45. package/corpus/templates/analytics/app/components/layout/MobileNav.tsx +9 -3
  46. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +5 -3
  47. package/corpus/templates/analytics/app/i18n/ar-SA.ts +3 -0
  48. package/corpus/templates/analytics/app/i18n/de-DE.ts +3 -0
  49. package/corpus/templates/analytics/app/i18n/en-US.ts +3 -0
  50. package/corpus/templates/analytics/app/i18n/es-ES.ts +3 -0
  51. package/corpus/templates/analytics/app/i18n/fr-FR.ts +3 -0
  52. package/corpus/templates/analytics/app/i18n/hi-IN.ts +3 -0
  53. package/corpus/templates/analytics/app/i18n/index.ts +31 -0
  54. package/corpus/templates/analytics/app/i18n/ja-JP.ts +3 -0
  55. package/corpus/templates/analytics/app/i18n/ko-KR.ts +3 -0
  56. package/corpus/templates/analytics/app/i18n/pt-BR.ts +3 -0
  57. package/corpus/templates/analytics/app/i18n/zh-CN.ts +3 -0
  58. package/corpus/templates/analytics/app/i18n-data.ts +433 -0
  59. package/corpus/templates/analytics/app/pages/Settings.tsx +50 -16
  60. package/corpus/templates/analytics/app/root.tsx +14 -1
  61. package/corpus/templates/analytics/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  62. package/corpus/templates/analytics/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  63. package/corpus/templates/assets/.agents/skills/self-modifying-code/SKILL.md +6 -0
  64. package/corpus/templates/assets/app/components/layout/Header.tsx +17 -8
  65. package/corpus/templates/assets/app/components/layout/Layout.tsx +10 -6
  66. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +40 -23
  67. package/corpus/templates/assets/app/i18n/ar-SA.ts +3 -0
  68. package/corpus/templates/assets/app/i18n/de-DE.ts +3 -0
  69. package/corpus/templates/assets/app/i18n/en-US.ts +3 -0
  70. package/corpus/templates/assets/app/i18n/es-ES.ts +3 -0
  71. package/corpus/templates/assets/app/i18n/fr-FR.ts +3 -0
  72. package/corpus/templates/assets/app/i18n/hi-IN.ts +3 -0
  73. package/corpus/templates/assets/app/i18n/index.ts +31 -0
  74. package/corpus/templates/assets/app/i18n/ja-JP.ts +3 -0
  75. package/corpus/templates/assets/app/i18n/ko-KR.ts +3 -0
  76. package/corpus/templates/assets/app/i18n/pt-BR.ts +3 -0
  77. package/corpus/templates/assets/app/i18n/zh-CN.ts +3 -0
  78. package/corpus/templates/assets/app/i18n-data.ts +668 -0
  79. package/corpus/templates/assets/app/root.tsx +40 -15
  80. package/corpus/templates/assets/app/routes/_index.tsx +9 -10
  81. package/corpus/templates/assets/app/routes/settings.tsx +37 -6
  82. package/corpus/templates/assets/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  83. package/corpus/templates/assets/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  84. package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +5 -0
  85. package/corpus/templates/brain/.agents/skills/self-modifying-code/SKILL.md +6 -0
  86. package/corpus/templates/brain/app/components/layout/Layout.tsx +12 -8
  87. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +23 -12
  88. package/corpus/templates/brain/app/i18n/ar-SA.ts +3 -0
  89. package/corpus/templates/brain/app/i18n/de-DE.ts +3 -0
  90. package/corpus/templates/brain/app/i18n/en-US.ts +3 -0
  91. package/corpus/templates/brain/app/i18n/es-ES.ts +3 -0
  92. package/corpus/templates/brain/app/i18n/fr-FR.ts +3 -0
  93. package/corpus/templates/brain/app/i18n/hi-IN.ts +3 -0
  94. package/corpus/templates/brain/app/i18n/index.ts +31 -0
  95. package/corpus/templates/brain/app/i18n/ja-JP.ts +3 -0
  96. package/corpus/templates/brain/app/i18n/ko-KR.ts +3 -0
  97. package/corpus/templates/brain/app/i18n/pt-BR.ts +3 -0
  98. package/corpus/templates/brain/app/i18n/zh-CN.ts +3 -0
  99. package/corpus/templates/brain/app/i18n-data.ts +624 -0
  100. package/corpus/templates/brain/app/root.tsx +27 -12
  101. package/corpus/templates/brain/app/routes/settings.tsx +45 -8
  102. package/corpus/templates/brain/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  103. package/corpus/templates/brain/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  104. package/corpus/templates/calendar/.agents/skills/self-modifying-code/SKILL.md +6 -0
  105. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +2 -0
  106. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +16 -9
  107. package/corpus/templates/calendar/app/i18n/ar-SA.ts +57 -0
  108. package/corpus/templates/calendar/app/i18n/de-DE.ts +58 -0
  109. package/corpus/templates/calendar/app/i18n/en-US.ts +57 -0
  110. package/corpus/templates/calendar/app/i18n/es-ES.ts +58 -0
  111. package/corpus/templates/calendar/app/i18n/fr-FR.ts +58 -0
  112. package/corpus/templates/calendar/app/i18n/hi-IN.ts +57 -0
  113. package/corpus/templates/calendar/app/i18n/index.ts +31 -0
  114. package/corpus/templates/calendar/app/i18n/ja-JP.ts +58 -0
  115. package/corpus/templates/calendar/app/i18n/ko-KR.ts +57 -0
  116. package/corpus/templates/calendar/app/i18n/pt-BR.ts +57 -0
  117. package/corpus/templates/calendar/app/i18n/zh-CN.ts +57 -0
  118. package/corpus/templates/calendar/app/i18n-data.ts +516 -0
  119. package/corpus/templates/calendar/app/pages/CalendarView.tsx +2 -0
  120. package/corpus/templates/calendar/app/pages/Settings.tsx +63 -28
  121. package/corpus/templates/calendar/app/root.tsx +78 -7
  122. package/corpus/templates/calendar/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  123. package/corpus/templates/calendar/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  124. package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +5 -0
  125. package/corpus/templates/chat/.agents/skills/self-modifying-code/SKILL.md +6 -0
  126. package/corpus/templates/chat/app/components/layout/Header.tsx +17 -11
  127. package/corpus/templates/chat/app/components/layout/Layout.tsx +12 -8
  128. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +47 -18
  129. package/corpus/templates/chat/app/i18n/ar-SA.ts +62 -0
  130. package/corpus/templates/chat/app/i18n/de-DE.ts +63 -0
  131. package/corpus/templates/chat/app/i18n/en-US.ts +63 -0
  132. package/corpus/templates/chat/app/i18n/es-ES.ts +63 -0
  133. package/corpus/templates/chat/app/i18n/fr-FR.ts +63 -0
  134. package/corpus/templates/chat/app/i18n/hi-IN.ts +63 -0
  135. package/corpus/templates/chat/app/i18n/index.ts +31 -0
  136. package/corpus/templates/chat/app/i18n/ja-JP.ts +63 -0
  137. package/corpus/templates/chat/app/i18n/ko-KR.ts +63 -0
  138. package/corpus/templates/chat/app/i18n/pt-BR.ts +63 -0
  139. package/corpus/templates/chat/app/i18n/zh-CN.ts +61 -0
  140. package/corpus/templates/chat/app/i18n-data.ts +475 -0
  141. package/corpus/templates/chat/app/root.tsx +18 -5
  142. package/corpus/templates/chat/app/routes/_index.tsx +9 -8
  143. package/corpus/templates/chat/app/routes/settings.tsx +86 -0
  144. package/corpus/templates/chat/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  145. package/corpus/templates/chat/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  146. package/corpus/templates/clips/.agents/skills/self-modifying-code/SKILL.md +6 -0
  147. package/corpus/templates/clips/app/components/layout/Header.tsx +23 -17
  148. package/corpus/templates/clips/app/components/library/empty-state.tsx +10 -34
  149. package/corpus/templates/clips/app/components/library/library-layout.tsx +45 -34
  150. package/corpus/templates/clips/app/i18n/ar-SA.ts +182 -0
  151. package/corpus/templates/clips/app/i18n/de-DE.ts +184 -0
  152. package/corpus/templates/clips/app/i18n/en-US.ts +179 -0
  153. package/corpus/templates/clips/app/i18n/es-ES.ts +183 -0
  154. package/corpus/templates/clips/app/i18n/fr-FR.ts +184 -0
  155. package/corpus/templates/clips/app/i18n/hi-IN.ts +180 -0
  156. package/corpus/templates/clips/app/i18n/index.ts +41 -0
  157. package/corpus/templates/clips/app/i18n/ja-JP.ts +180 -0
  158. package/corpus/templates/clips/app/i18n/ko-KR.ts +178 -0
  159. package/corpus/templates/clips/app/i18n/pt-BR.ts +183 -0
  160. package/corpus/templates/clips/app/i18n/zh-CN.ts +173 -0
  161. package/corpus/templates/clips/app/root.tsx +104 -10
  162. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +154 -95
  163. package/corpus/templates/clips/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  164. package/corpus/templates/clips/changelog/2026-06-24-clips-now-includes-a-language-picker-and-simplified-chinese-ui.md +6 -0
  165. package/corpus/templates/clips/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  166. package/corpus/templates/content/.agents/skills/self-modifying-code/SKILL.md +6 -0
  167. package/corpus/templates/content/app/components/EmptyState.tsx +7 -5
  168. package/corpus/templates/content/app/components/ThemeToggle.tsx +4 -2
  169. package/corpus/templates/content/app/components/layout/Header.tsx +2 -0
  170. package/corpus/templates/content/app/components/layout/Layout.tsx +8 -7
  171. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +41 -1
  172. package/corpus/templates/content/app/i18n/ar-SA.ts +3 -0
  173. package/corpus/templates/content/app/i18n/de-DE.ts +3 -0
  174. package/corpus/templates/content/app/i18n/en-US.ts +3 -0
  175. package/corpus/templates/content/app/i18n/es-ES.ts +3 -0
  176. package/corpus/templates/content/app/i18n/fr-FR.ts +3 -0
  177. package/corpus/templates/content/app/i18n/hi-IN.ts +3 -0
  178. package/corpus/templates/content/app/i18n/index.ts +31 -0
  179. package/corpus/templates/content/app/i18n/ja-JP.ts +3 -0
  180. package/corpus/templates/content/app/i18n/ko-KR.ts +3 -0
  181. package/corpus/templates/content/app/i18n/pt-BR.ts +3 -0
  182. package/corpus/templates/content/app/i18n/zh-CN.ts +3 -0
  183. package/corpus/templates/content/app/i18n-data.ts +490 -0
  184. package/corpus/templates/content/app/root.tsx +110 -23
  185. package/corpus/templates/content/app/routes/_app.settings.tsx +84 -0
  186. package/corpus/templates/content/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  187. package/corpus/templates/content/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  188. package/corpus/templates/design/.agents/skills/self-modifying-code/SKILL.md +6 -0
  189. package/corpus/templates/design/app/components/layout/Header.tsx +16 -8
  190. package/corpus/templates/design/app/components/layout/Layout.tsx +8 -6
  191. package/corpus/templates/design/app/components/layout/Sidebar.tsx +25 -9
  192. package/corpus/templates/design/app/i18n/ar-SA.ts +3 -0
  193. package/corpus/templates/design/app/i18n/de-DE.ts +3 -0
  194. package/corpus/templates/design/app/i18n/en-US.ts +3 -0
  195. package/corpus/templates/design/app/i18n/es-ES.ts +3 -0
  196. package/corpus/templates/design/app/i18n/fr-FR.ts +3 -0
  197. package/corpus/templates/design/app/i18n/hi-IN.ts +3 -0
  198. package/corpus/templates/design/app/i18n/index.ts +31 -0
  199. package/corpus/templates/design/app/i18n/ja-JP.ts +3 -0
  200. package/corpus/templates/design/app/i18n/ko-KR.ts +3 -0
  201. package/corpus/templates/design/app/i18n/pt-BR.ts +3 -0
  202. package/corpus/templates/design/app/i18n/zh-CN.ts +3 -0
  203. package/corpus/templates/design/app/i18n-data.ts +350 -0
  204. package/corpus/templates/design/app/root.tsx +40 -15
  205. package/corpus/templates/design/app/routes/settings.tsx +43 -0
  206. package/corpus/templates/design/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  207. package/corpus/templates/design/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  208. package/corpus/templates/dispatch/.agents/skills/self-modifying-code/SKILL.md +6 -0
  209. package/corpus/templates/dispatch/app/i18n/ar-SA.ts +3 -0
  210. package/corpus/templates/dispatch/app/i18n/de-DE.ts +3 -0
  211. package/corpus/templates/dispatch/app/i18n/en-US.ts +3 -0
  212. package/corpus/templates/dispatch/app/i18n/es-ES.ts +3 -0
  213. package/corpus/templates/dispatch/app/i18n/fr-FR.ts +3 -0
  214. package/corpus/templates/dispatch/app/i18n/hi-IN.ts +3 -0
  215. package/corpus/templates/dispatch/app/i18n/index.ts +31 -0
  216. package/corpus/templates/dispatch/app/i18n/ja-JP.ts +3 -0
  217. package/corpus/templates/dispatch/app/i18n/ko-KR.ts +3 -0
  218. package/corpus/templates/dispatch/app/i18n/pt-BR.ts +3 -0
  219. package/corpus/templates/dispatch/app/i18n/zh-CN.ts +3 -0
  220. package/corpus/templates/dispatch/app/i18n-data.ts +267 -0
  221. package/corpus/templates/dispatch/app/root.tsx +18 -4
  222. package/corpus/templates/dispatch/app/routes/settings.tsx +86 -0
  223. package/corpus/templates/dispatch/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  224. package/corpus/templates/dispatch/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  225. package/corpus/templates/forms/.agents/skills/self-modifying-code/SKILL.md +6 -0
  226. package/corpus/templates/forms/app/components/layout/Header.tsx +16 -9
  227. package/corpus/templates/forms/app/components/layout/Layout.tsx +6 -4
  228. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +34 -17
  229. package/corpus/templates/forms/app/i18n/ar-SA.ts +58 -0
  230. package/corpus/templates/forms/app/i18n/de-DE.ts +59 -0
  231. package/corpus/templates/forms/app/i18n/en-US.ts +59 -0
  232. package/corpus/templates/forms/app/i18n/es-ES.ts +59 -0
  233. package/corpus/templates/forms/app/i18n/fr-FR.ts +59 -0
  234. package/corpus/templates/forms/app/i18n/hi-IN.ts +59 -0
  235. package/corpus/templates/forms/app/i18n/index.ts +31 -0
  236. package/corpus/templates/forms/app/i18n/ja-JP.ts +59 -0
  237. package/corpus/templates/forms/app/i18n/ko-KR.ts +59 -0
  238. package/corpus/templates/forms/app/i18n/pt-BR.ts +59 -0
  239. package/corpus/templates/forms/app/i18n/zh-CN.ts +56 -0
  240. package/corpus/templates/forms/app/root.tsx +65 -16
  241. package/corpus/templates/forms/app/routes/_app.settings.tsx +85 -0
  242. package/corpus/templates/forms/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  243. package/corpus/templates/forms/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  244. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +29 -17
  245. package/corpus/templates/macros/app/components/layout/Header.tsx +16 -10
  246. package/corpus/templates/macros/app/i18n/ar-SA.ts +54 -0
  247. package/corpus/templates/macros/app/i18n/de-DE.ts +55 -0
  248. package/corpus/templates/macros/app/i18n/en-US.ts +55 -0
  249. package/corpus/templates/macros/app/i18n/es-ES.ts +55 -0
  250. package/corpus/templates/macros/app/i18n/fr-FR.ts +55 -0
  251. package/corpus/templates/macros/app/i18n/hi-IN.ts +55 -0
  252. package/corpus/templates/macros/app/i18n/index.ts +31 -0
  253. package/corpus/templates/macros/app/i18n/ja-JP.ts +55 -0
  254. package/corpus/templates/macros/app/i18n/ko-KR.ts +55 -0
  255. package/corpus/templates/macros/app/i18n/pt-BR.ts +55 -0
  256. package/corpus/templates/macros/app/i18n/zh-CN.ts +53 -0
  257. package/corpus/templates/macros/app/root.tsx +65 -15
  258. package/corpus/templates/macros/app/routes/settings.tsx +85 -0
  259. package/corpus/templates/macros/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  260. package/corpus/templates/macros/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  261. package/corpus/templates/mail/.agents/skills/self-modifying-code/SKILL.md +6 -0
  262. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +9 -4
  263. package/corpus/templates/mail/app/i18n/ar-SA.ts +33 -0
  264. package/corpus/templates/mail/app/i18n/de-DE.ts +33 -0
  265. package/corpus/templates/mail/app/i18n/en-US.ts +32 -0
  266. package/corpus/templates/mail/app/i18n/es-ES.ts +33 -0
  267. package/corpus/templates/mail/app/i18n/fr-FR.ts +33 -0
  268. package/corpus/templates/mail/app/i18n/hi-IN.ts +32 -0
  269. package/corpus/templates/mail/app/i18n/index.ts +31 -0
  270. package/corpus/templates/mail/app/i18n/ja-JP.ts +32 -0
  271. package/corpus/templates/mail/app/i18n/ko-KR.ts +33 -0
  272. package/corpus/templates/mail/app/i18n/pt-BR.ts +34 -0
  273. package/corpus/templates/mail/app/i18n/zh-CN.ts +32 -0
  274. package/corpus/templates/mail/app/pages/SettingsPage.tsx +67 -13
  275. package/corpus/templates/mail/app/root.tsx +20 -0
  276. package/corpus/templates/mail/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  277. package/corpus/templates/mail/changelog/2026-06-24-settings-now-link-directly-to-agent-settings-for-model-api-k.md +6 -0
  278. package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +5 -0
  279. package/corpus/templates/plan/.agents/skills/self-modifying-code/SKILL.md +6 -0
  280. package/corpus/templates/plan/app/components/layout/Header.tsx +19 -12
  281. package/corpus/templates/plan/app/components/layout/Layout.tsx +11 -7
  282. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +41 -28
  283. package/corpus/templates/plan/app/i18n/ar-SA.ts +77 -0
  284. package/corpus/templates/plan/app/i18n/de-DE.ts +78 -0
  285. package/corpus/templates/plan/app/i18n/en-US.ts +78 -0
  286. package/corpus/templates/plan/app/i18n/es-ES.ts +78 -0
  287. package/corpus/templates/plan/app/i18n/fr-FR.ts +78 -0
  288. package/corpus/templates/plan/app/i18n/hi-IN.ts +78 -0
  289. package/corpus/templates/plan/app/i18n/index.ts +31 -0
  290. package/corpus/templates/plan/app/i18n/ja-JP.ts +79 -0
  291. package/corpus/templates/plan/app/i18n/ko-KR.ts +77 -0
  292. package/corpus/templates/plan/app/i18n/pt-BR.ts +78 -0
  293. package/corpus/templates/plan/app/i18n/zh-CN.ts +74 -0
  294. package/corpus/templates/plan/app/root.tsx +45 -8
  295. package/corpus/templates/plan/app/routes/settings.tsx +86 -0
  296. package/corpus/templates/plan/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  297. package/corpus/templates/plan/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  298. package/corpus/templates/slides/.agents/skills/self-modifying-code/SKILL.md +6 -0
  299. package/corpus/templates/slides/app/components/layout/Header.tsx +23 -11
  300. package/corpus/templates/slides/app/components/layout/Layout.tsx +7 -6
  301. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +23 -11
  302. package/corpus/templates/slides/app/i18n/ar-SA.ts +54 -0
  303. package/corpus/templates/slides/app/i18n/de-DE.ts +56 -0
  304. package/corpus/templates/slides/app/i18n/en-US.ts +55 -0
  305. package/corpus/templates/slides/app/i18n/es-ES.ts +55 -0
  306. package/corpus/templates/slides/app/i18n/fr-FR.ts +55 -0
  307. package/corpus/templates/slides/app/i18n/hi-IN.ts +55 -0
  308. package/corpus/templates/slides/app/i18n/index.ts +31 -0
  309. package/corpus/templates/slides/app/i18n/ja-JP.ts +55 -0
  310. package/corpus/templates/slides/app/i18n/ko-KR.ts +55 -0
  311. package/corpus/templates/slides/app/i18n/pt-BR.ts +55 -0
  312. package/corpus/templates/slides/app/i18n/zh-CN.ts +53 -0
  313. package/corpus/templates/slides/app/root.tsx +50 -8
  314. package/corpus/templates/slides/app/routes/settings.tsx +85 -0
  315. package/corpus/templates/slides/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  316. package/corpus/templates/slides/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  317. package/corpus/templates/videos/.agents/skills/self-modifying-code/SKILL.md +6 -0
  318. package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +14 -9
  319. package/corpus/templates/videos/app/components/Sidebar.tsx +16 -9
  320. package/corpus/templates/videos/app/components/StudioHeader.tsx +12 -8
  321. package/corpus/templates/videos/app/components/layout/Header.tsx +21 -15
  322. package/corpus/templates/videos/app/components/layout/Layout.tsx +10 -7
  323. package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +21 -6
  324. package/corpus/templates/videos/app/i18n/ar-SA.ts +73 -0
  325. package/corpus/templates/videos/app/i18n/de-DE.ts +75 -0
  326. package/corpus/templates/videos/app/i18n/en-US.ts +74 -0
  327. package/corpus/templates/videos/app/i18n/es-ES.ts +75 -0
  328. package/corpus/templates/videos/app/i18n/fr-FR.ts +75 -0
  329. package/corpus/templates/videos/app/i18n/hi-IN.ts +74 -0
  330. package/corpus/templates/videos/app/i18n/index.ts +31 -0
  331. package/corpus/templates/videos/app/i18n/ja-JP.ts +74 -0
  332. package/corpus/templates/videos/app/i18n/ko-KR.ts +74 -0
  333. package/corpus/templates/videos/app/i18n/pt-BR.ts +75 -0
  334. package/corpus/templates/videos/app/i18n/zh-CN.ts +72 -0
  335. package/corpus/templates/videos/app/pages/Index.tsx +11 -9
  336. package/corpus/templates/videos/app/root.tsx +45 -7
  337. package/corpus/templates/videos/app/routes/settings.tsx +85 -0
  338. package/corpus/templates/videos/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  339. package/corpus/templates/videos/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  340. package/dist/client/CommandMenu.d.ts +3 -0
  341. package/dist/client/CommandMenu.d.ts.map +1 -1
  342. package/dist/client/CommandMenu.js +9 -0
  343. package/dist/client/CommandMenu.js.map +1 -1
  344. package/dist/client/app-providers.d.ts +8 -1
  345. package/dist/client/app-providers.d.ts.map +1 -1
  346. package/dist/client/app-providers.js +7 -5
  347. package/dist/client/app-providers.js.map +1 -1
  348. package/dist/client/i18n.d.ts +54 -0
  349. package/dist/client/i18n.d.ts.map +1 -0
  350. package/dist/client/i18n.js +354 -0
  351. package/dist/client/i18n.js.map +1 -0
  352. package/dist/client/index.d.ts +2 -1
  353. package/dist/client/index.d.ts.map +1 -1
  354. package/dist/client/index.js +2 -1
  355. package/dist/client/index.js.map +1 -1
  356. package/dist/index.browser.d.ts +1 -1
  357. package/dist/index.browser.d.ts.map +1 -1
  358. package/dist/index.browser.js +1 -1
  359. package/dist/index.browser.js.map +1 -1
  360. package/dist/localization/actions/get-localization-preference.d.ts +4 -0
  361. package/dist/localization/actions/get-localization-preference.d.ts.map +1 -0
  362. package/dist/localization/actions/get-localization-preference.js +16 -0
  363. package/dist/localization/actions/get-localization-preference.js.map +1 -0
  364. package/dist/localization/actions/set-localization-preference.d.ts +6 -0
  365. package/dist/localization/actions/set-localization-preference.d.ts.map +1 -0
  366. package/dist/localization/actions/set-localization-preference.js +24 -0
  367. package/dist/localization/actions/set-localization-preference.js.map +1 -0
  368. package/dist/localization/index.d.ts +3 -0
  369. package/dist/localization/index.d.ts.map +1 -0
  370. package/dist/localization/index.js +3 -0
  371. package/dist/localization/index.js.map +1 -0
  372. package/dist/localization/server.d.ts +25 -0
  373. package/dist/localization/server.d.ts.map +1 -0
  374. package/dist/localization/server.js +69 -0
  375. package/dist/localization/server.js.map +1 -0
  376. package/dist/localization/shared.d.ts +25 -0
  377. package/dist/localization/shared.d.ts.map +1 -0
  378. package/dist/localization/shared.js +134 -0
  379. package/dist/localization/shared.js.map +1 -0
  380. package/dist/server/action-discovery.d.ts.map +1 -1
  381. package/dist/server/action-discovery.js +8 -0
  382. package/dist/server/action-discovery.js.map +1 -1
  383. package/dist/server/index.d.ts +1 -0
  384. package/dist/server/index.d.ts.map +1 -1
  385. package/dist/server/index.js +1 -0
  386. package/dist/server/index.js.map +1 -1
  387. package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  388. package/dist/templates/default/.agents/skills/internationalization/SKILL.md +77 -0
  389. package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +6 -0
  390. package/dist/templates/default/AGENTS.md +16 -15
  391. package/dist/templates/default/app/i18n/en-US.ts +29 -0
  392. package/dist/templates/default/app/i18n/index.ts +13 -0
  393. package/dist/templates/default/app/root.tsx +20 -1
  394. package/dist/templates/default/app/routes/_index.tsx +24 -9
  395. package/dist/templates/default/app/routes/settings.tsx +67 -0
  396. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  397. package/dist/templates/workspace-core/.agents/skills/internationalization/SKILL.md +77 -0
  398. package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +6 -0
  399. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  400. package/dist/vite/action-types-plugin.js +8 -0
  401. package/dist/vite/action-types-plugin.js.map +1 -1
  402. package/docs/AGENTS.md +1 -0
  403. package/docs/content/client.md +15 -0
  404. package/docs/content/internationalization.md +145 -0
  405. package/docs/content/locales/ar-SA/internationalization.md +102 -0
  406. package/docs/content/locales/de-DE/internationalization.md +102 -0
  407. package/docs/content/locales/es-ES/internationalization.md +102 -0
  408. package/docs/content/locales/fr-FR/internationalization.md +102 -0
  409. package/docs/content/locales/hi-IN/internationalization.md +102 -0
  410. package/docs/content/locales/ja-JP/internationalization.md +114 -0
  411. package/docs/content/locales/ko-KR/internationalization.md +102 -0
  412. package/docs/content/locales/pt-BR/internationalization.md +102 -0
  413. package/docs/content/locales/zh-CN/internationalization.md +102 -0
  414. package/docs/content/skills-guide.md +19 -18
  415. package/package.json +7 -1
  416. package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  417. package/src/templates/default/.agents/skills/internationalization/SKILL.md +77 -0
  418. package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +6 -0
  419. package/src/templates/default/AGENTS.md +16 -15
  420. package/src/templates/default/app/i18n/en-US.ts +29 -0
  421. package/src/templates/default/app/i18n/index.ts +13 -0
  422. package/src/templates/default/app/root.tsx +20 -1
  423. package/src/templates/default/app/routes/_index.tsx +24 -9
  424. package/src/templates/default/app/routes/settings.tsx +67 -0
  425. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  426. package/src/templates/workspace-core/.agents/skills/internationalization/SKILL.md +77 -0
  427. package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +6 -0
@@ -27,7 +27,10 @@ import {
27
27
  AppearancePicker,
28
28
  callAction,
29
29
  ChangelogSettingsCard,
30
+ LanguagePicker,
31
+ openAgentSettings,
30
32
  type AppearancePresetId,
33
+ useT,
31
34
  } from "@agent-native/core/client";
32
35
  import changelog from "../../CHANGELOG.md?raw";
33
36
  import {
@@ -44,6 +47,7 @@ import {
44
47
  import { toast } from "sonner";
45
48
 
46
49
  export default function Settings() {
50
+ const t = useT();
47
51
  const { data: settings } = useSettings();
48
52
  const updateSettings = useUpdateSettings();
49
53
  const googleStatus = useGoogleAuthStatus();
@@ -54,7 +58,7 @@ export default function Settings() {
54
58
  startDesktopGoogleAuth,
55
59
  } = useGoogleDesktopAuth({
56
60
  onError: (issue) =>
57
- toast.error(issue.message || issue.error || "Google sign-in failed"),
61
+ toast.error(issue.message || issue.error || t("settings.googleFailed")),
58
62
  onSuccess: () => window.location.reload(),
59
63
  });
60
64
  const zoomStatus = useZoomStatus();
@@ -86,8 +90,8 @@ export default function Settings() {
86
90
  defaultEventDuration: defaultDuration,
87
91
  },
88
92
  {
89
- onSuccess: () => toast.success("Settings saved"),
90
- onError: () => toast.error("Failed to save settings"),
93
+ onSuccess: () => toast.success(t("settings.saved")),
94
+ onError: () => toast.error(t("settings.saveFailed")),
91
95
  },
92
96
  );
93
97
  }
@@ -121,47 +125,74 @@ export default function Settings() {
121
125
  for (const account of accounts) {
122
126
  await disconnectGoogle.mutateAsync(account.email);
123
127
  }
124
- toast.success("Google Calendar disconnected");
128
+ toast.success(t("settings.googleDisconnected"));
125
129
  } catch {
126
- toast.error("Failed to disconnect");
130
+ toast.error(t("settings.disconnectFailed"));
127
131
  }
128
132
  }
129
133
 
130
134
  function handleConnectZoom() {
131
135
  connectZoom.mutate(undefined, {
132
- onSuccess: () => toast("Zoom connection opened"),
136
+ onSuccess: () => toast(t("settings.zoomOpened")),
133
137
  onError: (error) =>
134
138
  toast.error(
135
- error instanceof Error ? error.message : "Could not connect Zoom",
139
+ error instanceof Error
140
+ ? error.message
141
+ : t("settings.zoomConnectFailed"),
136
142
  ),
137
143
  });
138
144
  }
139
145
 
140
146
  function handleDisconnectZoom() {
141
147
  disconnectZoom.mutate(undefined, {
142
- onSuccess: () => toast.success("Zoom disconnected"),
143
- onError: () => toast.error("Failed to disconnect Zoom"),
148
+ onSuccess: () => toast.success(t("settings.zoomDisconnected")),
149
+ onError: () => toast.error(t("settings.zoomDisconnectFailed")),
144
150
  });
145
151
  }
146
152
 
147
153
  return (
148
154
  <div className="mx-auto max-w-2xl space-y-6 px-4 py-8 pb-12">
149
155
  <div>
150
- <h1 className="text-2xl font-semibold">Settings</h1>
156
+ <h1 className="text-2xl font-semibold">{t("settings.title")}</h1>
151
157
  <p className="text-sm text-muted-foreground mt-1">
152
- Configure your calendar and integrations.
158
+ {t("settings.description")}
153
159
  </p>
154
160
  </div>
155
161
 
156
162
  <ChangelogSettingsCard markdown={changelog} />
157
163
 
164
+ <Card>
165
+ <CardHeader>
166
+ <CardTitle className="text-lg">
167
+ {t("settings.languageTitle")}
168
+ </CardTitle>
169
+ <CardDescription>{t("settings.languageDescription")}</CardDescription>
170
+ </CardHeader>
171
+ <CardContent className="max-w-xs space-y-1.5">
172
+ <Label>{t("settings.languageLabel")}</Label>
173
+ <LanguagePicker label={t("settings.languageLabel")} />
174
+ </CardContent>
175
+ </Card>
176
+
177
+ <Card>
178
+ <CardHeader>
179
+ <CardTitle className="text-lg">{t("settings.agentTitle")}</CardTitle>
180
+ <CardDescription>{t("settings.agentDescription")}</CardDescription>
181
+ </CardHeader>
182
+ <CardContent>
183
+ <Button variant="outline" onClick={() => openAgentSettings()}>
184
+ {t("settings.openAgentSettings")}
185
+ </Button>
186
+ </CardContent>
187
+ </Card>
188
+
158
189
  {/* Google Calendar Connection */}
159
190
  <Card>
160
191
  <CardHeader>
161
- <CardTitle className="text-lg">Google Calendar</CardTitle>
162
- <CardDescription>
163
- Connect your Google Calendar to sync events.
164
- </CardDescription>
192
+ <CardTitle className="text-lg">
193
+ {t("settings.googleCalendar")}
194
+ </CardTitle>
195
+ <CardDescription>{t("settings.googleDescription")}</CardDescription>
165
196
  </CardHeader>
166
197
  <CardContent>
167
198
  <div className="flex items-center justify-between">
@@ -170,7 +201,9 @@ export default function Settings() {
170
201
  <>
171
202
  <IconCircleCheck className="h-5 w-5 text-emerald-600 dark:text-emerald-400" />
172
203
  <div>
173
- <p className="text-sm font-medium">Connected</p>
204
+ <p className="text-sm font-medium">
205
+ {t("common.connected")}
206
+ </p>
174
207
  {googleStatus.data.accounts?.length > 0 && (
175
208
  <p className="text-xs text-muted-foreground">
176
209
  {googleStatus.data.accounts
@@ -183,7 +216,9 @@ export default function Settings() {
183
216
  ) : (
184
217
  <>
185
218
  <IconCircleX className="h-5 w-5 text-muted-foreground" />
186
- <p className="text-sm text-muted-foreground">Not connected</p>
219
+ <p className="text-sm text-muted-foreground">
220
+ {t("common.notConnected")}
221
+ </p>
187
222
  </>
188
223
  )}
189
224
  </div>
@@ -196,7 +231,7 @@ export default function Settings() {
196
231
  disabled={disconnectGoogle.isPending}
197
232
  >
198
233
  <IconUnlink className="mr-1.5 h-3.5 w-3.5" />
199
- Disconnect
234
+ {t("common.disconnect")}
200
235
  </Button>
201
236
  ) : (
202
237
  <Button
@@ -209,7 +244,7 @@ export default function Settings() {
209
244
  }
210
245
  >
211
246
  <IconExternalLink className="mr-1.5 h-3.5 w-3.5" />
212
- Connect
247
+ {t("common.connect")}
213
248
  </Button>
214
249
  )}
215
250
  </div>
@@ -307,14 +342,12 @@ export default function Settings() {
307
342
  {/* General Settings */}
308
343
  <Card>
309
344
  <CardHeader>
310
- <CardTitle className="text-lg">General</CardTitle>
311
- <CardDescription>
312
- Calendar defaults and fallback booking copy.
313
- </CardDescription>
345
+ <CardTitle className="text-lg">{t("settings.general")}</CardTitle>
346
+ <CardDescription>{t("settings.generalDescription")}</CardDescription>
314
347
  </CardHeader>
315
348
  <CardContent className="space-y-4">
316
349
  <div className="space-y-2">
317
- <Label htmlFor="timezone">Timezone</Label>
350
+ <Label htmlFor="timezone">{t("settings.timezone")}</Label>
318
351
  <TimezoneCombobox value={timezone} onChange={setTimezone} />
319
352
  </div>
320
353
 
@@ -368,12 +401,14 @@ export default function Settings() {
368
401
 
369
402
  <div className="flex flex-wrap gap-2">
370
403
  <Button onClick={handleSave} disabled={updateSettings.isPending}>
371
- {updateSettings.isPending ? "Saving..." : "Save Settings"}
404
+ {updateSettings.isPending
405
+ ? t("common.saving")
406
+ : t("settings.saveSettings")}
372
407
  </Button>
373
408
  <Button asChild variant="outline">
374
409
  <Link to="/booking-links">
375
410
  <IconLink className="mr-1.5 h-3.5 w-3.5" />
376
- Booking links
411
+ {t("navigation.bookingLinks")}
377
412
  </Link>
378
413
  </Button>
379
414
  </div>
@@ -383,9 +418,9 @@ export default function Settings() {
383
418
  {/* Appearance */}
384
419
  <Card>
385
420
  <CardHeader>
386
- <CardTitle className="text-lg">Appearance</CardTitle>
421
+ <CardTitle className="text-lg">{t("settings.appearance")}</CardTitle>
387
422
  <CardDescription>
388
- Pick a color theme for your workspace. Or just ask the agent.
423
+ {t("settings.appearanceDescription")}
389
424
  </CardDescription>
390
425
  </CardHeader>
391
426
  <CardContent>
@@ -4,7 +4,9 @@ import {
4
4
  Outlet,
5
5
  Scripts,
6
6
  ScrollRestoration,
7
+ useLoaderData,
7
8
  useLocation,
9
+ useRouteLoaderData,
8
10
  } from "react-router";
9
11
  import { useCallback, useState } from "react";
10
12
  import { useQueryClient } from "@tanstack/react-query";
@@ -17,14 +19,21 @@ import {
17
19
  appPath,
18
20
  configureTracking,
19
21
  createAgentNativeQueryClient,
22
+ getLocaleInitScript,
20
23
  getThemeInitScript,
24
+ type LocaleCode,
25
+ type LocaleMessages,
26
+ type LocalizationPreference,
21
27
  useCommandMenuShortcut,
22
28
  useDbSync,
29
+ useT,
23
30
  } from "@agent-native/core/client";
31
+ import { resolveLocaleFromRequest } from "@agent-native/core/server";
24
32
  import { IconSun, IconMoon } from "@tabler/icons-react";
25
33
  import changelog from "../CHANGELOG.md?raw";
26
- import type { LinksFunction } from "react-router";
34
+ import type { LinksFunction, LoaderFunctionArgs } from "react-router";
27
35
  import stylesheet from "./global.css?url";
36
+ import { i18nCatalog } from "./i18n";
28
37
  configureTracking({
29
38
  getDefaultProps: (_name, properties) => ({
30
39
  ...properties,
@@ -36,11 +45,55 @@ export const links: LinksFunction = () => [
36
45
  { rel: "stylesheet", href: stylesheet },
37
46
  ];
38
47
 
48
+ interface RootLoaderData {
49
+ locale: LocaleCode;
50
+ preference: LocalizationPreference;
51
+ dir: "ltr" | "rtl";
52
+ messages: LocaleMessages;
53
+ }
54
+
55
+ export async function loader({
56
+ request,
57
+ }: LoaderFunctionArgs): Promise<RootLoaderData> {
58
+ const resolved = resolveLocaleFromRequest({ request });
59
+ const messages =
60
+ ((await i18nCatalog.loadMessages?.(resolved.locale)) as
61
+ | LocaleMessages
62
+ | null
63
+ | undefined) ?? i18nCatalog.messages;
64
+ return {
65
+ locale: resolved.locale,
66
+ preference: resolved.preference,
67
+ dir: resolved.dir,
68
+ messages,
69
+ };
70
+ }
71
+
39
72
  const THEME_INIT_SCRIPT = getThemeInitScript();
40
73
 
74
+ const DEFAULT_LOADER_DATA: RootLoaderData = {
75
+ locale: "en-US",
76
+ preference: { locale: "system" },
77
+ dir: "ltr",
78
+ messages: i18nCatalog.messages,
79
+ };
80
+
41
81
  export function Layout({ children }: { children: React.ReactNode }) {
82
+ const loaderData =
83
+ useRouteLoaderData<typeof loader>("root") ?? DEFAULT_LOADER_DATA;
84
+ const localeInitScript = getLocaleInitScript({
85
+ locale: loaderData.locale,
86
+ preference: loaderData.preference,
87
+ messages: loaderData.messages,
88
+ });
89
+
42
90
  return (
43
- <html lang="en" suppressHydrationWarning>
91
+ <html
92
+ lang={loaderData.locale}
93
+ dir={loaderData.dir}
94
+ data-locale={loaderData.locale}
95
+ suppressHydrationWarning
96
+ >
44
97
  <head>
45
98
  <meta charSet="utf-8" />
46
99
  <meta
@@ -51,6 +104,11 @@ export function Layout({ children }: { children: React.ReactNode }) {
51
104
  suppressHydrationWarning
52
105
  dangerouslySetInnerHTML={{ __html: THEME_INIT_SCRIPT }}
53
106
  />
107
+ <script
108
+ data-agent-native-locale-init
109
+ suppressHydrationWarning
110
+ dangerouslySetInnerHTML={{ __html: localeInitScript }}
111
+ />
54
112
  <link rel="icon" type="image/svg+xml" href={appPath("/favicon.svg")} />
55
113
  <link rel="manifest" href={appPath("/manifest.json")} />
56
114
  <meta name="theme-color" content="#00B5FF" />
@@ -105,6 +163,7 @@ function DbSyncSetup() {
105
163
 
106
164
  function ThemeToggleItem() {
107
165
  const { resolvedTheme, setTheme } = useTheme();
166
+ const t = useT();
108
167
  const isDark = resolvedTheme === "dark";
109
168
  return (
110
169
  <CommandMenu.Item
@@ -112,7 +171,7 @@ function ThemeToggleItem() {
112
171
  keywords={["theme", "dark", "light", "mode"]}
113
172
  >
114
173
  {isDark ? <IconSun size={16} /> : <IconMoon size={16} />}
115
- Toggle theme
174
+ {t("root.toggleTheme")}
116
175
  </CommandMenu.Item>
117
176
  );
118
177
  }
@@ -134,6 +193,7 @@ function isPublicBookingPath(pathname: string): boolean {
134
193
 
135
194
  function AppContent() {
136
195
  const [cmdkOpen, setCmdkOpen] = useState(false);
196
+ const t = useT();
137
197
  useCommandMenuShortcut(useCallback(() => setCmdkOpen(true), []));
138
198
  return (
139
199
  <>
@@ -144,10 +204,12 @@ function AppContent() {
144
204
  changelog={changelog}
145
205
  changelogKey="calendar"
146
206
  >
147
- <CommandMenu.Group heading="Actions">
148
- <CommandMenu.Item onSelect={() => {}}>Search</CommandMenu.Item>
207
+ <CommandMenu.Group heading={t("root.commandActions")}>
208
+ <CommandMenu.Item onSelect={() => {}}>
209
+ {t("root.commandSearch")}
210
+ </CommandMenu.Item>
149
211
  </CommandMenu.Group>
150
- <CommandMenu.Group heading="Appearance">
212
+ <CommandMenu.Group heading={t("root.commandAppearance")}>
151
213
  <ThemeToggleItem />
152
214
  </CommandMenu.Group>
153
215
  </CommandMenu>
@@ -173,13 +235,22 @@ export default function Root() {
173
235
  }),
174
236
  );
175
237
  const location = useLocation();
238
+ const loaderData = useLoaderData<typeof loader>();
239
+ const isPublicPath = isPublicBookingPath(location.pathname);
176
240
 
177
241
  return (
178
242
  <AppProviders
179
243
  queryClient={queryClient}
180
- isPublicPath={isPublicBookingPath(location.pathname)}
244
+ isPublicPath={isPublicPath}
181
245
  clientOnlyFallback={<DefaultSpinner />}
182
246
  toaster={<Toaster richColors position="bottom-center" />}
247
+ i18n={{
248
+ catalog: i18nCatalog,
249
+ initialLocale: loaderData.locale,
250
+ initialPreference: loaderData.preference,
251
+ initialMessages: loaderData.messages,
252
+ persistPreference: !isPublicPath,
253
+ }}
183
254
  >
184
255
  <AppContent />
185
256
  </AppProviders>
@@ -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.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-06-24
4
+ ---
5
+
6
+ Settings now link directly to Agent settings for model, API key, automation, and voice preferences.
@@ -86,6 +86,10 @@ Instruction examples may name secret keys like `SLACK_WEBHOOK`, but must use
86
86
  placeholders such as `${keys.SLACK_WEBHOOK}` or `<SLACK_WEBHOOK>`. Do not paste
87
87
  real keys, internal data, or customer data into instructions as examples.
88
88
 
89
+ If the feature adds or changes visible UI copy, prompts, toasts, labels, empty
90
+ states, or formatting, read `internationalization` and update the app's i18n
91
+ catalogs in the same change.
92
+
89
93
  For app-backed skills, declare skill visibility in the app-skill manifest:
90
94
 
91
95
  - `internal` — only the app's own agents should use it.
@@ -177,3 +181,4 @@ TL;DR: spread `ownableColumns()` into the resource table, pair it with `createSh
177
181
  - **create-skill** — How to create skills for new patterns (area 3 in detail)
178
182
  - **storing-data** — Where to store the feature's data
179
183
  - **real-time-sync** — How the UI stays in sync when the agent writes data
184
+ - **internationalization** — How to update localized UI copy and catalogs
@@ -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,19 +1,23 @@
1
1
  import { useLocation } from "react-router";
2
2
  import { IconMenu2 } from "@tabler/icons-react";
3
3
  import { useHeaderTitle, useHeaderActions } from "./HeaderActions";
4
- import { AgentToggleButton } from "@agent-native/core/client";
4
+ import {
5
+ AgentToggleButton,
6
+ LanguagePicker,
7
+ useT,
8
+ } from "@agent-native/core/client";
5
9
  import { APP_TITLE } from "@/lib/app-config";
6
10
 
7
- const pageTitles: Record<string, string> = {
8
- "/": "Chat",
9
- "/observability": "Observability",
10
- "/settings": "Settings",
11
- "/team": "Team",
11
+ const pageTitleKeys: Record<string, string> = {
12
+ "/": "navigation.chat",
13
+ "/observability": "navigation.observability",
14
+ "/settings": "navigation.settings",
15
+ "/team": "navigation.team",
12
16
  };
13
17
 
14
- function resolveTitle(pathname: string): string {
15
- if (pageTitles[pathname]) return pageTitles[pathname];
16
- if (pathname.startsWith("/extensions")) return "Extensions";
18
+ function resolveTitle(pathname: string, t: (key: string) => string): string {
19
+ if (pageTitleKeys[pathname]) return t(pageTitleKeys[pathname]);
20
+ if (pathname.startsWith("/extensions")) return t("navigation.extensions");
17
21
  return APP_TITLE;
18
22
  }
19
23
 
@@ -23,6 +27,7 @@ interface HeaderProps {
23
27
 
24
28
  export function Header({ onOpenMobileSidebar }: HeaderProps) {
25
29
  const location = useLocation();
30
+ const t = useT();
26
31
  const title = useHeaderTitle();
27
32
  const actions = useHeaderActions();
28
33
 
@@ -32,7 +37,7 @@ export function Header({ onOpenMobileSidebar }: HeaderProps) {
32
37
  <button
33
38
  type="button"
34
39
  onClick={onOpenMobileSidebar}
35
- aria-label="Open navigation"
40
+ aria-label={t("navigation.openNavigation")}
36
41
  className="flex h-9 w-9 cursor-pointer items-center justify-center rounded-md text-muted-foreground hover:text-foreground hover:bg-accent md:hidden"
37
42
  >
38
43
  <IconMenu2 className="h-4 w-4" />
@@ -41,12 +46,13 @@ export function Header({ onOpenMobileSidebar }: HeaderProps) {
41
46
  <div className="flex items-center gap-3 flex-1 min-w-0">
42
47
  {title ?? (
43
48
  <h1 className="text-lg font-semibold tracking-tight truncate">
44
- {resolveTitle(location.pathname)}
49
+ {resolveTitle(location.pathname, t)}
45
50
  </h1>
46
51
  )}
47
52
  </div>
48
53
  <div className="flex items-center gap-2 shrink-0">
49
54
  {actions}
55
+ <LanguagePicker variant="icon" />
50
56
  <AgentToggleButton />
51
57
  </div>
52
58
  </header>
@@ -10,6 +10,7 @@ import {
10
10
  navigateWithAgentChatViewTransition,
11
11
  useAgentChatHomeHandoff,
12
12
  useAgentChatHomeHandoffLinks,
13
+ useT,
13
14
  } from "@agent-native/core/client";
14
15
  import { APP_TITLE } from "@/lib/app-config";
15
16
  import { TAB_ID } from "@/lib/tab-id";
@@ -44,6 +45,7 @@ function routeOwnsToolbar(pathname: string): boolean {
44
45
  export function Layout({ children }: LayoutProps) {
45
46
  const location = useLocation();
46
47
  const navigate = useNavigate();
48
+ const t = useT();
47
49
  const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
48
50
  const [sidebarCollapsed, setSidebarCollapsed] = useState(true);
49
51
  const isChatRoute =
@@ -105,7 +107,7 @@ export function Layout({ children }: LayoutProps) {
105
107
  variant="ghost"
106
108
  size="icon"
107
109
  onClick={() => setMobileSidebarOpen(true)}
108
- aria-label="Open navigation"
110
+ aria-label={t("navigation.openNavigation")}
109
111
  >
110
112
  <IconMenu2 className="size-4" />
111
113
  </Button>
@@ -116,7 +118,7 @@ export function Layout({ children }: LayoutProps) {
116
118
  <button
117
119
  type="button"
118
120
  onClick={() => setMobileSidebarOpen(true)}
119
- aria-label="Open navigation"
121
+ aria-label={t("navigation.openNavigation")}
120
122
  className="flex h-9 w-9 cursor-pointer items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
121
123
  >
122
124
  <IconMenu2 className="h-4 w-4" />
@@ -142,9 +144,11 @@ export function Layout({ children }: LayoutProps) {
142
144
  </div>
143
145
  <Sheet open={mobileSidebarOpen} onOpenChange={setMobileSidebarOpen}>
144
146
  <SheetContent side="left" className="p-0 w-[260px]">
145
- <SheetTitle className="sr-only">Navigation</SheetTitle>
147
+ <SheetTitle className="sr-only">
148
+ {t("navigation.navigation")}
149
+ </SheetTitle>
146
150
  <SheetDescription className="sr-only">
147
- App navigation links
151
+ {t("navigation.navigationDescription")}
148
152
  </SheetDescription>
149
153
  <Sidebar collapsed={false} collapsible={false} />
150
154
  </SheetContent>
@@ -159,11 +163,11 @@ export function Layout({ children }: LayoutProps) {
159
163
  browserTabId={TAB_ID}
160
164
  openOnChatRunning={chatHomeHandoffActive}
161
165
  onFullscreenRequest={openAskAgentFullscreen}
162
- emptyStateText="Ask the agent to inspect or change this app."
166
+ emptyStateText={t("chat.inspectEmptyState")}
163
167
  suggestions={[
164
- "What can you do here?",
165
- "Call hello for Builder",
166
- "Add a new action and show it in the UI",
168
+ t("chat.inspectSuggestionCapabilities"),
169
+ t("chat.inspectSuggestionHello"),
170
+ t("chat.inspectSuggestionAction"),
167
171
  ]}
168
172
  >
169
173
  {contentFrame}