@qlover/create-app 1.0.2 → 2.0.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.
- package/CHANGELOG.md +43 -0
- package/dist/index.cjs +9 -9
- package/dist/index.js +9 -9
- package/package.json +4 -3
- package/dist/configs/_common/.editorconfig +0 -23
- package/dist/configs/_common/.env.template +0 -13
- package/dist/configs/_common/.gitattributes +0 -2
- package/dist/configs/_common/.github/workflows/general-check.yml +0 -41
- package/dist/configs/_common/.github/workflows/release.yml +0 -81
- package/dist/configs/_common/.gitignore.template +0 -64
- package/dist/configs/_common/.husky/commit-msg +0 -3
- package/dist/configs/_common/.husky/pre-commit +0 -3
- package/dist/configs/_common/.prettierignore +0 -17
- package/dist/configs/_common/.prettierrc.js +0 -7
- package/dist/configs/_common/.vscode/extensions.json +0 -9
- package/dist/configs/_common/.vscode/react.code-snippets +0 -19
- package/dist/configs/_common/.vscode/settings.json +0 -16
- package/dist/configs/_common/commitlint.config.js +0 -10
- package/dist/configs/_common/package.json.template +0 -75
- package/dist/configs/node-lib/eslint.config.js +0 -50
- package/dist/templates/next-app/.env.template +0 -25
- package/dist/templates/next-app/.prettierignore +0 -58
- package/dist/templates/next-app/README.en.md +0 -130
- package/dist/templates/next-app/README.md +0 -130
- package/dist/templates/next-app/config/IOCIdentifier.ts +0 -74
- package/dist/templates/next-app/config/Identifier/api.ts +0 -41
- package/dist/templates/next-app/config/Identifier/common/admint.table.ts +0 -69
- package/dist/templates/next-app/config/Identifier/common/common.ts +0 -90
- package/dist/templates/next-app/config/Identifier/common/index.ts +0 -3
- package/dist/templates/next-app/config/Identifier/common/validators.ts +0 -34
- package/dist/templates/next-app/config/Identifier/index.ts +0 -3
- package/dist/templates/next-app/config/Identifier/pages/index.ts +0 -7
- package/dist/templates/next-app/config/Identifier/pages/page.about.ts +0 -20
- package/dist/templates/next-app/config/Identifier/pages/page.admin.home.ts +0 -27
- package/dist/templates/next-app/config/Identifier/pages/page.admin.locales.ts +0 -266
- package/dist/templates/next-app/config/Identifier/pages/page.admin.user.ts +0 -293
- package/dist/templates/next-app/config/Identifier/pages/page.home.ts +0 -56
- package/dist/templates/next-app/config/Identifier/pages/page.login.ts +0 -159
- package/dist/templates/next-app/config/Identifier/pages/page.register.ts +0 -177
- package/dist/templates/next-app/config/adminNavs.ts +0 -19
- package/dist/templates/next-app/config/common.ts +0 -43
- package/dist/templates/next-app/config/cookies.ts +0 -23
- package/dist/templates/next-app/config/i18n/AboutI18n.ts +0 -14
- package/dist/templates/next-app/config/i18n/HomeI18n.ts +0 -24
- package/dist/templates/next-app/config/i18n/PageI18nInterface.ts +0 -51
- package/dist/templates/next-app/config/i18n/admin18n.ts +0 -75
- package/dist/templates/next-app/config/i18n/i18nConfig.ts +0 -16
- package/dist/templates/next-app/config/i18n/i18nKeyScheam.ts +0 -36
- package/dist/templates/next-app/config/i18n/index.ts +0 -7
- package/dist/templates/next-app/config/i18n/loginI18n.ts +0 -50
- package/dist/templates/next-app/config/i18n/register18n.ts +0 -44
- package/dist/templates/next-app/config/route.ts +0 -9
- package/dist/templates/next-app/config/theme.ts +0 -28
- package/dist/templates/next-app/docs/en/api.md +0 -387
- package/dist/templates/next-app/docs/en/component.md +0 -544
- package/dist/templates/next-app/docs/en/database.md +0 -496
- package/dist/templates/next-app/docs/en/development-guide.md +0 -727
- package/dist/templates/next-app/docs/en/env.md +0 -563
- package/dist/templates/next-app/docs/en/i18n.md +0 -287
- package/dist/templates/next-app/docs/en/index.md +0 -165
- package/dist/templates/next-app/docs/en/page.md +0 -457
- package/dist/templates/next-app/docs/en/project-structure.md +0 -176
- package/dist/templates/next-app/docs/en/router.md +0 -427
- package/dist/templates/next-app/docs/en/theme.md +0 -532
- package/dist/templates/next-app/docs/en/validator.md +0 -478
- package/dist/templates/next-app/docs/zh/api.md +0 -387
- package/dist/templates/next-app/docs/zh/component.md +0 -544
- package/dist/templates/next-app/docs/zh/database.md +0 -496
- package/dist/templates/next-app/docs/zh/development-guide.md +0 -727
- package/dist/templates/next-app/docs/zh/env.md +0 -563
- package/dist/templates/next-app/docs/zh/i18n.md +0 -287
- package/dist/templates/next-app/docs/zh/index.md +0 -165
- package/dist/templates/next-app/docs/zh/page.md +0 -457
- package/dist/templates/next-app/docs/zh/project-structure.md +0 -176
- package/dist/templates/next-app/docs/zh/router.md +0 -427
- package/dist/templates/next-app/docs/zh/theme.md +0 -532
- package/dist/templates/next-app/docs/zh/validator.md +0 -476
- package/dist/templates/next-app/eslint.config.mjs +0 -285
- package/dist/templates/next-app/make/generateLocales.ts +0 -32
- package/dist/templates/next-app/migrations/schema/LocalesSchema.ts +0 -15
- package/dist/templates/next-app/migrations/schema/UserSchema.ts +0 -38
- package/dist/templates/next-app/migrations/sql/1694244000000.sql +0 -21
- package/dist/templates/next-app/next.config.ts +0 -25
- package/dist/templates/next-app/package.json +0 -87
- package/dist/templates/next-app/postcss.config.mjs +0 -5
- package/dist/templates/next-app/public/favicon.ico +0 -0
- package/dist/templates/next-app/public/file.svg +0 -1
- package/dist/templates/next-app/public/globe.svg +0 -1
- package/dist/templates/next-app/public/locales/en.json +0 -182
- package/dist/templates/next-app/public/locales/zh.json +0 -182
- package/dist/templates/next-app/public/next.svg +0 -1
- package/dist/templates/next-app/public/vercel.svg +0 -1
- package/dist/templates/next-app/public/window.svg +0 -1
- package/dist/templates/next-app/src/app/[locale]/admin/AdminI18nProvider.tsx +0 -37
- package/dist/templates/next-app/src/app/[locale]/admin/layout.tsx +0 -42
- package/dist/templates/next-app/src/app/[locale]/admin/locales/page.tsx +0 -153
- package/dist/templates/next-app/src/app/[locale]/admin/page.tsx +0 -20
- package/dist/templates/next-app/src/app/[locale]/admin/users/page.tsx +0 -67
- package/dist/templates/next-app/src/app/[locale]/auth/layout.tsx +0 -18
- package/dist/templates/next-app/src/app/[locale]/auth/login/LoginForm.tsx +0 -126
- package/dist/templates/next-app/src/app/[locale]/auth/login/page.tsx +0 -90
- package/dist/templates/next-app/src/app/[locale]/auth/page.tsx +0 -8
- package/dist/templates/next-app/src/app/[locale]/auth/register/RegisterForm.tsx +0 -197
- package/dist/templates/next-app/src/app/[locale]/auth/register/page.tsx +0 -90
- package/dist/templates/next-app/src/app/[locale]/layout.tsx +0 -63
- package/dist/templates/next-app/src/app/[locale]/not-found.tsx +0 -24
- package/dist/templates/next-app/src/app/[locale]/page.tsx +0 -98
- package/dist/templates/next-app/src/app/api/admin/locales/create/route.ts +0 -13
- package/dist/templates/next-app/src/app/api/admin/locales/import/route.ts +0 -13
- package/dist/templates/next-app/src/app/api/admin/locales/route.ts +0 -20
- package/dist/templates/next-app/src/app/api/admin/locales/update/route.ts +0 -13
- package/dist/templates/next-app/src/app/api/admin/users/route.ts +0 -20
- package/dist/templates/next-app/src/app/api/ai/completions/route.ts +0 -32
- package/dist/templates/next-app/src/app/api/auth/callback/route.ts +0 -11
- package/dist/templates/next-app/src/app/api/callback/route.ts +0 -49
- package/dist/templates/next-app/src/app/api/locales/json/route.ts +0 -33
- package/dist/templates/next-app/src/app/api/user/login/route.ts +0 -10
- package/dist/templates/next-app/src/app/api/user/logout/route.ts +0 -8
- package/dist/templates/next-app/src/app/api/user/register/route.ts +0 -11
- package/dist/templates/next-app/src/app/manifest.ts +0 -16
- package/dist/templates/next-app/src/app/robots.txt +0 -2
- package/dist/templates/next-app/src/base/cases/AdminPageManager.ts +0 -28
- package/dist/templates/next-app/src/base/cases/AppConfig.ts +0 -40
- package/dist/templates/next-app/src/base/cases/Datetime.ts +0 -18
- package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +0 -57
- package/dist/templates/next-app/src/base/cases/DialogHandler.ts +0 -116
- package/dist/templates/next-app/src/base/cases/InversifyContainer.ts +0 -45
- package/dist/templates/next-app/src/base/cases/NavigateBridge.ts +0 -32
- package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +0 -77
- package/dist/templates/next-app/src/base/cases/ResourceState.ts +0 -17
- package/dist/templates/next-app/src/base/cases/RouterService.ts +0 -52
- package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +0 -73
- package/dist/templates/next-app/src/base/cases/TranslateI18nUtil.ts +0 -53
- package/dist/templates/next-app/src/base/cases/ZodColumnBuilder.ts +0 -212
- package/dist/templates/next-app/src/base/port/AdminLayoutInterface.ts +0 -26
- package/dist/templates/next-app/src/base/port/AppApiInterface.ts +0 -36
- package/dist/templates/next-app/src/base/port/AppUserApiInterface.ts +0 -27
- package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +0 -25
- package/dist/templates/next-app/src/base/port/IOCInterface.ts +0 -33
- package/dist/templates/next-app/src/base/port/RouterInterface.ts +0 -11
- package/dist/templates/next-app/src/base/port/UserServiceInterface.ts +0 -25
- package/dist/templates/next-app/src/base/port/ZodBuilderInterface.ts +0 -8
- package/dist/templates/next-app/src/base/services/AdminPageEvent.ts +0 -26
- package/dist/templates/next-app/src/base/services/AdminPageScheduler.ts +0 -42
- package/dist/templates/next-app/src/base/services/AppApiRequester.ts +0 -67
- package/dist/templates/next-app/src/base/services/AppUserGateway.ts +0 -110
- package/dist/templates/next-app/src/base/services/I18nService.ts +0 -87
- package/dist/templates/next-app/src/base/services/ResourceService.ts +0 -139
- package/dist/templates/next-app/src/base/services/UserService.ts +0 -68
- package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +0 -106
- package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +0 -87
- package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +0 -110
- package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +0 -52
- package/dist/templates/next-app/src/base/types/AppPageRouter.ts +0 -12
- package/dist/templates/next-app/src/base/types/PagesRouter.ts +0 -9
- package/dist/templates/next-app/src/core/bootstraps/BootstrapClient.ts +0 -76
- package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +0 -125
- package/dist/templates/next-app/src/core/bootstraps/BootstrapsRegistry.ts +0 -50
- package/dist/templates/next-app/src/core/bootstraps/IocIdentifierTest.ts +0 -26
- package/dist/templates/next-app/src/core/bootstraps/PrintBootstrap.ts +0 -18
- package/dist/templates/next-app/src/core/clientIoc/ClientIOC.ts +0 -68
- package/dist/templates/next-app/src/core/clientIoc/ClientIOCRegister.ts +0 -100
- package/dist/templates/next-app/src/core/globals.ts +0 -28
- package/dist/templates/next-app/src/core/serverIoc/ServerIOC.ts +0 -80
- package/dist/templates/next-app/src/core/serverIoc/ServerIOCRegister.ts +0 -66
- package/dist/templates/next-app/src/i18n/loadMessages.ts +0 -103
- package/dist/templates/next-app/src/i18n/request.ts +0 -31
- package/dist/templates/next-app/src/i18n/routing.ts +0 -35
- package/dist/templates/next-app/src/lib/supabase/client.ts +0 -8
- package/dist/templates/next-app/src/lib/supabase/conts.ts +0 -2
- package/dist/templates/next-app/src/lib/supabase/proxy.ts +0 -84
- package/dist/templates/next-app/src/lib/supabase/server.ts +0 -38
- package/dist/templates/next-app/src/pages/[locale]/about.tsx +0 -61
- package/dist/templates/next-app/src/pages/_app.tsx +0 -50
- package/dist/templates/next-app/src/pages/_document.tsx +0 -13
- package/dist/templates/next-app/src/proxy.ts +0 -33
- package/dist/templates/next-app/src/server/AppErrorApi.ts +0 -10
- package/dist/templates/next-app/src/server/AppPageRouteParams.ts +0 -110
- package/dist/templates/next-app/src/server/AppSuccessApi.ts +0 -7
- package/dist/templates/next-app/src/server/NextApiServer.ts +0 -61
- package/dist/templates/next-app/src/server/PagesRouteParams.ts +0 -145
- package/dist/templates/next-app/src/server/PasswordEncrypt.ts +0 -18
- package/dist/templates/next-app/src/server/ServerAuth.ts +0 -81
- package/dist/templates/next-app/src/server/SupabaseBridge.ts +0 -262
- package/dist/templates/next-app/src/server/UserCredentialToken.ts +0 -53
- package/dist/templates/next-app/src/server/controllers/AdminLocalesController.ts +0 -86
- package/dist/templates/next-app/src/server/controllers/AdminUserController.ts +0 -42
- package/dist/templates/next-app/src/server/controllers/LocalesController.ts +0 -36
- package/dist/templates/next-app/src/server/controllers/UserController.ts +0 -91
- package/dist/templates/next-app/src/server/port/AIControllerInterface.ts +0 -8
- package/dist/templates/next-app/src/server/port/AdminLocalesControllerInterface.ts +0 -21
- package/dist/templates/next-app/src/server/port/AdminUserControllerInterface.ts +0 -11
- package/dist/templates/next-app/src/server/port/CrentialTokenInterface.ts +0 -5
- package/dist/templates/next-app/src/server/port/DBBridgeInterface.ts +0 -36
- package/dist/templates/next-app/src/server/port/DBTableInterface.ts +0 -12
- package/dist/templates/next-app/src/server/port/LocalesControllerInterface.ts +0 -10
- package/dist/templates/next-app/src/server/port/LocalesRepositoryInterface.ts +0 -43
- package/dist/templates/next-app/src/server/port/PaginationInterface.ts +0 -6
- package/dist/templates/next-app/src/server/port/RouteParamsnHandlerInterface.ts +0 -18
- package/dist/templates/next-app/src/server/port/ServerAuthInterface.ts +0 -15
- package/dist/templates/next-app/src/server/port/ServerInterface.ts +0 -23
- package/dist/templates/next-app/src/server/port/UserRepositoryInterface.ts +0 -15
- package/dist/templates/next-app/src/server/port/UserServiceInterface.ts +0 -14
- package/dist/templates/next-app/src/server/port/ValidatorInterface.ts +0 -23
- package/dist/templates/next-app/src/server/repositorys/LocalesRepository.ts +0 -216
- package/dist/templates/next-app/src/server/repositorys/UserRepository.ts +0 -102
- package/dist/templates/next-app/src/server/services/AIService.ts +0 -45
- package/dist/templates/next-app/src/server/services/AdminAuthPlugin.ts +0 -21
- package/dist/templates/next-app/src/server/services/AdminLocalesService.ts +0 -20
- package/dist/templates/next-app/src/server/services/ApiLocaleService.ts +0 -137
- package/dist/templates/next-app/src/server/services/ApiUserService.ts +0 -29
- package/dist/templates/next-app/src/server/services/UserService.ts +0 -134
- package/dist/templates/next-app/src/server/validators/ExtendedExecutorError.ts +0 -6
- package/dist/templates/next-app/src/server/validators/LocalesValidator.ts +0 -145
- package/dist/templates/next-app/src/server/validators/LoginValidator.ts +0 -82
- package/dist/templates/next-app/src/server/validators/PaginationValidator.ts +0 -70
- package/dist/templates/next-app/src/server/validators/SignupVerifyValidator.ts +0 -68
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/_default.css +0 -280
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/dark.css +0 -233
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/_common/pink.css +0 -246
- package/dist/templates/next-app/src/styles/css/antd-themes/index.css +0 -4
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/_default.css +0 -108
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/dark.css +0 -67
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/menu/pink.css +0 -67
- package/dist/templates/next-app/src/styles/css/antd-themes/no-context.css +0 -34
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/_default.css +0 -34
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/dark.css +0 -31
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/pagination/pink.css +0 -36
- package/dist/templates/next-app/src/styles/css/antd-themes/table/_default.css +0 -44
- package/dist/templates/next-app/src/styles/css/antd-themes/table/dark.css +0 -43
- package/dist/templates/next-app/src/styles/css/antd-themes/table/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/antd-themes/table/pink.css +0 -43
- package/dist/templates/next-app/src/styles/css/index.css +0 -6
- package/dist/templates/next-app/src/styles/css/page.css +0 -20
- package/dist/templates/next-app/src/styles/css/scrollbar.css +0 -34
- package/dist/templates/next-app/src/styles/css/tailwind.css +0 -5
- package/dist/templates/next-app/src/styles/css/themes/_default.css +0 -30
- package/dist/templates/next-app/src/styles/css/themes/dark.css +0 -30
- package/dist/templates/next-app/src/styles/css/themes/index.css +0 -3
- package/dist/templates/next-app/src/styles/css/themes/pink.css +0 -30
- package/dist/templates/next-app/src/styles/css/zIndex.css +0 -9
- package/dist/templates/next-app/src/uikit/components/AdminLayout.tsx +0 -150
- package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +0 -39
- package/dist/templates/next-app/src/uikit/components/ClientRootProvider.tsx +0 -64
- package/dist/templates/next-app/src/uikit/components/ClientSeo.tsx +0 -36
- package/dist/templates/next-app/src/uikit/components/ClinetRenderProvider.tsx +0 -42
- package/dist/templates/next-app/src/uikit/components/EditableCell.tsx +0 -118
- package/dist/templates/next-app/src/uikit/components/FeatureItem.tsx +0 -13
- package/dist/templates/next-app/src/uikit/components/IOCProvider.tsx +0 -34
- package/dist/templates/next-app/src/uikit/components/LocaleLink.tsx +0 -50
- package/dist/templates/next-app/src/uikit/components/With.tsx +0 -17
- package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportButton.tsx +0 -62
- package/dist/templates/next-app/src/uikit/components/localesImportButton/LocalesImportEvent.ts +0 -28
- package/dist/templates/next-app/src/uikit/components/localesImportButton/import.module.css +0 -6
- package/dist/templates/next-app/src/uikit/components-app/AdminButton.tsx +0 -29
- package/dist/templates/next-app/src/uikit/components-app/AppBridge.tsx +0 -17
- package/dist/templates/next-app/src/uikit/components-app/AppRoutePage.tsx +0 -105
- package/dist/templates/next-app/src/uikit/components-app/AuthButton.tsx +0 -20
- package/dist/templates/next-app/src/uikit/components-app/LanguageSwitcher.tsx +0 -75
- package/dist/templates/next-app/src/uikit/components-app/LogoutButton.tsx +0 -45
- package/dist/templates/next-app/src/uikit/components-app/ThemeSwitcher.tsx +0 -144
- package/dist/templates/next-app/src/uikit/components-pages/LanguageSwitcher.tsx +0 -98
- package/dist/templates/next-app/src/uikit/components-pages/PagesRoutePage.tsx +0 -93
- package/dist/templates/next-app/src/uikit/context/IOCContext.ts +0 -25
- package/dist/templates/next-app/src/uikit/hook/useI18nInterface.ts +0 -22
- package/dist/templates/next-app/src/uikit/hook/useIOC.ts +0 -37
- package/dist/templates/next-app/src/uikit/hook/useStrictEffect.ts +0 -32
- package/dist/templates/next-app/src/uikit/hook/useWarnTranslations.ts +0 -11
- package/dist/templates/next-app/src/uikit/utils/getHashParams.ts +0 -8
- package/dist/templates/next-app/src/uikit/utils/getHashVerifyEmailParams.ts +0 -42
- package/dist/templates/next-app/tailwind.config.ts +0 -8
- package/dist/templates/next-app/tsconfig.json +0 -39
- package/dist/templates/node-lib/__tests__/readJson.test.ts +0 -26
- package/dist/templates/node-lib/bin/test.js +0 -30
- package/dist/templates/node-lib/package.json +0 -66
- package/dist/templates/node-lib/rollup.config.js +0 -79
- package/dist/templates/node-lib/src/index.ts +0 -7
- package/dist/templates/node-lib/src/readJson.ts +0 -12
- package/dist/templates/node-lib/tsconfig.json +0 -23
- package/dist/templates/pack-app/README.md +0 -108
- package/dist/templates/pack-app/eslint.config.js +0 -97
- package/dist/templates/pack-app/fe-config.json +0 -35
- package/dist/templates/pack-app/package.json +0 -86
- package/dist/templates/pack-app/pnpm-workspace.yaml +0 -2
- package/dist/templates/pack-app/tsconfig.json +0 -9
- package/dist/templates/pack-app/tsconfig.test.json +0 -10
- package/dist/templates/pack-app/vite.config.ts +0 -14
- package/dist/templates/react-app/.env.template +0 -22
- package/dist/templates/react-app/.prettierignore +0 -17
- package/dist/templates/react-app/README.en.md +0 -274
- package/dist/templates/react-app/README.md +0 -273
- package/dist/templates/react-app/__tests__/__mocks__/BootstrapTest.ts +0 -16
- package/dist/templates/react-app/__tests__/__mocks__/MockAppConfig.ts +0 -48
- package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +0 -17
- package/dist/templates/react-app/__tests__/__mocks__/MockLogger.ts +0 -14
- package/dist/templates/react-app/__tests__/__mocks__/components/TestApp.tsx +0 -38
- package/dist/templates/react-app/__tests__/__mocks__/components/TestBootstrapsProvider.tsx +0 -53
- package/dist/templates/react-app/__tests__/__mocks__/components/TestRouter.tsx +0 -46
- package/dist/templates/react-app/__tests__/__mocks__/components/index.ts +0 -12
- package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +0 -96
- package/dist/templates/react-app/__tests__/__mocks__/i18nextHttpBackend.ts +0 -110
- package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOC.ts +0 -55
- package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOCRegister.ts +0 -74
- package/dist/templates/react-app/__tests__/setup/index.ts +0 -1
- package/dist/templates/react-app/__tests__/setup/setupGlobal.ts +0 -64
- package/dist/templates/react-app/__tests__/src/App.structure.test.tsx +0 -115
- package/dist/templates/react-app/__tests__/src/base/cases/AppConfig.test.ts +0 -288
- package/dist/templates/react-app/__tests__/src/base/cases/DialogHandler.test.ts +0 -226
- package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +0 -178
- package/dist/templates/react-app/__tests__/src/base/cases/InversifyContainer.test.ts +0 -181
- package/dist/templates/react-app/__tests__/src/base/cases/PublicAssetsPath.test.ts +0 -61
- package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +0 -177
- package/dist/templates/react-app/__tests__/src/base/cases/RequestStatusCatcher.test.ts +0 -191
- package/dist/templates/react-app/__tests__/src/base/cases/RouterLoader.test.ts +0 -245
- package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +0 -240
- package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +0 -242
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +0 -135
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +0 -74
- package/dist/templates/react-app/__tests__/src/main.test.tsx +0 -46
- package/dist/templates/react-app/__tests__/src/uikit/components/BaseHeader.test.tsx +0 -97
- package/dist/templates/react-app/__tests__/src/uikit/components/chatMessage/ChatRoot.test.tsx +0 -274
- package/dist/templates/react-app/config/IOCIdentifier.ts +0 -91
- package/dist/templates/react-app/config/Identifier/common/common.error.ts +0 -34
- package/dist/templates/react-app/config/Identifier/common/common.ts +0 -62
- package/dist/templates/react-app/config/Identifier/common/index.ts +0 -2
- package/dist/templates/react-app/config/Identifier/components/component.chatMessage.ts +0 -56
- package/dist/templates/react-app/config/Identifier/components/component.messageBaseList.ts +0 -103
- package/dist/templates/react-app/config/Identifier/index.ts +0 -2
- package/dist/templates/react-app/config/Identifier/pages/index.ts +0 -9
- package/dist/templates/react-app/config/Identifier/pages/page.about.ts +0 -189
- package/dist/templates/react-app/config/Identifier/pages/page.executor.ts +0 -275
- package/dist/templates/react-app/config/Identifier/pages/page.home.ts +0 -71
- package/dist/templates/react-app/config/Identifier/pages/page.identifiter.ts +0 -102
- package/dist/templates/react-app/config/Identifier/pages/page.jsonStorage.ts +0 -77
- package/dist/templates/react-app/config/Identifier/pages/page.login.ts +0 -162
- package/dist/templates/react-app/config/Identifier/pages/page.message.ts +0 -20
- package/dist/templates/react-app/config/Identifier/pages/page.register.ts +0 -159
- package/dist/templates/react-app/config/Identifier/pages/page.request.ts +0 -169
- package/dist/templates/react-app/config/app.router.ts +0 -338
- package/dist/templates/react-app/config/common.ts +0 -85
- package/dist/templates/react-app/config/feapi.mock.json +0 -34
- package/dist/templates/react-app/config/i18n/PageI18nInterface.ts +0 -51
- package/dist/templates/react-app/config/i18n/aboutI18n.ts +0 -42
- package/dist/templates/react-app/config/i18n/chatMessageI18n.ts +0 -17
- package/dist/templates/react-app/config/i18n/executorI18n.ts +0 -51
- package/dist/templates/react-app/config/i18n/homeI18n.ts +0 -24
- package/dist/templates/react-app/config/i18n/i18nConfig.ts +0 -30
- package/dist/templates/react-app/config/i18n/identifiter18n.ts +0 -30
- package/dist/templates/react-app/config/i18n/jsonStorage18n.ts +0 -27
- package/dist/templates/react-app/config/i18n/login18n.ts +0 -42
- package/dist/templates/react-app/config/i18n/messageBaseListI18n.ts +0 -22
- package/dist/templates/react-app/config/i18n/messageI18n.ts +0 -14
- package/dist/templates/react-app/config/i18n/notFoundI18n.ts +0 -34
- package/dist/templates/react-app/config/i18n/register18n.ts +0 -40
- package/dist/templates/react-app/config/i18n/request18n.ts +0 -41
- package/dist/templates/react-app/config/theme.ts +0 -21
- package/dist/templates/react-app/docs/en/bootstrap.md +0 -1891
- package/dist/templates/react-app/docs/en/components/chat-message-component.md +0 -320
- package/dist/templates/react-app/docs/en/components/chat-message-refactor.md +0 -283
- package/dist/templates/react-app/docs/en/components/message-base-list-component.md +0 -171
- package/dist/templates/react-app/docs/en/development-guide.md +0 -1199
- package/dist/templates/react-app/docs/en/env.md +0 -1336
- package/dist/templates/react-app/docs/en/global.md +0 -509
- package/dist/templates/react-app/docs/en/i18n.md +0 -979
- package/dist/templates/react-app/docs/en/index.md +0 -802
- package/dist/templates/react-app/docs/en/ioc.md +0 -1365
- package/dist/templates/react-app/docs/en/playwright/e2e-tests.md +0 -321
- package/dist/templates/react-app/docs/en/playwright/index.md +0 -19
- package/dist/templates/react-app/docs/en/playwright/installation-summary.md +0 -332
- package/dist/templates/react-app/docs/en/playwright/overview.md +0 -222
- package/dist/templates/react-app/docs/en/playwright/quickstart.md +0 -325
- package/dist/templates/react-app/docs/en/playwright/reorganization-notes.md +0 -340
- package/dist/templates/react-app/docs/en/playwright/setup-complete.md +0 -290
- package/dist/templates/react-app/docs/en/playwright/testing-guide.md +0 -565
- package/dist/templates/react-app/docs/en/request.md +0 -423
- package/dist/templates/react-app/docs/en/router.md +0 -404
- package/dist/templates/react-app/docs/en/store.md +0 -1331
- package/dist/templates/react-app/docs/en/test-guide.md +0 -976
- package/dist/templates/react-app/docs/en/theme.md +0 -424
- package/dist/templates/react-app/docs/en/typescript-guide.md +0 -473
- package/dist/templates/react-app/docs/en/why-no-globals.md +0 -797
- package/dist/templates/react-app/docs/zh/bootstrap.md +0 -1891
- package/dist/templates/react-app/docs/zh/components/chat-message-component.md +0 -320
- package/dist/templates/react-app/docs/zh/components/chat-message-refactor.md +0 -283
- package/dist/templates/react-app/docs/zh/components/message-base-list-component.md +0 -171
- package/dist/templates/react-app/docs/zh/development-guide.md +0 -1199
- package/dist/templates/react-app/docs/zh/env.md +0 -1336
- package/dist/templates/react-app/docs/zh/global.md +0 -511
- package/dist/templates/react-app/docs/zh/i18n.md +0 -979
- package/dist/templates/react-app/docs/zh/index.md +0 -786
- package/dist/templates/react-app/docs/zh/ioc.md +0 -1364
- package/dist/templates/react-app/docs/zh/playwright/e2e-tests.md +0 -321
- package/dist/templates/react-app/docs/zh/playwright/index.md +0 -19
- package/dist/templates/react-app/docs/zh/playwright/installation-summary.md +0 -332
- package/dist/templates/react-app/docs/zh/playwright/overview.md +0 -222
- package/dist/templates/react-app/docs/zh/playwright/quickstart.md +0 -325
- package/dist/templates/react-app/docs/zh/playwright/reorganization-notes.md +0 -340
- package/dist/templates/react-app/docs/zh/playwright/setup-complete.md +0 -290
- package/dist/templates/react-app/docs/zh/playwright/testing-guide.md +0 -565
- package/dist/templates/react-app/docs/zh/request.md +0 -427
- package/dist/templates/react-app/docs/zh/router.md +0 -408
- package/dist/templates/react-app/docs/zh/store.md +0 -1329
- package/dist/templates/react-app/docs/zh/test-guide.md +0 -976
- package/dist/templates/react-app/docs/zh/theme.md +0 -424
- package/dist/templates/react-app/docs/zh/typescript-guide.md +0 -473
- package/dist/templates/react-app/docs/zh/why-no-globals.md +0 -797
- package/dist/templates/react-app/e2e/App.spec.ts +0 -319
- package/dist/templates/react-app/e2e/fixtures/base.fixture.ts +0 -40
- package/dist/templates/react-app/e2e/main.spec.ts +0 -20
- package/dist/templates/react-app/e2e/utils/test-helpers.ts +0 -19
- package/dist/templates/react-app/eslint.config.mjs +0 -325
- package/dist/templates/react-app/index.html +0 -13
- package/dist/templates/react-app/makes/generateTs2LocalesOptions.ts +0 -26
- package/dist/templates/react-app/package.json +0 -125
- package/dist/templates/react-app/playwright.config.ts +0 -79
- package/dist/templates/react-app/postcss.config.js +0 -5
- package/dist/templates/react-app/public/locales/en/common.json +0 -235
- package/dist/templates/react-app/public/locales/zh/common.json +0 -235
- package/dist/templates/react-app/public/logo.svg +0 -1
- package/dist/templates/react-app/public/router-root/logo.svg +0 -1
- package/dist/templates/react-app/src/App.tsx +0 -35
- package/dist/templates/react-app/src/assets/react.svg +0 -1
- package/dist/templates/react-app/src/base/apis/AiApi.ts +0 -68
- package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +0 -29
- package/dist/templates/react-app/src/base/apis/feApi/FeApiAdapter.ts +0 -14
- package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +0 -86
- package/dist/templates/react-app/src/base/apis/feApi/FeApiType.ts +0 -21
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +0 -142
- package/dist/templates/react-app/src/base/apis/userApi/UserApiAdapter.ts +0 -14
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +0 -86
- package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +0 -70
- package/dist/templates/react-app/src/base/cases/AppConfig.ts +0 -123
- package/dist/templates/react-app/src/base/cases/DialogHandler.ts +0 -115
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +0 -64
- package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +0 -45
- package/dist/templates/react-app/src/base/cases/PublicAssetsPath.ts +0 -23
- package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +0 -55
- package/dist/templates/react-app/src/base/cases/RequestLogger.ts +0 -80
- package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +0 -40
- package/dist/templates/react-app/src/base/cases/ResourceState.ts +0 -23
- package/dist/templates/react-app/src/base/cases/RouterLoader.ts +0 -173
- package/dist/templates/react-app/src/base/cases/TranslateI18nInterface.ts +0 -26
- package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +0 -23
- package/dist/templates/react-app/src/base/port/I18nServiceInterface.ts +0 -10
- package/dist/templates/react-app/src/base/port/IOCInterface.ts +0 -38
- package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +0 -21
- package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +0 -23
- package/dist/templates/react-app/src/base/port/RequestStatusInterface.ts +0 -5
- package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +0 -29
- package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +0 -20
- package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +0 -61
- package/dist/templates/react-app/src/base/services/I18nService.ts +0 -146
- package/dist/templates/react-app/src/base/services/IdentifierService.ts +0 -162
- package/dist/templates/react-app/src/base/services/RouteService.ts +0 -115
- package/dist/templates/react-app/src/base/services/UserBootstrap.ts +0 -45
- package/dist/templates/react-app/src/base/services/UserService.ts +0 -88
- package/dist/templates/react-app/src/base/types/Page.ts +0 -47
- package/dist/templates/react-app/src/base/types/deprecated-antd.d.ts +0 -60
- package/dist/templates/react-app/src/base/types/global.d.ts +0 -8
- package/dist/templates/react-app/src/core/IOC.ts +0 -28
- package/dist/templates/react-app/src/core/bootstraps/BootstrapClient.ts +0 -108
- package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +0 -54
- package/dist/templates/react-app/src/core/bootstraps/IocIdentifierTest.ts +0 -26
- package/dist/templates/react-app/src/core/bootstraps/PrintBootstrap.ts +0 -14
- package/dist/templates/react-app/src/core/bootstraps/SaveAppInfo.ts +0 -28
- package/dist/templates/react-app/src/core/clientIoc/ClientIOC.ts +0 -47
- package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +0 -142
- package/dist/templates/react-app/src/core/globals.ts +0 -47
- package/dist/templates/react-app/src/main.tsx +0 -19
- package/dist/templates/react-app/src/pages/404.tsx +0 -19
- package/dist/templates/react-app/src/pages/500.tsx +0 -18
- package/dist/templates/react-app/src/pages/NoRouteFound.tsx +0 -5
- package/dist/templates/react-app/src/pages/auth/Layout.tsx +0 -27
- package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +0 -166
- package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +0 -226
- package/dist/templates/react-app/src/pages/base/AboutPage.tsx +0 -123
- package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +0 -467
- package/dist/templates/react-app/src/pages/base/HomePage.tsx +0 -81
- package/dist/templates/react-app/src/pages/base/IdentifierPage.tsx +0 -117
- package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +0 -132
- package/dist/templates/react-app/src/pages/base/Layout.tsx +0 -20
- package/dist/templates/react-app/src/pages/base/MessagePage.tsx +0 -71
- package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +0 -18
- package/dist/templates/react-app/src/pages/base/RequestPage.tsx +0 -193
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/_default.css +0 -280
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/dark.css +0 -233
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/_common/pink.css +0 -246
- package/dist/templates/react-app/src/styles/css/antd-themes/index.css +0 -4
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/_default.css +0 -108
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/dark.css +0 -67
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/menu/pink.css +0 -67
- package/dist/templates/react-app/src/styles/css/antd-themes/no-context.css +0 -34
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/_default.css +0 -34
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/dark.css +0 -31
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/pagination/pink.css +0 -36
- package/dist/templates/react-app/src/styles/css/antd-themes/table/_default.css +0 -44
- package/dist/templates/react-app/src/styles/css/antd-themes/table/dark.css +0 -43
- package/dist/templates/react-app/src/styles/css/antd-themes/table/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/antd-themes/table/pink.css +0 -43
- package/dist/templates/react-app/src/styles/css/index.css +0 -6
- package/dist/templates/react-app/src/styles/css/page.css +0 -20
- package/dist/templates/react-app/src/styles/css/scrollbar.css +0 -34
- package/dist/templates/react-app/src/styles/css/tailwind.css +0 -5
- package/dist/templates/react-app/src/styles/css/themes/_default.css +0 -30
- package/dist/templates/react-app/src/styles/css/themes/dark.css +0 -30
- package/dist/templates/react-app/src/styles/css/themes/index.css +0 -3
- package/dist/templates/react-app/src/styles/css/themes/pink.css +0 -30
- package/dist/templates/react-app/src/styles/css/zIndex.css +0 -9
- package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +0 -72
- package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +0 -41
- package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +0 -22
- package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +0 -136
- package/dist/templates/react-app/src/uikit/components/AppRouterProvider.tsx +0 -35
- package/dist/templates/react-app/src/uikit/components/BaseHeader.tsx +0 -51
- package/dist/templates/react-app/src/uikit/components/BaseLayoutProvider.tsx +0 -44
- package/dist/templates/react-app/src/uikit/components/BaseRouteProvider.tsx +0 -21
- package/dist/templates/react-app/src/uikit/components/BaseRouteSeo.tsx +0 -18
- package/dist/templates/react-app/src/uikit/components/BootstrapsProvider.tsx +0 -11
- package/dist/templates/react-app/src/uikit/components/ClientSeo.tsx +0 -62
- package/dist/templates/react-app/src/uikit/components/ComboProvider.tsx +0 -38
- package/dist/templates/react-app/src/uikit/components/LanguageSwitcher.tsx +0 -78
- package/dist/templates/react-app/src/uikit/components/Loading.tsx +0 -49
- package/dist/templates/react-app/src/uikit/components/LocaleLink.tsx +0 -43
- package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +0 -58
- package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +0 -258
- package/dist/templates/react-app/src/uikit/components/RouterRenderComponent.tsx +0 -19
- package/dist/templates/react-app/src/uikit/components/ThemeSwitcher.tsx +0 -137
- package/dist/templates/react-app/src/uikit/components/With.tsx +0 -17
- package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +0 -205
- package/dist/templates/react-app/src/uikit/components/chatMessage/ChatRoot.tsx +0 -21
- package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +0 -108
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +0 -282
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessageItem.tsx +0 -102
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessagesList.tsx +0 -86
- package/dist/templates/react-app/src/uikit/contexts/BaseRouteContext.ts +0 -42
- package/dist/templates/react-app/src/uikit/contexts/IOCContext.ts +0 -13
- package/dist/templates/react-app/src/uikit/hooks/useAppTranslation.ts +0 -26
- package/dist/templates/react-app/src/uikit/hooks/useI18nInterface.ts +0 -25
- package/dist/templates/react-app/src/uikit/hooks/useIOC.ts +0 -35
- package/dist/templates/react-app/src/uikit/hooks/useNavigateBridge.ts +0 -21
- package/dist/templates/react-app/src/uikit/hooks/useRouterI18nGuard.ts +0 -25
- package/dist/templates/react-app/src/uikit/hooks/useStrictEffect.ts +0 -31
- package/dist/templates/react-app/src/vite-env.d.ts +0 -1
- package/dist/templates/react-app/tailwind.config.js +0 -4
- package/dist/templates/react-app/tsconfig.app.json +0 -36
- package/dist/templates/react-app/tsconfig.e2e.json +0 -24
- package/dist/templates/react-app/tsconfig.json +0 -22
- package/dist/templates/react-app/tsconfig.node.json +0 -27
- package/dist/templates/react-app/tsconfig.test.json +0 -18
- package/dist/templates/react-app/vite.config.ts +0 -144
|
@@ -1,979 +0,0 @@
|
|
|
1
|
-
# Internationalization (i18n)
|
|
2
|
-
|
|
3
|
-
## 📋 Table of Contents
|
|
4
|
-
|
|
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
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## 🎯 Core Philosophy
|
|
16
|
-
|
|
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!**
|
|
18
|
-
|
|
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:**
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
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)
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @description Login button text
|
|
57
|
-
* @localZh 登录
|
|
58
|
-
* @localEn Login
|
|
59
|
-
*/
|
|
60
|
-
export const BUTTON_LOGIN = 'common:button.login';
|
|
61
|
-
// ↑ Constant name ↑ Identifier string
|
|
62
|
-
// Used in code Key name stored in translation files
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* @description Welcome message
|
|
66
|
-
* @localZh 欢迎回来,{{name}}!
|
|
67
|
-
* @localEn Welcome back, {{name}}!
|
|
68
|
-
*/
|
|
69
|
-
export const MESSAGE_WELCOME = 'common:message.welcome';
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
**Structure explanation:**
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
'common:button.login'
|
|
76
|
-
↑ ↑ ↑
|
|
77
|
-
Namespace Category Specific identifier
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### Naming Conventions
|
|
81
|
-
|
|
82
|
-
```typescript
|
|
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
|
-
```
|
|
96
|
-
|
|
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
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
### 2. i18n Configuration
|
|
340
|
-
|
|
341
|
-
```typescript
|
|
342
|
-
// config/i18n/i18nConfig.ts
|
|
343
|
-
export const i18nConfig = {
|
|
344
|
-
fallbackLng: 'en', // Default language
|
|
345
|
-
debug: false,
|
|
346
|
-
interpolation: {
|
|
347
|
-
escapeValue: false
|
|
348
|
-
},
|
|
349
|
-
ns: ['common'], // Namespaces
|
|
350
|
-
defaultNS: 'common',
|
|
351
|
-
backend: {
|
|
352
|
-
loadPath: '/locales/{{lng}}/{{ns}}.json' // Translation file path
|
|
353
|
-
},
|
|
354
|
-
supportedLngs: ['en', 'zh'] // Supported languages
|
|
355
|
-
} as const;
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
### 3. I18nService (Bootstrap Plugin)
|
|
359
|
-
|
|
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
|
|
417
|
-
|
|
418
|
-
```typescript
|
|
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
|
|
469
|
-
|
|
470
|
-
/**
|
|
471
|
-
* @description Home page title
|
|
472
|
-
* @localZh 首页
|
|
473
|
-
* @localEn Home
|
|
474
|
-
*/
|
|
475
|
-
export const PAGE_HOME_TITLE = 'common:page.home.title';
|
|
476
|
-
|
|
477
|
-
/**
|
|
478
|
-
* @description Home page welcome message
|
|
479
|
-
* @localZh 欢迎来到我们的应用!
|
|
480
|
-
* @localEn Welcome to our application!
|
|
481
|
-
*/
|
|
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';
|
|
490
|
-
```
|
|
491
|
-
|
|
492
|
-
**Comment conventions:**
|
|
493
|
-
|
|
494
|
-
- `@description`: Explain text purpose (English)
|
|
495
|
-
- `@localZh`: Chinese translation
|
|
496
|
-
- `@localEn`: English translation
|
|
497
|
-
|
|
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';
|
|
508
|
-
|
|
509
|
-
function HomePage() {
|
|
510
|
-
const { t } = useAppTranslation();
|
|
511
|
-
const userName = 'John';
|
|
512
|
-
|
|
513
|
-
return (
|
|
514
|
-
<div>
|
|
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>
|
|
521
|
-
</div>
|
|
522
|
-
);
|
|
523
|
-
}
|
|
524
|
-
```
|
|
525
|
-
|
|
526
|
-
### 3. Use in Services
|
|
527
|
-
|
|
528
|
-
```typescript
|
|
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
|
-
}
|
|
551
|
-
}
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
### 4. Switch Language
|
|
555
|
-
|
|
556
|
-
```typescript
|
|
557
|
-
// src/uikit/components/LanguageSwitcher.tsx
|
|
558
|
-
import { useIOC } from '@/uikit/hooks/useIOC';
|
|
559
|
-
|
|
560
|
-
function LanguageSwitcher() {
|
|
561
|
-
const i18nService = useIOC('I18nServiceInterface');
|
|
562
|
-
const currentLang = i18nService.getCurrentLanguage();
|
|
563
|
-
|
|
564
|
-
const handleChange = (lang: 'zh' | 'en') => {
|
|
565
|
-
// ✅ Switch language
|
|
566
|
-
i18nService.changeLanguage(lang);
|
|
567
|
-
};
|
|
568
|
-
|
|
569
|
-
return (
|
|
570
|
-
<select value={currentLang} onChange={(e) => handleChange(e.target.value)}>
|
|
571
|
-
<option value="zh">中文</option>
|
|
572
|
-
<option value="en">English</option>
|
|
573
|
-
</select>
|
|
574
|
-
);
|
|
575
|
-
}
|
|
576
|
-
```
|
|
577
|
-
|
|
578
|
-
### 5. Complex Scenarios
|
|
579
|
-
|
|
580
|
-
#### Scenario 1: Dynamic Text
|
|
581
|
-
|
|
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';
|
|
589
|
-
|
|
590
|
-
// Usage
|
|
591
|
-
<p>{t(UPLOAD_PROGRESS, { current: 3, total: 10 })}</p>
|
|
592
|
-
// Chinese: 已上传 3 / 10 个文件
|
|
593
|
-
// English: Uploaded 3 / 10 files
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
#### Scenario 2: Plural Forms
|
|
597
|
-
|
|
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';
|
|
605
|
-
|
|
606
|
-
// Usage
|
|
607
|
-
<p>{t(FILES_COUNT, { count: 1 })}</p> // 1 file
|
|
608
|
-
<p>{t(FILES_COUNT, { count: 5 })}</p> // 5 files
|
|
609
|
-
```
|
|
610
|
-
|
|
611
|
-
#### Scenario 3: HTML Content
|
|
612
|
-
|
|
613
|
-
```typescript
|
|
614
|
-
/**
|
|
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>
|
|
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
|
-
}
|
|
657
|
-
```
|
|
658
|
-
|
|
659
|
-
### 2. ✅ Organize i18n Keys Reasonably
|
|
660
|
-
|
|
661
|
-
```typescript
|
|
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
|
|
677
|
-
|
|
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';
|
|
689
|
-
```
|
|
690
|
-
|
|
691
|
-
### 4. ✅ Add Clear Comments to i18n Keys
|
|
692
|
-
|
|
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
|
|
703
|
-
/**
|
|
704
|
-
* @description Delete
|
|
705
|
-
* @localZh 删除
|
|
706
|
-
* @localEn Delete
|
|
707
|
-
*/
|
|
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';
|
|
774
|
-
|
|
775
|
-
// Usage
|
|
776
|
-
<h1>{t(WELCOME_USER, { name: 'John' })}</h1>
|
|
777
|
-
<h1>{t(WELCOME_USER, { name: 'Mary' })}</h1>
|
|
778
|
-
```
|
|
779
|
-
|
|
780
|
-
---
|
|
781
|
-
|
|
782
|
-
## ❓ FAQ
|
|
783
|
-
|
|
784
|
-
### Q1: Why can't I write text directly?
|
|
785
|
-
|
|
786
|
-
**A:**
|
|
787
|
-
|
|
788
|
-
```typescript
|
|
789
|
-
// ❌ Problems with writing text directly
|
|
790
|
-
<button>Login</button>
|
|
791
|
-
|
|
792
|
-
// Problem 1: Cannot internationalize
|
|
793
|
-
// If user switches to Chinese, text won't change
|
|
794
|
-
|
|
795
|
-
// Problem 2: Hard to maintain
|
|
796
|
-
// If want to change "Login" to "Sign In", need to find all places to modify
|
|
797
|
-
|
|
798
|
-
// Problem 3: Cannot manage uniformly
|
|
799
|
-
// Can't know how many "Login" buttons exist in the project
|
|
800
|
-
|
|
801
|
-
// ✅ Advantages of using i18n Key
|
|
802
|
-
<button>{t(BUTTON_LOGIN)}</button>
|
|
803
|
-
|
|
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/
|
|
816
|
-
|
|
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?
|
|
822
|
-
|
|
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
|
-
```
|
|
975
|
-
|
|
976
|
-
---
|
|
977
|
-
|
|
978
|
-
**Feedback:**
|
|
979
|
-
If you have any questions or suggestions about the internationalization system, please discuss in the team channel or submit an Issue.
|