@qlover/create-app 0.7.15 → 0.9.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 (363) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/configs/_common/.github/workflows/general-check.yml +1 -1
  3. package/dist/configs/_common/.github/workflows/release.yml +2 -2
  4. package/dist/configs/_common/.gitignore.template +6 -0
  5. package/dist/configs/_common/.prettierignore +17 -5
  6. package/dist/configs/_common/.vscode/settings.json +6 -1
  7. package/dist/index.cjs +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/templates/next-app/.env.template +1 -1
  10. package/dist/templates/next-app/README.en.md +0 -1
  11. package/dist/templates/next-app/README.md +0 -1
  12. package/dist/templates/next-app/config/Identifier/api.ts +5 -5
  13. package/dist/templates/next-app/config/Identifier/common/admint.table.ts +69 -0
  14. package/dist/templates/next-app/config/Identifier/common/common.ts +76 -0
  15. package/dist/templates/next-app/config/Identifier/common/index.ts +3 -0
  16. package/dist/templates/next-app/config/Identifier/{validator.ts → common/validators.ts} +5 -5
  17. package/dist/templates/next-app/config/Identifier/index.ts +2 -12
  18. package/dist/templates/next-app/config/Identifier/pages/index.ts +6 -0
  19. package/dist/templates/next-app/config/Identifier/pages/page.admin.home.ts +27 -0
  20. package/dist/templates/next-app/config/Identifier/pages/page.admin.locales.ts +266 -0
  21. package/dist/templates/next-app/config/Identifier/pages/page.admin.user.ts +293 -0
  22. package/dist/templates/{react-app/config/Identifier → next-app/config/Identifier/pages}/page.home.ts +15 -22
  23. package/dist/templates/next-app/config/Identifier/{page.login.ts → pages/page.login.ts} +28 -34
  24. package/dist/templates/next-app/config/Identifier/{page.register.ts → pages/page.register.ts} +30 -29
  25. package/dist/templates/next-app/config/adminNavs.ts +19 -0
  26. package/dist/templates/next-app/config/common.ts +22 -13
  27. package/dist/templates/next-app/config/i18n/HomeI18n.ts +5 -5
  28. package/dist/templates/next-app/config/i18n/admin18n.ts +61 -19
  29. package/dist/templates/next-app/config/i18n/i18nConfig.ts +2 -0
  30. package/dist/templates/next-app/config/i18n/i18nKeyScheam.ts +36 -0
  31. package/dist/templates/next-app/config/i18n/loginI18n.ts +22 -22
  32. package/dist/templates/next-app/config/i18n/register18n.ts +23 -24
  33. package/dist/templates/next-app/docs/en/index.md +0 -1
  34. package/dist/templates/next-app/docs/en/project-structure.md +0 -1
  35. package/dist/templates/next-app/docs/zh/index.md +0 -1
  36. package/dist/templates/next-app/docs/zh/project-structure.md +0 -1
  37. package/dist/templates/next-app/make/generateLocales.ts +19 -12
  38. package/dist/templates/next-app/migrations/schema/LocalesSchema.ts +15 -0
  39. package/dist/templates/next-app/migrations/sql/1694244000000.sql +11 -0
  40. package/dist/templates/next-app/package.json +7 -3
  41. package/dist/templates/next-app/public/locales/en.json +172 -207
  42. package/dist/templates/next-app/public/locales/zh.json +172 -207
  43. package/dist/templates/next-app/src/app/[locale]/admin/locales/page.tsx +153 -0
  44. package/dist/templates/next-app/src/app/[locale]/admin/users/page.tsx +48 -50
  45. package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +2 -2
  46. package/dist/templates/next-app/src/app/api/admin/locales/create/route.ts +34 -0
  47. package/dist/templates/next-app/src/app/api/admin/locales/import/route.ts +40 -0
  48. package/dist/templates/next-app/src/app/api/admin/locales/route.ts +42 -0
  49. package/dist/templates/next-app/src/app/api/admin/locales/update/route.ts +32 -0
  50. package/dist/templates/next-app/src/app/api/locales/json/route.ts +44 -0
  51. package/dist/templates/next-app/src/base/cases/AdminPageManager.ts +1 -13
  52. package/dist/templates/next-app/src/base/cases/Datetime.ts +18 -0
  53. package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +12 -6
  54. package/dist/templates/next-app/src/base/cases/ResourceState.ts +17 -0
  55. package/dist/templates/next-app/src/base/cases/TranslateI18nInterface.ts +25 -0
  56. package/dist/templates/next-app/src/base/cases/ZodColumnBuilder.ts +200 -0
  57. package/dist/templates/next-app/src/base/port/ZodBuilderInterface.ts +8 -0
  58. package/dist/templates/next-app/src/base/services/AdminLocalesService.ts +20 -0
  59. package/dist/templates/next-app/src/base/services/AdminPageEvent.ts +26 -0
  60. package/dist/templates/next-app/src/base/services/AdminPageScheduler.ts +42 -0
  61. package/dist/templates/next-app/src/base/services/ResourceService.ts +122 -0
  62. package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +104 -0
  63. package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +38 -5
  64. package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +1 -1
  65. package/dist/templates/next-app/src/i18n/request.ts +30 -1
  66. package/dist/templates/next-app/src/server/PageParams.ts +2 -10
  67. package/dist/templates/next-app/src/server/port/DBBridgeInterface.ts +5 -0
  68. package/dist/templates/next-app/src/server/port/DBTableInterface.ts +2 -0
  69. package/dist/templates/next-app/src/server/port/LocalesRepositoryInterface.ts +43 -0
  70. package/dist/templates/next-app/src/server/repositorys/LocalesRepository.ts +197 -0
  71. package/dist/templates/next-app/src/server/services/ApiLocaleService.ts +122 -0
  72. package/dist/templates/next-app/src/server/sqlBridges/SupabaseBridge.ts +60 -11
  73. package/dist/templates/next-app/src/server/validators/ExtendedExecutorError.ts +6 -0
  74. package/dist/templates/next-app/src/server/validators/LocalesValidator.ts +131 -0
  75. package/dist/templates/next-app/src/server/validators/LoginValidator.ts +2 -5
  76. package/dist/templates/next-app/src/server/validators/PaginationValidator.ts +32 -16
  77. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/_default.css +2 -1
  78. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/dark.css +28 -29
  79. package/dist/templates/next-app/src/styles/css/antd-themes/pagination/pink.css +2 -1
  80. package/dist/templates/next-app/src/uikit/components/AdminLayout.tsx +17 -3
  81. package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +5 -4
  82. package/dist/templates/next-app/src/uikit/components/BaseLayout.tsx +5 -4
  83. package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +3 -2
  84. package/dist/templates/next-app/src/uikit/components/ComboProvider.tsx +1 -1
  85. package/dist/templates/next-app/src/uikit/components/EditableCell.tsx +118 -0
  86. package/dist/templates/next-app/src/uikit/components/LogoutButton.tsx +5 -6
  87. package/dist/templates/next-app/src/uikit/components/ThemeSwitcher.tsx +1 -1
  88. package/dist/templates/next-app/src/uikit/components/With.tsx +2 -2
  89. package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportButton.tsx +62 -0
  90. package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportEvent.ts +28 -0
  91. package/dist/templates/next-app/src/uikit/components/localesImportButton/import.module.css +6 -0
  92. package/dist/templates/next-app/src/uikit/hook/useI18nInterface.ts +8 -14
  93. package/dist/templates/next-app/src/uikit/hook/useWarnTranslations.ts +25 -0
  94. package/dist/templates/react-app/.prettierignore +17 -0
  95. package/dist/templates/react-app/README.en.md +71 -54
  96. package/dist/templates/react-app/README.md +35 -18
  97. package/dist/templates/react-app/__tests__/__mocks__/BootstrapTest.ts +14 -0
  98. package/dist/templates/react-app/__tests__/__mocks__/MockAppConfit.ts +1 -1
  99. package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +2 -2
  100. package/dist/templates/react-app/__tests__/__mocks__/MockLogger.ts +1 -1
  101. package/dist/templates/react-app/__tests__/__mocks__/components/TestApp.tsx +45 -0
  102. package/dist/templates/react-app/__tests__/__mocks__/components/TestBootstrapsProvider.tsx +34 -0
  103. package/dist/templates/react-app/__tests__/__mocks__/components/TestRouter.tsx +46 -0
  104. package/dist/templates/react-app/__tests__/__mocks__/components/index.ts +12 -0
  105. package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +1 -2
  106. package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOC.ts +51 -0
  107. package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOCRegister.ts +69 -0
  108. package/dist/templates/react-app/__tests__/setup/index.ts +1 -51
  109. package/dist/templates/react-app/__tests__/setup/setupGlobal.ts +51 -0
  110. package/dist/templates/react-app/__tests__/src/App.structure.test.tsx +115 -0
  111. package/dist/templates/react-app/__tests__/src/base/cases/AppConfig.test.ts +2 -2
  112. package/dist/templates/react-app/__tests__/src/base/cases/AppError.test.ts +1 -1
  113. package/dist/templates/react-app/__tests__/src/base/cases/DialogHandler.test.ts +3 -5
  114. package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +13 -2
  115. package/dist/templates/react-app/__tests__/src/base/cases/InversifyContainer.test.ts +1 -1
  116. package/dist/templates/react-app/__tests__/src/base/cases/PublicAssetsPath.test.ts +1 -1
  117. package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +5 -5
  118. package/dist/templates/react-app/__tests__/src/base/cases/RequestStatusCatcher.test.ts +1 -2
  119. package/dist/templates/react-app/__tests__/src/base/cases/RouterLoader.test.ts +25 -15
  120. package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +29 -15
  121. package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +19 -9
  122. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +153 -0
  123. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +9 -7
  124. package/dist/templates/react-app/__tests__/src/main.integration.test.tsx +4 -5
  125. package/dist/templates/react-app/__tests__/src/main.test.tsx +4 -4
  126. package/dist/templates/react-app/__tests__/src/uikit/components/BaseHeader.test.tsx +68 -59
  127. package/dist/templates/react-app/__tests__/src/uikit/components/chatMessage/ChatRoot.test.tsx +274 -0
  128. package/dist/templates/react-app/config/IOCIdentifier.ts +11 -8
  129. package/dist/templates/react-app/config/Identifier/{common.error.ts → common/common.error.ts} +5 -5
  130. package/dist/templates/react-app/config/Identifier/{common.ts → common/common.ts} +9 -9
  131. package/dist/templates/react-app/config/Identifier/common/index.ts +2 -0
  132. package/dist/templates/react-app/config/Identifier/components/component.chatMessage.ts +56 -0
  133. package/dist/templates/react-app/config/Identifier/components/component.messageBaseList.ts +103 -0
  134. package/dist/templates/react-app/config/Identifier/index.ts +1 -9
  135. package/dist/templates/react-app/config/Identifier/pages/index.ts +9 -0
  136. package/dist/templates/react-app/config/Identifier/{page.about.ts → pages/page.about.ts} +34 -26
  137. package/dist/templates/react-app/config/Identifier/{page.executor.ts → pages/page.executor.ts} +47 -39
  138. package/dist/templates/{next-app/config/Identifier → react-app/config/Identifier/pages}/page.home.ts +24 -23
  139. package/dist/templates/react-app/config/Identifier/pages/page.identifiter.ts +102 -0
  140. package/dist/templates/react-app/config/Identifier/{page.jsonStorage.ts → pages/page.jsonStorage.ts} +18 -11
  141. package/dist/templates/react-app/config/Identifier/{page.login.ts → pages/page.login.ts} +37 -27
  142. package/dist/templates/react-app/config/Identifier/pages/page.message.ts +20 -0
  143. package/dist/templates/react-app/config/Identifier/{page.register.ts → pages/page.register.ts} +37 -25
  144. package/dist/templates/react-app/config/Identifier/{page.request.ts → pages/page.request.ts} +34 -44
  145. package/dist/templates/react-app/config/app.router.ts +81 -61
  146. package/dist/templates/react-app/config/i18n/PageI18nInterface.ts +51 -0
  147. package/dist/templates/react-app/config/i18n/aboutI18n.ts +42 -0
  148. package/dist/templates/react-app/config/i18n/chatMessageI18n.ts +17 -0
  149. package/dist/templates/react-app/config/i18n/executorI18n.ts +51 -0
  150. package/dist/templates/react-app/config/i18n/homeI18n.ts +24 -0
  151. package/dist/templates/react-app/config/i18n/i18nConfig.ts +30 -0
  152. package/dist/templates/react-app/config/i18n/identifiter18n.ts +30 -0
  153. package/dist/templates/react-app/config/i18n/jsonStorage18n.ts +27 -0
  154. package/dist/templates/react-app/config/i18n/login18n.ts +42 -0
  155. package/dist/templates/react-app/config/i18n/messageBaseListI18n.ts +22 -0
  156. package/dist/templates/react-app/config/i18n/messageI18n.ts +14 -0
  157. package/dist/templates/react-app/config/i18n/notFoundI18n.ts +34 -0
  158. package/dist/templates/react-app/config/i18n/register18n.ts +40 -0
  159. package/dist/templates/react-app/config/i18n/request18n.ts +41 -0
  160. package/dist/templates/react-app/config/theme.ts +14 -4
  161. package/dist/templates/react-app/docs/en/bootstrap.md +1670 -341
  162. package/dist/templates/react-app/docs/en/components/chat-message-component.md +314 -0
  163. package/dist/templates/react-app/docs/en/components/chat-message-refactor.md +270 -0
  164. package/dist/templates/react-app/docs/en/components/message-base-list-component.md +172 -0
  165. package/dist/templates/react-app/docs/en/development-guide.md +1021 -345
  166. package/dist/templates/react-app/docs/en/env.md +1132 -278
  167. package/dist/templates/react-app/docs/en/i18n.md +858 -147
  168. package/dist/templates/react-app/docs/en/index.md +733 -104
  169. package/dist/templates/react-app/docs/en/ioc.md +1228 -287
  170. package/dist/templates/react-app/docs/en/playwright/e2e-tests.md +321 -0
  171. package/dist/templates/react-app/docs/en/playwright/index.md +19 -0
  172. package/dist/templates/react-app/docs/en/playwright/installation-summary.md +332 -0
  173. package/dist/templates/react-app/docs/en/playwright/overview.md +222 -0
  174. package/dist/templates/react-app/docs/en/playwright/quickstart.md +325 -0
  175. package/dist/templates/react-app/docs/en/playwright/reorganization-notes.md +340 -0
  176. package/dist/templates/react-app/docs/en/playwright/setup-complete.md +290 -0
  177. package/dist/templates/react-app/docs/en/playwright/testing-guide.md +565 -0
  178. package/dist/templates/react-app/docs/en/store.md +1194 -184
  179. package/dist/templates/react-app/docs/en/why-no-globals.md +797 -0
  180. package/dist/templates/react-app/docs/zh/bootstrap.md +1670 -341
  181. package/dist/templates/react-app/docs/zh/components/chat-message-component.md +314 -0
  182. package/dist/templates/react-app/docs/zh/components/chat-message-refactor.md +270 -0
  183. package/dist/templates/react-app/docs/zh/components/message-base-list-component.md +172 -0
  184. package/dist/templates/react-app/docs/zh/development-guide.md +1021 -345
  185. package/dist/templates/react-app/docs/zh/env.md +1132 -275
  186. package/dist/templates/react-app/docs/zh/i18n.md +858 -147
  187. package/dist/templates/react-app/docs/zh/index.md +717 -104
  188. package/dist/templates/react-app/docs/zh/ioc.md +1229 -287
  189. package/dist/templates/react-app/docs/zh/playwright/e2e-tests.md +321 -0
  190. package/dist/templates/react-app/docs/zh/playwright/index.md +19 -0
  191. package/dist/templates/react-app/docs/zh/playwright/installation-summary.md +332 -0
  192. package/dist/templates/react-app/docs/zh/playwright/overview.md +222 -0
  193. package/dist/templates/react-app/docs/zh/playwright/quickstart.md +325 -0
  194. package/dist/templates/react-app/docs/zh/playwright/reorganization-notes.md +340 -0
  195. package/dist/templates/react-app/docs/zh/playwright/setup-complete.md +290 -0
  196. package/dist/templates/react-app/docs/zh/playwright/testing-guide.md +565 -0
  197. package/dist/templates/react-app/docs/zh/store.md +1192 -184
  198. package/dist/templates/react-app/docs/zh/why-no-globals.md +797 -0
  199. package/dist/templates/react-app/e2e/App.spec.ts +319 -0
  200. package/dist/templates/react-app/e2e/fixtures/base.fixture.ts +40 -0
  201. package/dist/templates/react-app/e2e/main.spec.ts +20 -0
  202. package/dist/templates/react-app/e2e/utils/test-helpers.ts +19 -0
  203. package/dist/templates/react-app/eslint.config.mjs +247 -0
  204. package/dist/templates/react-app/makes/eslint-utils.mjs +195 -0
  205. package/dist/templates/react-app/makes/generateTs2LocalesOptions.ts +26 -0
  206. package/dist/templates/react-app/package.json +31 -3
  207. package/dist/templates/react-app/playwright.config.ts +79 -0
  208. package/dist/templates/react-app/public/locales/en/common.json +233 -179
  209. package/dist/templates/react-app/public/locales/zh/common.json +233 -179
  210. package/dist/templates/react-app/src/App.tsx +15 -42
  211. package/dist/templates/react-app/src/base/apis/AiApi.ts +5 -5
  212. package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +1 -1
  213. package/dist/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +1 -1
  214. package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +8 -8
  215. package/dist/templates/react-app/src/base/apis/feApi/FeApiType.ts +1 -1
  216. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +6 -6
  217. package/dist/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +1 -1
  218. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +12 -14
  219. package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +1 -1
  220. package/dist/templates/react-app/src/base/cases/DialogHandler.ts +5 -2
  221. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +3 -3
  222. package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +3 -3
  223. package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +2 -2
  224. package/dist/templates/react-app/src/base/cases/RequestLogger.ts +4 -4
  225. package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +1 -1
  226. package/dist/templates/react-app/src/base/cases/ResourceState.ts +23 -0
  227. package/dist/templates/react-app/src/base/cases/RouterLoader.ts +4 -4
  228. package/dist/templates/react-app/src/base/cases/TranslateI18nInterface.ts +26 -0
  229. package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +2 -3
  230. package/dist/templates/react-app/src/base/port/I18nServiceInterface.ts +1 -1
  231. package/dist/templates/react-app/src/base/port/IOCInterface.ts +36 -0
  232. package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +2 -1
  233. package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +1 -1
  234. package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +2 -2
  235. package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +9 -5
  236. package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +1 -1
  237. package/dist/templates/react-app/src/base/services/I18nService.ts +29 -29
  238. package/dist/templates/react-app/src/base/services/IdentifierService.ts +143 -0
  239. package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +3 -3
  240. package/dist/templates/react-app/src/base/services/RouteService.ts +27 -8
  241. package/dist/templates/react-app/src/base/services/UserService.ts +8 -8
  242. package/dist/templates/react-app/src/base/types/Page.ts +14 -2
  243. package/dist/templates/react-app/src/base/types/global.d.ts +1 -1
  244. package/dist/templates/react-app/src/core/IOC.ts +5 -46
  245. package/dist/templates/react-app/src/core/bootstraps/{BootstrapApp.ts → BootstrapClient.ts} +44 -17
  246. package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +14 -7
  247. package/dist/templates/react-app/src/core/bootstraps/IocIdentifierTest.ts +1 -1
  248. package/dist/templates/react-app/src/core/bootstraps/PrintBootstrap.ts +1 -1
  249. package/dist/templates/react-app/src/core/clientIoc/ClientIOC.ts +40 -0
  250. package/dist/templates/react-app/src/core/{IocRegisterImpl.ts → clientIoc/ClientIOCRegister.ts} +35 -24
  251. package/dist/templates/react-app/src/core/globals.ts +9 -9
  252. package/dist/templates/react-app/src/main.tsx +4 -4
  253. package/dist/templates/react-app/src/pages/404.tsx +6 -3
  254. package/dist/templates/react-app/src/pages/500.tsx +5 -2
  255. package/dist/templates/react-app/src/pages/NoRouteFound.tsx +5 -0
  256. package/dist/templates/react-app/src/pages/auth/Layout.tsx +9 -6
  257. package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +46 -56
  258. package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +46 -58
  259. package/dist/templates/react-app/src/pages/base/AboutPage.tsx +35 -40
  260. package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +51 -51
  261. package/dist/templates/react-app/src/pages/base/HomePage.tsx +14 -15
  262. package/dist/templates/react-app/src/pages/base/IdentifierPage.tsx +70 -11
  263. package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +24 -25
  264. package/dist/templates/react-app/src/pages/base/Layout.tsx +2 -2
  265. package/dist/templates/react-app/src/pages/base/MessagePage.tsx +40 -0
  266. package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +3 -2
  267. package/dist/templates/react-app/src/pages/base/RequestPage.tsx +41 -59
  268. package/dist/templates/react-app/src/styles/css/antd-themes/{_default.css → _common/_default.css} +85 -0
  269. package/dist/templates/react-app/src/styles/css/antd-themes/{dark.css → _common/dark.css} +99 -0
  270. package/dist/templates/react-app/src/styles/css/antd-themes/_common/index.css +3 -0
  271. package/dist/templates/react-app/src/styles/css/antd-themes/{pink.css → _common/pink.css} +86 -0
  272. package/dist/templates/react-app/src/styles/css/antd-themes/index.css +4 -3
  273. package/dist/templates/react-app/src/styles/css/antd-themes/menu/_default.css +108 -0
  274. package/dist/templates/react-app/src/styles/css/antd-themes/menu/dark.css +67 -0
  275. package/dist/templates/react-app/src/styles/css/antd-themes/menu/index.css +3 -0
  276. package/dist/templates/react-app/src/styles/css/antd-themes/menu/pink.css +67 -0
  277. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/_default.css +34 -0
  278. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/dark.css +31 -0
  279. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/index.css +3 -0
  280. package/dist/templates/react-app/src/styles/css/antd-themes/pagination/pink.css +36 -0
  281. package/dist/templates/react-app/src/styles/css/antd-themes/table/_default.css +44 -0
  282. package/dist/templates/react-app/src/styles/css/antd-themes/table/dark.css +43 -0
  283. package/dist/templates/react-app/src/styles/css/antd-themes/table/index.css +3 -0
  284. package/dist/templates/react-app/src/styles/css/antd-themes/table/pink.css +43 -0
  285. package/dist/templates/react-app/src/styles/css/page.css +4 -3
  286. package/dist/templates/react-app/src/styles/css/themes/_default.css +1 -0
  287. package/dist/templates/react-app/src/styles/css/themes/dark.css +1 -0
  288. package/dist/templates/react-app/src/styles/css/themes/pink.css +1 -0
  289. package/dist/templates/react-app/src/styles/css/zIndex.css +1 -1
  290. package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +3 -3
  291. package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +2 -2
  292. package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +1 -1
  293. package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +3 -3
  294. package/dist/templates/react-app/src/uikit/components/AppRouterProvider.tsx +35 -0
  295. package/dist/templates/react-app/src/uikit/components/BaseHeader.tsx +15 -11
  296. package/dist/templates/react-app/src/uikit/components/BaseRouteProvider.tsx +14 -11
  297. package/dist/templates/react-app/src/uikit/components/BaseRouteSeo.tsx +18 -0
  298. package/dist/templates/react-app/src/uikit/components/BootstrapsProvider.tsx +13 -0
  299. package/dist/templates/react-app/src/uikit/components/ClientSeo.tsx +62 -0
  300. package/dist/templates/react-app/src/uikit/components/ComboProvider.tsx +38 -0
  301. package/dist/templates/react-app/src/uikit/components/LanguageSwitcher.tsx +48 -27
  302. package/dist/templates/react-app/src/uikit/components/Loading.tsx +4 -2
  303. package/dist/templates/react-app/src/uikit/components/LocaleLink.tsx +4 -5
  304. package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +34 -11
  305. package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +240 -0
  306. package/dist/templates/react-app/src/uikit/components/ProcessExecutorProvider.tsx +9 -5
  307. package/dist/templates/react-app/src/uikit/components/RouterRenderComponent.tsx +6 -3
  308. package/dist/templates/react-app/src/uikit/components/ThemeSwitcher.tsx +97 -40
  309. package/dist/templates/react-app/src/uikit/components/UserAuthProvider.tsx +5 -5
  310. package/dist/templates/react-app/src/uikit/components/With.tsx +17 -0
  311. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +176 -0
  312. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatRoot.tsx +21 -0
  313. package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +106 -0
  314. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +271 -0
  315. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageItem.tsx +102 -0
  316. package/dist/templates/react-app/src/uikit/components/chatMessage/MessagesList.tsx +86 -0
  317. package/dist/templates/react-app/src/uikit/contexts/BaseRouteContext.ts +17 -11
  318. package/dist/templates/react-app/src/uikit/contexts/IOCContext.ts +13 -0
  319. package/dist/templates/react-app/src/uikit/hooks/useAppTranslation.ts +26 -0
  320. package/dist/templates/react-app/src/uikit/hooks/useI18nGuard.ts +8 -11
  321. package/dist/templates/react-app/src/uikit/hooks/useI18nInterface.ts +25 -0
  322. package/dist/templates/react-app/src/uikit/hooks/useIOC.ts +35 -0
  323. package/dist/templates/react-app/src/uikit/hooks/useNavigateBridge.ts +3 -3
  324. package/dist/templates/react-app/src/uikit/hooks/useStrictEffect.ts +0 -1
  325. package/dist/templates/react-app/tsconfig.e2e.json +21 -0
  326. package/dist/templates/react-app/tsconfig.json +8 -1
  327. package/dist/templates/react-app/tsconfig.node.json +1 -1
  328. package/dist/templates/react-app/tsconfig.test.json +3 -1
  329. package/dist/templates/react-app/vite.config.ts +50 -34
  330. package/package.json +2 -1
  331. package/dist/configs/react-app/eslint.config.js +0 -94
  332. package/dist/templates/next-app/config/Identifier/common.error.ts +0 -41
  333. package/dist/templates/next-app/config/Identifier/common.ts +0 -69
  334. package/dist/templates/next-app/config/Identifier/page.about.ts +0 -181
  335. package/dist/templates/next-app/config/Identifier/page.admin.ts +0 -48
  336. package/dist/templates/next-app/config/Identifier/page.executor.ts +0 -272
  337. package/dist/templates/next-app/config/Identifier/page.identifiter.ts +0 -39
  338. package/dist/templates/next-app/config/Identifier/page.jsonStorage.ts +0 -72
  339. package/dist/templates/next-app/config/Identifier/page.request.ts +0 -182
  340. package/dist/templates/next-app/src/base/cases/ChatAction.ts +0 -21
  341. package/dist/templates/next-app/src/base/cases/FocusBarAction.ts +0 -36
  342. package/dist/templates/next-app/src/base/cases/RequestState.ts +0 -20
  343. package/dist/templates/next-app/src/base/port/AdminPageInterface.ts +0 -85
  344. package/dist/templates/next-app/src/base/port/AsyncStateInterface.ts +0 -7
  345. package/dist/templates/next-app/src/base/services/AdminUserService.ts +0 -45
  346. package/dist/templates/next-app/src/uikit/components/ChatRoot.tsx +0 -17
  347. package/dist/templates/next-app/src/uikit/components/chat/ChatActionInterface.ts +0 -30
  348. package/dist/templates/next-app/src/uikit/components/chat/ChatFocusBar.tsx +0 -65
  349. package/dist/templates/next-app/src/uikit/components/chat/ChatMessages.tsx +0 -59
  350. package/dist/templates/next-app/src/uikit/components/chat/ChatWrap.tsx +0 -28
  351. package/dist/templates/next-app/src/uikit/components/chat/FocusBarActionInterface.ts +0 -19
  352. package/dist/templates/next-app/src/uikit/hook/useMountedClient.ts +0 -17
  353. package/dist/templates/next-app/src/uikit/hook/useStore.ts +0 -15
  354. package/dist/templates/react-app/__tests__/__mocks__/I18nService.ts +0 -13
  355. package/dist/templates/react-app/__tests__/src/App.test.tsx +0 -139
  356. package/dist/templates/react-app/config/Identifier/page.identifiter.ts +0 -39
  357. package/dist/templates/react-app/config/i18n.ts +0 -15
  358. package/dist/templates/react-app/docs/en/project-structure.md +0 -434
  359. package/dist/templates/react-app/docs/zh/project-structure.md +0 -434
  360. package/dist/templates/react-app/src/base/cases/RequestState.ts +0 -20
  361. package/dist/templates/react-app/src/base/port/AsyncStateInterface.ts +0 -7
  362. package/dist/templates/react-app/src/uikit/hooks/useDocumentTitle.ts +0 -15
  363. package/dist/templates/react-app/src/uikit/hooks/useStore.ts +0 -15
