diff --git a/apps/web/.typesafe-i18n.json b/apps/web/.typesafe-i18n.json new file mode 100644 index 0000000..b8c57c8 --- /dev/null +++ b/apps/web/.typesafe-i18n.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://unpkg.com/typesafe-i18n@5.27.1/schema/typesafe-i18n.json", + "baseLocale": "en", + "outputPath": "./i18n/", + "outputFormat": "TypeScript", + "generateOnlyTypes": false, + "adapter": "react" +} diff --git a/apps/web/I18N.md b/apps/web/I18N.md new file mode 100644 index 0000000..a9b61bb --- /dev/null +++ b/apps/web/I18N.md @@ -0,0 +1,22 @@ +# i18n Usage + +All translations live in `i18n/en/index.ts` (English) and `i18n/nl/index.ts` (Dutch), organized by namespace. + +```tsx +"use client"; +import { useI18n } from "../hooks/useI18n"; + +export function MyComponent() { + const { LL, locale, setLocale } = useI18n(); + return
- {session ? "Welcome back!" : "Sign in to continue"} + {session ? LL.Auth.welcomeBack() : LL.Auth.signInToContinue()}
Name
{LL.Forms.name()}
{session.user.name || "N/A"}
Email
{LL.Forms.email()}
{session.user.email}
- We sent a verification code to{" "} - {email} + {LL.Auth.otpSentTo({ email })}
Loading...
{LL.Common.loading()}
- You need to be authenticated to access this application. -
{LL.Auth.signInRequiredMessage()}
+ {session.user.name} +
+ {session.user.email} +
- {session.user.name} -
- {session.user.email} -
Loading your tenants...
+ {LL.Errors.loadingYourTenants()} +
- You don't have access to any tenants yet. Please contact an - administrator to get added to a tenant. -
{LL.Errors.noTenantsMessage()}
- Setting up your tenant... + {LL.Errors.settingUpTenant()}
- Switch tenant + {LL.Navigation.switchTenant()}
Loading items...
{LL.Common.loadingItems()}
- {crudList.data.cruds.length}{" "} - {crudList.data.cruds.length === 1 ? "Item" : "Items"} + {LL.Common.itemCount({ count: crudList.data.cruds.length })}
- No items yet. Add one to get started! -
{LL.Common.noItemsYet()}
- Side-by-side comparison of Mongoose (MongoDB) and Prisma - (PostgreSQL) + {LL.Dashboard.crudDemoSubtitle()}
- NextJs (TailwindCSS) • NestJs • tRPC • Transactions + {LL.Dashboard.crudDemoTechStack()}
{submitted - ? "Check your inbox" - : "Enter your email to receive a password reset link"} + ? LL.Auth.checkYourInbox() + : LL.Auth.forgotPasswordSubtitle()}
- If an account exists with this email, you'll receive a link - to set your password. + {LL.Auth.resetLinkSentMessage()}
- Back to Sign In + {LL.Auth.backToSignIn()}
- {list.data.items.length}{" "} - {list.data.items.length === 1 ? "Item" : "Items"} (global) + {LL.Common.itemCountGlobal({ count: list.data.items.length })}
- Same as CRUD but shared across all tenants. Everyone sees and edits - the same data. + {LL.Dashboard.globalCrudDemoSubtitle()}
- Mongoose (MongoDB) & Prisma (PostgreSQL) • No tenant scope + {LL.Dashboard.globalCrudDemoTechStack()}
- NextJs (Tailwind CSS), NestJs, Expo, tRPC, Better Auth -
{LL.Home.subtitle()}
- Test Create, Read, Update, Delete operations with tRPC and - Prisma integration. Full-stack type safety demonstration. + {LL.Home.crudDemoDescription()}
- Same as CRUD but shared across all tenants. Everyone sees and - edits the same data. + {LL.Home.globalCrudDemoDescription()}
- Create, edit, and remove tenants across the platform. - Super-admin only. + {LL.Home.platformTenantsDescription()}
- Add or remove members from tenants you administer. + {LL.Home.manageMembersDescription()}
- Test authentication with Better Auth. OAuth integration with - Google, session management, and protected routes. + {LL.Home.authDemoDescription()}
- Built with modern tools for rapid development -
{LL.Home.footer()}
- Manage your account security and linked sign-in methods. -
{LL.Settings.profileSubtitle()}
- Your email is not verified + {LL.Settings.emailNotVerified()}
- Please verify your email to access all features. + {LL.Settings.verifyEmailPrompt()}
- Verification email sent! Check your inbox. + {LL.Auth.verificationEmailSent()}
Google
+ {LL.Settings.google()} +
Connected
+ {LL.Settings.connected()} +
- Email & Password + {LL.Settings.emailAndPassword()}
Password set
+ {LL.Settings.passwordSet()} +
- Add a password to sign in without Google or OTP. + {LL.Settings.addPasswordDescription()}
- Check your inbox to set your password. + {LL.Settings.checkInboxForPassword()}
- This password reset link is invalid or has expired. Please request a - new one. + {LL.Auth.invalidOrExpiredLinkMessage()}
- Enter a new password for your account -
{LL.Auth.setPasswordSubtitle()}
- Choose your preferred sign-in method -
{LL.Auth.signInSubtitle()}
- Don't have an account?{" "} + {LL.Auth.dontHaveAccount()}{" "} - Sign up + {LL.Auth.signUp()}
- We've sent a verification email to{" "} - {email}. Please - check your inbox and click the link to verify your account before - signing in. + {LL.Auth.checkInboxMessage({ email })}
- Sign up with your email and password -
{LL.Auth.signUpSubtitle()}
- Min 8 characters with uppercase, lowercase, number, and - special character. + {LL.Auth.passwordMinChars()}
- Already have an account?{" "} + {LL.Auth.alreadyHaveAccount()}{" "} - Sign in + {LL.Auth.signIn()}
- Create, edit, and remove tenants. Super-admin only. + {LL.Dashboard.platformTenantsSubtitle()}
- {tenants.length} tenant - {tenants.length !== 1 ? "s" : ""} + {LL.Dashboard.tenantCount({ count: tenants.length })}
- You don't have admin access to any tenants. + {LL.Settings.noAdminAccessMessage()}
- Add or remove members from your tenants. + {LL.Settings.manageMembersSubtitle()}
- Your tenants ({adminTenants.length}) + {LL.Settings.yourTenants({ count: adminTenants.length })}
- Add member + {LL.Settings.addMember()}
- Loading members... + {LL.Settings.loadingMembers()}
- No members yet. Add one above. + {LL.Settings.noMembersYet()}
- {m.role === "TENANT_ADMIN" ? "Admin" : "User"} + {m.role === "TENANT_ADMIN" + ? LL.Common.roleAdmin() + : LL.Common.roleUser()}
- Select a tenant from the list to manage its members. + {LL.Settings.selectTenantPrompt()}
{errorParam === "token_expired" - ? "This verification link has expired. Please try signing in again to receive a new verification email." - : "This verification link is invalid. Please try signing in again to receive a new verification email."} + ? LL.Auth.verificationFailedExpired() + : LL.Auth.verificationFailedInvalid()}
- Your email has been verified successfully. Redirecting to home... -
{LL.Auth.emailVerifiedMessage()}