@@ -1,152 +1,568 @@
1
- # Internationalization System
1
+ # Internationalization (i18n)
2
2
 
3
- ## Overview
3
+ ## 📋 Table of Contents
4
4
 
5
- The internationalization system adopts an identifier-alias based approach, combining i18next and TypeScript comments to implement a type-safe, maintainable internationalization solution. Main features:
5
+ - [Core Philosophy](#-core-philosophy) - Never hard-code, use variables only
6
+ - [What is an i18n Key](#-what-is-an-i18n-key) - Unique identifier
7
+ - [Why Use i18n Keys](#-why-use-i18n-keys) - Reduce cognitive burden
8
+ - [Implementation in the Project](#-implementation-in-the-project) - Bootstrap plugin
9
+ - [How to Use](#-how-to-use) - Practical guide
10
+ - [Best Practices](#-best-practices) - 7 core practices
11
+ - [FAQ](#-faq) - Common questions
6
12
 
7
- - **Identifier Aliases**: Use constants instead of strings as translation keys
8
- - **TypeScript Comments**: Automatically generate translation resources through comments
9
- - **Type Safety**: Complete type checking and auto-completion
10
- - **Router Integration**: Support language parameters in URL paths
11
- - **Auto Generation**: Automatically generate translation files from source code
12
- - **Developer Friendly**: Complete development tool support
13
+ ---
13
14
 
14
- ## Core Concepts
15
+ ## 🎯 Core Philosophy
15
16
 
16
- ### 1. Identifier Aliases
17
+ > **🚨 Important Principle: All text, words, and sentences that need to be displayed in the project must use i18n Keys. Hard-coded text is absolutely not allowed!**
17
18
 
18
- Use constants instead of string keys to provide better type safety and maintainability:
19
+ > **⭐ Core Advantage: Developers don't need to remember complex translation strings, just variable names. The IDE will provide auto-completion!**
20
+
21
+ ### Core Concept
22
+
23
+ ```
24
+ ❌ Hard-coded text ✅ i18n Key (variable)
25
+ "Login" → BUTTON_LOGIN (no need to remember 'common:button.login')
26
+ "Welcome back" → MESSAGE_WELCOME (no need to remember 'common:message.welcome')
27
+ "Are you sure?" → CONFIRM_DELETE (no need to remember 'common:confirm.delete')
28
+ ```
29
+
30
+ **Every text has a unique identifier:**
19
31
 
20
32
  ```typescript
21
- // config/Identifier/common.ts
33
+ // ❌ Wrong: Write text directly or use strings
34
+ <button>Login</button>
35
+ <h1>Welcome back</h1>
36
+ <p>{t('common:confirm.delete')}</p> // Don't write strings either
37
+
38
+ // ✅ Correct: Use i18n Key variables
39
+ <button>{t(BUTTON_LOGIN)}</button> // Just remember the variable name
40
+ <h1>{t(MESSAGE_WELCOME)}</h1> // IDE will auto-complete
41
+ <p>{t(CONFIRM_DELETE)}</p> // TypeScript will check spelling
42
+ ```
43
+
44
+ ---
45
+
46
+ ## 🔑 What is an i18n Key
47
+
48
+ An i18n Key is **a unique identifier for each text**, just like everyone has an ID number.
49
+
50
+ ### Basic Concept
51
+
52
+ ```typescript
53
+ // i18n Key definition (in config/Identifier/ directory)
22
54
 
23
55
  /**
24
- * @description Theme switcher default theme label
25
- * @localZh 默认主题
26
- * @localEn Default Theme
56
+ * @description Login button text
57
+ * @localZh 登录
58
+ * @localEn Login
27
59
  */
28
- export const HEADER_THEME_DEFAULT = 'header.theme.default';
60
+ export const BUTTON_LOGIN = 'common:button.login';
61
+ // ↑ Constant name ↑ Identifier string
62
+ // Used in code Key name stored in translation files
29
63
 
30
64
  /**
31
- * @description Theme switcher dark theme label
32
- * @localZh 暗色主题
33
- * @localEn Dark Theme
65
+ * @description Welcome message
66
+ * @localZh 欢迎回来,{{name}}!
67
+ * @localEn Welcome back, {{name}}!
34
68
  */
35
- export const HEADER_THEME_DARK = 'header.theme.dark';
69
+ export const MESSAGE_WELCOME = 'common:message.welcome';
36
70
  ```
37
71
 
38
- ### 2. Auto Generation Configuration
72
+ **Structure explanation:**
73
+
74
+ ```
75
+ 'common:button.login'
76
+ ↑ ↑ ↑
77
+ Namespace Category Specific identifier
78
+ ```
39
79
 
40
- Configure auto generation in `vite.config.ts`:
80
+ ### Naming Conventions
41
81
 
42
82
  ```typescript
43
- import ts2Locales from '@brain-toolkit/ts2locales/vite';
83
+ // Good naming: Clear and structured
84
+ export const BUTTON_LOGIN = 'common:button.login'; // Button text
85
+ export const BUTTON_SUBMIT = 'common:button.submit'; // Button text
86
+ export const MESSAGE_WELCOME = 'common:message.welcome'; // Message text
87
+ export const CONFIRM_DELETE = 'common:confirm.delete'; // Confirm dialog
88
+ export const ERROR_NETWORK = 'common:error.network'; // Error message
89
+ export const PAGE_HOME_TITLE = 'common:page.home.title'; // Page title
90
+
91
+ // ❌ Bad naming: Vague and unstructured
92
+ export const TEXT1 = 'login';
93
+ export const MSG = 'welcome';
94
+ export const DELETE_CONFIRM = 'delete_confirm';
95
+ ```
44
96
 
45
- export default defineConfig({
46
- plugins: [
47
- ts2Locales({
48
- locales: ['en', 'zh'],
49
- options: [
50
- {
51
- source: './config/Identifier/common.ts',
52
- target: './public/locales/{{lng}}/common.json'
53
- },
54
- {
55
- source: './config/Identifier/error.ts',
56
- target: './public/locales/{{lng}}/common.json'
57
- }
58
- ]
59
- })
60
- ]
61
- });
97
+ ---
98
+
99
+ ## 🤔 Why Use i18n Keys
100
+
101
+ ### Problem: Pain Points of Hard-coded Text
102
+
103
+ ```typescript
104
+ // ❌ Traditional approach: Hard-coded text
105
+
106
+ function LoginPage() {
107
+ return (
108
+ <div>
109
+ <h1>Login</h1>
110
+ <button>Login</button>
111
+ <p>Welcome back!</p>
112
+ <span>Forgot password?</span>
113
+ </div>
114
+ );
115
+ }
116
+
117
+ // 😰 Problem 1: Difficult to internationalize
118
+ // If we need to support Chinese, need to modify lots of code
119
+
120
+ // 😰 Problem 2: Hard to maintain
121
+ // Same text might be used in multiple places, easy to miss when changing
122
+
123
+ // 😰 Problem 3: Hard to manage uniformly
124
+ // Can't count how many texts exist in the project, which need translation
125
+
126
+ // 😰 Problem 4: Hard to search
127
+ // To find where a text is used, can only globally search strings
128
+ ```
129
+
130
+ ### Solution: Use i18n Keys
131
+
132
+ ```typescript
133
+ // ✅ Use i18n Keys
134
+
135
+ import { useAppTranslation } from '@/uikit/hooks/useAppTranslation';
136
+ import {
137
+ PAGE_LOGIN_TITLE,
138
+ BUTTON_LOGIN,
139
+ MESSAGE_WELCOME,
140
+ LINK_FORGOT_PASSWORD
141
+ } from '@config/Identifier';
142
+
143
+ function LoginPage() {
144
+ const { t } = useAppTranslation();
145
+
146
+ return (
147
+ <div>
148
+ <h1>{t(PAGE_LOGIN_TITLE)}</h1>
149
+ <button>{t(BUTTON_LOGIN)}</button>
150
+ <p>{t(MESSAGE_WELCOME)}</p>
151
+ <span>{t(LINK_FORGOT_PASSWORD)}</span>
152
+ </div>
153
+ );
154
+ }
155
+
156
+ // ✅ Advantage 1: Automatic internationalization
157
+ // Automatically displays corresponding text based on user language
158
+
159
+ // ✅ Advantage 2: Centralized management
160
+ // All text managed uniformly in Identifier files
161
+
162
+ // ✅ Advantage 3: Easy to maintain
163
+ // Only need to modify in one place
164
+
165
+ // ✅ Advantage 4: Type safe
166
+ // TypeScript will check if Key exists
167
+
168
+ // ✅ Advantage 5: Reduce thinking ⭐
169
+ // Developers only need to know BUTTON_LOGIN is a variable
170
+ // Don't need to remember 'common:button.login' string
171
+ // IDE will provide auto-completion, wrong spelling will immediately error
172
+ ```
173
+
174
+ ### Comparison Summary
175
+
176
+ | Feature | Hard-coded Text | i18n Key |
177
+ | ------------------------ | ---------------------------------- | ------------------------------------ |
178
+ | **Internationalization** | ❌ Difficult (need to change code) | ✅ Automatic (just switch language) |
179
+ | **Maintainability** | ❌ Poor (scattered everywhere) | ✅ Good (centralized management) |
180
+ | **Reusability** | ❌ Poor (copy-paste) | ✅ Good (reference Key) |
181
+ | **Searchability** | ❌ Difficult (string search) | ✅ Simple (search constant) |
182
+ | **Countability** | ❌ Impossible | ✅ Easy (count Keys) |
183
+ | **Type Safety** | ❌ None | ✅ Yes (TypeScript) |
184
+ | **Cognitive Burden** | ❌ High (need to remember text) | ✅ Low (just remember variable name) |
185
+ | **IDE Support** | ❌ No auto-complete | ✅ Full auto-complete |
186
+
187
+ ### ⭐ Core Advantage: Reduce Developer Thinking
188
+
189
+ **The most important advantage: Developers don't need to care about what the actual i18n string is!**
190
+
191
+ ```typescript
192
+ // ❌ Traditional approach: Need to remember complex strings
193
+ function LoginPage() {
194
+ const { t } = useTranslation();
195
+
196
+ return (
197
+ <div>
198
+ {/* 😰 Need to remember 'common:button.login' */}
199
+ <button>{t('common:button.login')}</button>
200
+
201
+ {/* 😰 Need to remember 'page.login.title' */}
202
+ <h1>{t('page.login.title')}</h1>
203
+
204
+ {/* 😰 Spelling mistake won't error */}
205
+ <p>{t('page.login.welcom')}</p> {/* welcom → welcome, spelling error */}
206
+ </div>
207
+ );
208
+ }
209
+
210
+ // ✅ i18n Key approach: Just need to know variable name
211
+ import { BUTTON_LOGIN, PAGE_LOGIN_TITLE, PAGE_LOGIN_WELCOME } from '@config/Identifier';
212
+
213
+ function LoginPage() {
214
+ const { t } = useAppTranslation();
215
+
216
+ return (
217
+ <div>
218
+ {/* ✅ Just remember BUTTON_LOGIN, IDE will auto-complete */}
219
+ <button>{t(BUTTON_LOGIN)}</button>
220
+
221
+ {/* ✅ Type PAGE_ and IDE will show all available Keys */}
222
+ <h1>{t(PAGE_LOGIN_TITLE)}</h1>
223
+
224
+ {/* ✅ Wrong spelling will immediately error in TypeScript */}
225
+ <p>{t(PAGE_LOGIN_WELCOM)}</p> {/* ❌ TS error: Variable not found */}
226
+ </div>
227
+ );
228
+ }
229
+ ```
230
+
231
+ **Development Experience Comparison:**
232
+
233
+ ```typescript
234
+ // ❌ Using strings workflow:
235
+ // 1. 😰 Check translation files, find corresponding key
236
+ // 2. 😰 Remember complete key path (like 'common:page.login.title')
237
+ // 3. 😰 Manually type the string in code
238
+ // 4. 😰 May type incorrectly, but compiler won't error
239
+ // 5. 😰 Only discover translation didn't work at runtime
240
+
241
+ // ✅ Using i18n Key workflow:
242
+ // 1. 😊 Type variable name prefix (like BUTTON_)
243
+ // 2. 😊 IDE automatically suggests all available Keys
244
+ // 3. 😊 Select needed Key, IDE auto-completes
245
+ // 4. 😊 If typed incorrectly, TypeScript immediately errors
246
+ // 5. 😊 Can ensure Key correctness at compile time
247
+ ```
248
+
249
+ **Cognitive Burden Comparison:**
250
+
251
+ | What Developers Need to Remember | String Method | i18n Key Method |
252
+ | -------------------------------- | --------------------------------------------- | ------------------------------ |
253
+ | **Translation File Structure** | ✅ Must remember (like `common:button.login`) | ❌ Don't need to |
254
+ | **Namespace** | ✅ Must remember (like `common:`, `page:`) | ❌ Don't need to |
255
+ | **String Path** | ✅ Must remember complete path | ❌ Don't need to |
256
+ | **Variable Name** | ❌ No variable | ✅ Just remember variable name |
257
+ | **IDE Hints** | ❌ None | ✅ Full hints |
258
+
259
+ **Real Development Scenarios:**
260
+
261
+ ```typescript
262
+ // Scenario 1: Write a new button
263
+
264
+ // ❌ String method (need to think a lot)
265
+ // 1. What should this button's translation key be called?
266
+ // 2. Which namespace should it go in? common? page?
267
+ // 3. What should the path be? button.submit? submit.button?
268
+ // 4. Finally write: t('common:button.submit')
269
+ <button>{t('common:button.submit')}</button>
270
+
271
+ // ✅ i18n Key method (just need to search)
272
+ // 1. Type BUTTON_
273
+ // 2. IDE shows all available button Keys
274
+ // 3. See BUTTON_SUBMIT, select it
275
+ // 4. Done!
276
+ <button>{t(BUTTON_SUBMIT)}</button>
277
+
278
+ // Scenario 2: Change text on another page
279
+
280
+ // ❌ String method
281
+ // 1. Check that page's code
282
+ // 2. Find t('page.home.welcome')
283
+ // 3. Remember this string
284
+ // 4. Search and modify in translation files
285
+
286
+ // ✅ i18n Key method
287
+ // 1. See PAGE_HOME_WELCOME in code
288
+ // 2. Jump directly to definition (IDE's Go to Definition)
289
+ // 3. Modify translation in comment
290
+ // 4. Automatically generate new translation files
291
+ ```
292
+
293
+ **Summary:**
294
+
295
+ Using i18n Keys allows developers to:
296
+
297
+ - ✅ **Don't need to remember** complex string paths
298
+ - ✅ **Don't need to remember** translation file structure
299
+ - ✅ **Don't need to care about** specific translation key names
300
+ - ✅ **Just need to know** this is a variable
301
+ - ✅ **Rely on IDE** provided auto-complete and type checking
302
+ - ✅ **Focus on** business logic, not translation details
303
+
304
+ > 💡 **Core Philosophy: Let developers put their energy into business logic, not memorizing translation strings!**
305
+
306
+ ---
307
+
308
+ ## 🛠️ Implementation in the Project
309
+
310
+ ### 1. File Structure
311
+
312
+ ```
313
+ config/
314
+ └── Identifier/ # i18n Key definition directory
315
+ ├── index.ts # Export all Keys
316
+ ├── common/ # Common text
317
+ │ ├── index.ts
318
+ │ ├── common.ts # General text (buttons, messages, etc.)
319
+ │ └── common.error.ts # Error messages
320
+ └── pages/ # Page text
321
+ ├── index.ts
322
+ ├── page.home.ts # Home page text
323
+ ├── page.login.ts # Login page text
324
+ └── page.about.ts # About page text
325
+
326
+ public/
327
+ └── locales/ # Generated translation files
328
+ ├── zh/
329
+ │ └── common.json # Chinese translations
330
+ └── en/
331
+ └── common.json # English translations
332
+
333
+ src/
334
+ └── uikit/
335
+ └── hooks/
336
+ └── useAppTranslation.ts # Translation Hook
62
337
  ```
63
338
 
64
- ### 3. i18n Service Configuration
339
+ ### 2. i18n Configuration
65
340
 
66
341
  ```typescript
67
- // config/i18n.ts
68
- export default {
69
- fallbackLng: 'en',
342
+ // config/i18n/i18nConfig.ts
343
+ export const i18nConfig = {
344
+ fallbackLng: 'en', // Default language
70
345
  debug: false,
71
346
  interpolation: {
72
347
  escapeValue: false
73
348
  },
74
- ns: ['common'],
349
+ ns: ['common'], // Namespaces
75
350
  defaultNS: 'common',
76
351
  backend: {
77
- loadPath: '/locales/{{lng}}/{{ns}}.json'
352
+ loadPath: '/locales/{{lng}}/{{ns}}.json' // Translation file path
78
353
  },
79
- supportedLngs: ['en', 'zh']
354
+ supportedLngs: ['en', 'zh'] // Supported languages
80
355
  } as const;
81
356
  ```
82
357
 
83
- ## Usage
358
+ ### 3. I18nService (Bootstrap Plugin)
84
359
 
85
- ### 1. Define Translation Keys
360
+ ```typescript
361
+ // src/base/services/I18nService.ts
362
+ export class I18nService implements BootstrapExecutorPlugin {
363
+ readonly pluginName = 'I18nService';
364
+
365
+ constructor(protected pathname: string) {
366
+ super(() => new I18nServiceState(i18n.language));
367
+ }
368
+
369
+ /**
370
+ * Initialize i18n on Bootstrap startup
371
+ */
372
+ onBefore(): void {
373
+ i18n
374
+ .use(HttpApi) // Load translation files
375
+ .use(LanguageDetector) // Language detection
376
+ .use(initReactI18next) // React integration
377
+ .init(i18nConfig); // Initialize config
378
+
379
+ // Add custom language detector (detect from URL path)
380
+ const pathLanguageDetector = {
381
+ name: 'pathLanguageDetector',
382
+ lookup: () => {
383
+ const paths = this.pathname.split('/');
384
+ for (const path of paths) {
385
+ if (this.isValidLanguage(path)) {
386
+ return path; // Extract language from URL (like /zh/home)
387
+ }
388
+ }
389
+ return fallbackLng;
390
+ },
391
+ cacheUserLanguage(lng: string) {
392
+ localStorage.setItem('i18nextLng', lng);
393
+ }
394
+ };
395
+
396
+ i18n.services.languageDetector.addDetector(pathLanguageDetector);
397
+ }
398
+
399
+ /**
400
+ * Switch language
401
+ */
402
+ async changeLanguage(language: string): Promise<void> {
403
+ await i18n.changeLanguage(language);
404
+ localStorage.setItem('i18nextLng', language);
405
+ }
406
+
407
+ /**
408
+ * Translate text
409
+ */
410
+ t(key: string, params?: Record<string, unknown>): string {
411
+ return i18n.t(key, { lng: i18n.language, ...params });
412
+ }
413
+ }
414
+ ```
415
+
416
+ ### 4. Auto-generate Translation Files
86
417
 
87
418
  ```typescript
88
- // config/Identifier/page.ts
419
+ // vite.config.ts
420
+ import ts2Locales from '@brain-toolkit/ts2locales/vite';
421
+
422
+ export default defineConfig({
423
+ plugins: [
424
+ // ✅ ts2locales plugin: Auto-generate translation files from TypeScript comments
425
+ ts2Locales({
426
+ locales: ['en', 'zh'],
427
+ options: generateTs2LocalesOptions() // Configure generation rules
428
+ })
429
+ ]
430
+ });
431
+ ```
432
+
433
+ **How it works:**
434
+
435
+ ```typescript
436
+ // 1. Define Key in Identifier file
437
+ /**
438
+ * @description Login button text
439
+ * @localZh 登录
440
+ * @localEn Login
441
+ */
442
+ export const BUTTON_LOGIN = 'common:button.login';
443
+
444
+ // 2. ts2locales plugin automatically generates translation files
445
+
446
+ // public/locales/zh/common.json
447
+ {
448
+ "button": {
449
+ "login": "登录"
450
+ }
451
+ }
452
+
453
+ // public/locales/en/common.json
454
+ {
455
+ "button": {
456
+ "login": "Login"
457
+ }
458
+ }
459
+ ```
460
+
461
+ ---
462
+
463
+ ## 📝 How to Use
464
+
465
+ ### 1. Define i18n Key
466
+
467
+ ```typescript
468
+ // config/Identifier/pages/page.home.ts
89
469
 
90
470
  /**
91
471
  * @description Home page title
92
472
  * @localZh 首页
93
473
  * @localEn Home
94
474
  */
95
- export const PAGE_HOME_TITLE = 'page.home.title';
475
+ export const PAGE_HOME_TITLE = 'common:page.home.title';
96
476
 
97
477
  /**
98
478
  * @description Home page welcome message
99
- * @localZh 欢迎来到我们的应用
100
- * @localEn Welcome to our application
479
+ * @localZh 欢迎来到我们的应用!
480
+ * @localEn Welcome to our application!
101
481
  */
102
- export const PAGE_HOME_WELCOME = 'page.home.welcome';
482
+ export const PAGE_HOME_WELCOME = 'common:page.home.welcome';
483
+
484
+ /**
485
+ * @description Home page description with user name
486
+ * @localZh 你好,{{name}}!今天是个好日子。
487
+ * @localEn Hello, {{name}}! Have a great day.
488
+ */
489
+ export const PAGE_HOME_GREETING = 'common:page.home.greeting';
103
490
  ```
104
491
 
105
- ### 2. Using in Components
492
+ **Comment conventions:**
493
+
494
+ - `@description`: Explain text purpose (English)
495
+ - `@localZh`: Chinese translation
496
+ - `@localEn`: English translation
106
497
 
107
- ```tsx
108
- import { useTranslation } from 'react-i18next';
109
- import * as i18nKeys from '@config/Identifier/page';
498
+ ### 2. Use in UI Components
499
+
500
+ ```typescript
501
+ // src/pages/base/HomePage.tsx
502
+ import { useAppTranslation } from '@/uikit/hooks/useAppTranslation';
503
+ import {
504
+ PAGE_HOME_TITLE,
505
+ PAGE_HOME_WELCOME,
506
+ PAGE_HOME_GREETING
507
+ } from '@config/Identifier';
110
508
 
111
509
  function HomePage() {
112
- const { t } = useTranslation();
510
+ const { t } = useAppTranslation();
511
+ const userName = 'John';
113
512
 
114
513
  return (
115
514
  <div>
116
- <h1>{t(i18nKeys.PAGE_HOME_TITLE)}</h1>
117
- <p>{t(i18nKeys.PAGE_HOME_WELCOME)}</p>
515
+ {/* ✅ Simple text */}
516
+ <h1>{t(PAGE_HOME_TITLE)}</h1>
517
+ <p>{t(PAGE_HOME_WELCOME)}</p>
518
+
519
+ {/* ✅ Text with parameters */}
520
+ <p>{t(PAGE_HOME_GREETING, { name: userName })}</p>
118
521
  </div>
119
522
  );
120
523
  }
121
524
  ```
122
525
 
123
- ### 3. Translations with Parameters
526
+ ### 3. Use in Services
124
527
 
125
528
  ```typescript
126
- /**
127
- * @description Welcome user message
128
- * @localZh 欢迎,{{name}}!
129
- * @localEn Welcome, {{name}}!
130
- */
131
- export const USER_WELCOME = 'user.welcome';
132
-
133
- function Welcome({ username }: { username: string }) {
134
- const { t } = useTranslation();
135
- return <h1>{t(i18nKeys.USER_WELCOME, { name: username })}</h1>;
529
+ // src/base/services/UserService.ts
530
+ import { injectable, inject } from 'inversify';
531
+ import { I18nServiceInterface } from '@/base/port/I18nServiceInterface';
532
+ import { ERROR_USER_NOT_FOUND } from '@config/Identifier';
533
+
534
+ @injectable()
535
+ export class UserService {
536
+ constructor(
537
+ @inject(IOCIdentifier.I18nServiceInterface)
538
+ private i18n: I18nServiceInterface
539
+ ) {}
540
+
541
+ async getUser(id: string) {
542
+ const user = await this.api.getUserById(id);
543
+
544
+ if (!user) {
545
+ // ✅ Use i18n in service
546
+ throw new Error(this.i18n.t(ERROR_USER_NOT_FOUND, { id }));
547
+ }
548
+
549
+ return user;
550
+ }
136
551
  }
137
552
  ```
138
553
 
139
- ### 4. Language Switching
554
+ ### 4. Switch Language
140
555
 
141
- ```tsx
142
- import { IOC } from '@/core/IOC';
143
- import { I18nService } from '@/base/services/I18nService';
556
+ ```typescript
557
+ // src/uikit/components/LanguageSwitcher.tsx
558
+ import { useIOC } from '@/uikit/hooks/useIOC';
144
559
 
145
560
  function LanguageSwitcher() {
146
- const i18nService = IOC(I18nService);
561
+ const i18nService = useIOC('I18nServiceInterface');
147
562
  const currentLang = i18nService.getCurrentLanguage();
148
563
 
149
- const handleChange = (lang: string) => {
564
+ const handleChange = (lang: 'zh' | 'en') => {
565
+ // ✅ Switch language
150
566
  i18nService.changeLanguage(lang);
151
567
  };
152
568
 
@@ -159,110 +575,405 @@ function LanguageSwitcher() {
159
575
  }
160
576
  ```
161
577
 
162
- ## Best Practices
578
+ ### 5. Complex Scenarios
163
579
 
164
- ### 1. Identifier Organization
580
+ #### Scenario 1: Dynamic Text
165
581
 
166
- - **Naming Conventions**:
582
+ ```typescript
583
+ /**
584
+ * @description Upload progress message
585
+ * @localZh 已上传 {{current}} / {{total}} 个文件
586
+ * @localEn Uploaded {{current}} / {{total}} files
587
+ */
588
+ export const UPLOAD_PROGRESS = 'common:upload.progress';
167
589
 
168
- ```typescript
169
- // Page related
170
- PAGE_HOME_TITLE;
171
- PAGE_ABOUT_DESCRIPTION;
590
+ // Usage
591
+ <p>{t(UPLOAD_PROGRESS, { current: 3, total: 10 })}</p>
592
+ // Chinese: 已上传 3 / 10 个文件
593
+ // English: Uploaded 3 / 10 files
594
+ ```
172
595
 
173
- // Feature module related
174
- AUTH_LOGIN_BUTTON;
175
- AUTH_LOGOUT_CONFIRM;
596
+ #### Scenario 2: Plural Forms
176
597
 
177
- // Common component related
178
- COMMON_SUBMIT_BUTTON;
179
- COMMON_CANCEL_BUTTON;
180
- ```
598
+ ```typescript
599
+ /**
600
+ * @description Files count message
601
+ * @localZh {{count}} 个文件
602
+ * @localEn {{count}} file_plural
603
+ */
604
+ export const FILES_COUNT = 'common:files.count';
181
605
 
182
- - **File Organization**:
183
- ```
184
- config/
185
- ├── Identifier/
186
- │ ├── common.ts // Common text
187
- │ ├── page.ts // Page text
188
- │ ├── error.ts // Error messages
189
- │ └── auth.ts // Authentication related
190
- ```
606
+ // Usage
607
+ <p>{t(FILES_COUNT, { count: 1 })}</p> // 1 file
608
+ <p>{t(FILES_COUNT, { count: 5 })}</p> // 5 files
609
+ ```
191
610
 
192
- ### 2. Comment Standards
611
+ #### Scenario 3: HTML Content
193
612
 
194
613
  ```typescript
195
614
  /**
196
- * @description Brief description explaining text usage
197
- * @localZh Chinese translation text
198
- * @localEn English translation text
615
+ * @description Terms of service agreement
616
+ * @localZh 我已阅读并同意<a href="/terms">服务条款</a>
617
+ * @localEn I have read and agree to the <a href="/terms">Terms of Service</a>
199
618
  */
619
+ export const TERMS_AGREEMENT = 'common:terms.agreement';
620
+
621
+ // Usage (Need to use Trans component in React)
622
+ import { Trans } from 'react-i18next';
623
+
624
+ <Trans i18nKey={TERMS_AGREEMENT}>
625
+ I have read and agree to the <a href="/terms">Terms of Service</a>
626
+ </Trans>
627
+ ```
628
+
629
+ ---
630
+
631
+ ## 💎 Best Practices
632
+
633
+ ### 1. ✅ All Text Uses i18n Keys
634
+
635
+ ```typescript
636
+ // ❌ Wrong: Mix hard-coded and i18n Keys
637
+ function LoginForm() {
638
+ return (
639
+ <form>
640
+ <h1>{t(PAGE_LOGIN_TITLE)}</h1>
641
+ <button>Login</button> {/* ❌ Hard-coded */}
642
+ <a href="/forgot">Forgot password?</a> {/* ❌ Hard-coded */}
643
+ </form>
644
+ );
645
+ }
646
+
647
+ // ✅ Correct: All text uses i18n Keys
648
+ function LoginForm() {
649
+ return (
650
+ <form>
651
+ <h1>{t(PAGE_LOGIN_TITLE)}</h1>
652
+ <button>{t(BUTTON_LOGIN)}</button> {/* ✅ Use Key */}
653
+ <a href="/forgot">{t(LINK_FORGOT_PASSWORD)}</a> {/* ✅ Use Key */}
654
+ </form>
655
+ );
656
+ }
200
657
  ```
201
658
 
202
- ### 3. Type Safety
659
+ ### 2. Organize i18n Keys Reasonably
203
660
 
204
661
  ```typescript
205
- // Use type imports to ensure key existence
206
- import * as i18nKeys from '@config/Identifier';
662
+ // Good organization: Categorize by functional modules
663
+ config/Identifier/
664
+ ├── common/
665
+ │ ├── common.ts # General text (buttons, labels, etc.)
666
+ │ └── common.error.ts # Error messages
667
+ ├── pages/
668
+ │ ├── page.home.ts # Home page text
669
+ │ ├── page.login.ts # Login page text
670
+ │ └── page.about.ts # About page text
671
+ └── components/
672
+ ├── component.header.ts # Header component text
673
+ └── component.footer.ts # Footer component text
674
+ ```
675
+
676
+ ### 3. ✅ Use Semantic Naming
207
677
 
208
- // Type checking catches incorrect keys
209
- t(i18nKeys.NONEXISTENT_KEY); // TS error
678
+ ```typescript
679
+ // Good naming: Clearly expresses meaning
680
+ export const BUTTON_SUBMIT = 'common:button.submit';
681
+ export const BUTTON_CANCEL = 'common:button.cancel';
682
+ export const ERROR_NETWORK = 'common:error.network';
683
+ export const MESSAGE_SUCCESS = 'common:message.success';
684
+
685
+ // ❌ Bad naming: Unclear meaning
686
+ export const BTN1 = 'btn1';
687
+ export const TEXT = 'text';
688
+ export const MSG = 'msg';
210
689
  ```
211
690
 
212
- ### 4. Dynamic Content
691
+ ### 4. Add Clear Comments to i18n Keys
213
692
 
214
693
  ```typescript
694
+ // ✅ Good comments: Clearly explain purpose and context
695
+ /**
696
+ * @description Confirmation message when user tries to delete an item
697
+ * @localZh 确定要删除 {{itemName}} 吗?此操作不可撤销。
698
+ * @localEn Are you sure you want to delete {{itemName}}? This action cannot be undone.
699
+ */
700
+ export const CONFIRM_DELETE_ITEM = 'common:confirm.delete.item';
701
+
702
+ // ❌ Bad comments: No context information
215
703
  /**
216
- * @description File upload progress
217
- * @localZh 已上传 {{count}} 个文件,共 {{total}} 个
218
- * @localEn Uploaded {{count}} files out of {{total}}
704
+ * @description Delete
705
+ * @localZh 删除
706
+ * @localEn Delete
219
707
  */
220
- export const UPLOAD_PROGRESS = 'upload.progress';
708
+ export const DELETE = 'delete';
709
+ ```
710
+
711
+ ### 5. ✅ Unified Naming Conventions
712
+
713
+ ```typescript
714
+ // ✅ Recommended naming conventions:
715
+
716
+ // Button text
717
+ export const BUTTON_LOGIN = 'common:button.login';
718
+ export const BUTTON_SUBMIT = 'common:button.submit';
719
+ export const BUTTON_CANCEL = 'common:button.cancel';
720
+
721
+ // Page titles
722
+ export const PAGE_HOME_TITLE = 'common:page.home.title';
723
+ export const PAGE_ABOUT_TITLE = 'common:page.about.title';
724
+
725
+ // Error messages
726
+ export const ERROR_NETWORK = 'common:error.network';
727
+ export const ERROR_INVALID_INPUT = 'common:error.invalid.input';
728
+
729
+ // Message prompts
730
+ export const MESSAGE_SUCCESS = 'common:message.success';
731
+ export const MESSAGE_WARNING = 'common:message.warning';
732
+
733
+ // Confirm dialogs
734
+ export const CONFIRM_DELETE = 'common:confirm.delete';
735
+ export const CONFIRM_LOGOUT = 'common:confirm.logout';
736
+
737
+ // Link text
738
+ export const LINK_FORGOT_PASSWORD = 'common:link.forgot.password';
739
+ export const LINK_PRIVACY_POLICY = 'common:link.privacy.policy';
740
+ ```
741
+
742
+ ### 6. ✅ Avoid Duplicate Definitions
743
+
744
+ ```typescript
745
+ // ❌ Wrong: Duplicate definitions of same text
746
+ // config/Identifier/common/common.ts
747
+ export const BUTTON_OK_1 = 'common:button.ok1';
748
+
749
+ // config/Identifier/pages/page.home.ts
750
+ export const BUTTON_OK_2 = 'common:button.ok2';
751
+
752
+ // ✅ Correct: Define once in common file, reference in multiple places
753
+ // config/Identifier/common/common.ts
754
+ export const BUTTON_OK = 'common:button.ok';
755
+
756
+ // Reference in various pages
757
+ import { BUTTON_OK } from '@config/Identifier';
758
+ ```
759
+
760
+ ### 7. ✅ Use Parameterized Text
761
+
762
+ ```typescript
763
+ // ❌ Bad: Define different Keys for each case
764
+ export const WELCOME_USER_JOHN = 'common:welcome.john';
765
+ export const WELCOME_USER_MARY = 'common:welcome.mary';
766
+
767
+ // ✅ Good: Use parameters
768
+ /**
769
+ * @description Welcome message with user name
770
+ * @localZh 欢迎,{{name}}!
771
+ * @localEn Welcome, {{name}}!
772
+ */
773
+ export const WELCOME_USER = 'common:welcome.user';
221
774
 
222
775
  // Usage
223
- t(i18nKeys.UPLOAD_PROGRESS, { count: 3, total: 10 });
776
+ <h1>{t(WELCOME_USER, { name: 'John' })}</h1>
777
+ <h1>{t(WELCOME_USER, { name: 'Mary' })}</h1>
224
778
  ```
225
779
 
226
- ## Workflow
780
+ ---
227
781
 
228
- 1. **Development Phase**:
229
- - Define translation keys and comments in Identifier files
230
- - Reference translations using identifier aliases in code
231
- - Automatically generate translation files during development server runtime
782
+ ## FAQ
232
783
 
233
- 2. **Build Phase**:
234
- - Automatically check translation completeness
235
- - Generate production translation files
236
- - Optimize translation resource loading
784
+ ### Q1: Why can't I write text directly?
237
785
 
238
- 3. **Runtime**:
239
- - Detect language based on URL
240
- - Load translation resources on demand
241
- - Respond to language switch events
786
+ **A:**
242
787
 
243
- ## Common Issues
788
+ ```typescript
789
+ // ❌ Problems with writing text directly
790
+ <button>Login</button>
244
791
 
245
- ### 1. Translations Not Working
792
+ // Problem 1: Cannot internationalize
793
+ // If user switches to Chinese, text won't change
246
794
 
247
- Check the following:
795
+ // Problem 2: Hard to maintain
796
+ // If want to change "Login" to "Sign In", need to find all places to modify
248
797
 
249
- - Ensure identifiers are correctly exported
250
- - Check if comment format is correct
251
- - Verify translation files are generated
252
- - Confirm language detection is working
798
+ // Problem 3: Cannot manage uniformly
799
+ // Can't know how many "Login" buttons exist in the project
253
800
 
254
- ### 2. Type Errors
801
+ // Advantages of using i18n Key
802
+ <button>{t(BUTTON_LOGIN)}</button>
255
803
 
256
- Possible solutions:
804
+ // ✅ Automatic internationalization: Switch language to automatically show corresponding text
805
+ // ✅ Easy to maintain: Only need to modify definition in one place
806
+ // ✅ Unified management: All text centralized in Identifier files
807
+ ```
808
+
809
+ ### Q2: How to know where a Key is used?
810
+
811
+ **A:**
812
+
813
+ ```bash
814
+ # Search constant name
815
+ grep -r "BUTTON_LOGIN" src/
257
816
 
258
- - Check identifier import paths
259
- - Ensure correct identifier usage
260
- - Update TypeScript type definitions
817
+ # Or use "Find Usages" feature in IDE
818
+ # Can quickly find all places using this Key
819
+ ```
820
+
821
+ ### Q3: What if I forget to define an i18n Key?
261
822
 
262
- ### 3. Performance Optimization
823
+ **A:** TypeScript will error at compile time:
824
+
825
+ ```typescript
826
+ // ❌ Using undefined Key
827
+ <button>{t(BUTTON_NOT_EXIST)}</button>
828
+ // TypeScript error: Cannot find name 'BUTTON_NOT_EXIST'
829
+
830
+ // ✅ Correct: Define Key first
831
+ export const BUTTON_NOT_EXIST = 'common:button.not.exist';
832
+ ```
833
+
834
+ ### Q4: How to handle dynamic text?
835
+
836
+ **A:** Use parameters:
837
+
838
+ ```typescript
839
+ /**
840
+ * @description User greeting with name and time
841
+ * @localZh {{name}},{{time}}好!
842
+ * @localEn Good {{time}}, {{name}}!
843
+ */
844
+ export const GREETING_WITH_TIME = 'common:greeting.with.time';
845
+
846
+ // Usage
847
+ <h1>{t(GREETING_WITH_TIME, { name: 'John', time: 'morning' })}</h1>
848
+ // Chinese: John,morning好!
849
+ // English: Good morning, John!
850
+ ```
851
+
852
+ ### Q5: How are translation files generated?
853
+
854
+ **A:**
855
+
856
+ ```
857
+ 1. Developer defines Keys and translation comments in Identifier files
858
+
859
+ 2. ts2locales plugin scans TypeScript files
860
+
861
+ 3. Extract @localZh and @localEn from comments
862
+
863
+ 4. Auto-generate public/locales/{lng}/common.json
864
+
865
+ 5. i18next loads these JSON files at runtime
866
+ ```
867
+
868
+ ### Q6: Can I use translated text directly in code?
869
+
870
+ **A:**
871
+
872
+ ```typescript
873
+ // ❌ Not recommended: Skip i18n system
874
+ const loginText = 'Login'; // Hard-coded
875
+ <button>{loginText}</button>
876
+
877
+ // ✅ Recommended: Always use i18n Key
878
+ const loginText = t(BUTTON_LOGIN); // Through i18n system
879
+ <button>{loginText}</button>
880
+ ```
881
+
882
+ ### Q7: How to test i18n?
883
+
884
+ **A:**
885
+
886
+ ```typescript
887
+ // __tests__/i18n.test.ts
888
+ import { I18nService } from '@/base/services/I18nService';
889
+ import { BUTTON_LOGIN } from '@config/Identifier';
890
+
891
+ describe('I18n', () => {
892
+ let i18nService: I18nService;
893
+
894
+ beforeEach(() => {
895
+ i18nService = new I18nService('/zh/home');
896
+ i18nService.onBefore();
897
+ });
898
+
899
+ it('should translate to Chinese', () => {
900
+ i18nService.changeLanguage('zh');
901
+ expect(i18nService.t(BUTTON_LOGIN)).toBe('登录');
902
+ });
903
+
904
+ it('should translate to English', () => {
905
+ i18nService.changeLanguage('en');
906
+ expect(i18nService.t(BUTTON_LOGIN)).toBe('Login');
907
+ });
908
+
909
+ it('should support parameters', () => {
910
+ const result = i18nService.t(WELCOME_USER, { name: 'John' });
911
+ expect(result).toContain('John');
912
+ });
913
+ });
914
+ ```
915
+
916
+ ---
917
+
918
+ ## 📚 Related Documentation
919
+
920
+ - [Project Architecture Design](./index.md) - Understand overall architecture
921
+ - [Bootstrap Initializer](./bootstrap.md) - I18nService is one of the Bootstrap plugins
922
+ - [Configuration-Driven Development](./#configuration-driven-development) - i18n Key is a practice of configuration-driven development
923
+
924
+ ---
925
+
926
+ ## 🎉 Summary
927
+
928
+ Core philosophy of the internationalization system:
929
+
930
+ 1. **Unique Identifier** 🔑 - Every text has a unique i18n Key
931
+ 2. **Never Hard-code** 🚫 - All text in project must use i18n Keys
932
+ 3. **Reduce Thinking** 🧠 - Developers only need to know variable names, don't need to remember string paths
933
+ 4. **Centralized Management** 📦 - All Key definitions in Identifier directory
934
+ 5. **Auto-generation** ⚡ - Translation files auto-generated from comments
935
+ 6. **Type Safety** 🔒 - TypeScript provides complete type checking
936
+ 7. **Easy to Maintain** 🛠️ - Only need to modify translation in one place
937
+ 8. **IDE Friendly** 💻 - Complete auto-completion and type hints
938
+
939
+ **Remember two core principles:**
940
+
941
+ 1. **Never write text directly in code!**
942
+ 2. **Developers don't need to remember translation strings, just variable names!**
943
+
944
+ ```typescript
945
+ // ❌ Never do this
946
+ <button>Login</button>
947
+ <h1>Welcome back</h1>
948
+ <p>{t('common:confirm.delete')}</p> // Don't write strings directly either
949
+
950
+ // ✅ Always do this
951
+ <button>{t(BUTTON_LOGIN)}</button>
952
+ <h1>{t(MESSAGE_WELCOME)}</h1>
953
+ <p>{t(CONFIRM_DELETE)}</p> // Use variables, IDE will auto-complete
954
+ ```
955
+
956
+ **Development Workflow:**
957
+
958
+ ```typescript
959
+ // 1. Type variable name prefix
960
+ t(BUTTON_
961
+
962
+ // 2. IDE automatically suggests all available Keys
963
+ // BUTTON_LOGIN
964
+ // BUTTON_SUBMIT
965
+ // BUTTON_CANCEL
966
+ // ...
967
+
968
+ // 3. Select needed Key, done!
969
+ t(BUTTON_LOGIN)
970
+
971
+ // Don't need to remember 'common:button.login'
972
+ // Don't need to care about translation file structure
973
+ // Don't need to worry about spelling errors (TypeScript will check)
974
+ ```
263
975
 
264
- Development suggestions:
976
+ ---
265
977
 
266
- - Reasonably split translation files
267
- - Use translation resource preloading
268
- - Avoid duplicate translation keys
978
+ **Feedback:**
979
+ If you have any questions or suggestions about the internationalization system, please discuss in the team channel or submit an Issue.