From b6f690533c76a43c86ce7820b0ed4fbc2b157074 Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Tue, 22 Apr 2025 21:56:27 +1000 Subject: [PATCH 01/12] feat: finished introduction page for Vietnamese --- www/src/config.ts | 42 ++ www/src/pages/vi/deployment/docker.md | 209 ++++++++++ www/src/pages/vi/deployment/index.astro | 24 ++ www/src/pages/vi/deployment/netlify.mdx | 93 +++++ www/src/pages/vi/deployment/vercel.md | 62 +++ www/src/pages/vi/examples.mdx | 22 + www/src/pages/vi/faq.mdx | 78 ++++ www/src/pages/vi/folder-structure-app.mdx | 254 ++++++++++++ www/src/pages/vi/folder-structure-pages.mdx | 247 +++++++++++ www/src/pages/vi/installation.mdx | 83 ++++ www/src/pages/vi/introduction.mdx | 41 ++ www/src/pages/vi/other-recs.md | 169 ++++++++ www/src/pages/vi/t3-collection.mdx | 29 ++ .../pages/vi/usage/_next-auth-app-router.mdx | 206 ++++++++++ www/src/pages/vi/usage/_next-auth-pages.mdx | 218 ++++++++++ www/src/pages/vi/usage/drizzle.mdx | 84 ++++ www/src/pages/vi/usage/env-variables.mdx | 149 +++++++ www/src/pages/vi/usage/first-steps.md | 53 +++ www/src/pages/vi/usage/index.astro | 24 ++ www/src/pages/vi/usage/next-auth.mdx | 18 + www/src/pages/vi/usage/next-js.md | 37 ++ www/src/pages/vi/usage/prisma.md | 78 ++++ www/src/pages/vi/usage/tailwind.md | 96 +++++ www/src/pages/vi/usage/trpc.md | 382 ++++++++++++++++++ www/src/pages/vi/usage/typescript.md | 67 +++ www/src/pages/vi/why.md | 50 +++ 26 files changed, 2815 insertions(+) create mode 100644 www/src/pages/vi/deployment/docker.md create mode 100644 www/src/pages/vi/deployment/index.astro create mode 100644 www/src/pages/vi/deployment/netlify.mdx create mode 100644 www/src/pages/vi/deployment/vercel.md create mode 100644 www/src/pages/vi/examples.mdx create mode 100644 www/src/pages/vi/faq.mdx create mode 100644 www/src/pages/vi/folder-structure-app.mdx create mode 100644 www/src/pages/vi/folder-structure-pages.mdx create mode 100644 www/src/pages/vi/installation.mdx create mode 100644 www/src/pages/vi/introduction.mdx create mode 100644 www/src/pages/vi/other-recs.md create mode 100644 www/src/pages/vi/t3-collection.mdx create mode 100644 www/src/pages/vi/usage/_next-auth-app-router.mdx create mode 100644 www/src/pages/vi/usage/_next-auth-pages.mdx create mode 100644 www/src/pages/vi/usage/drizzle.mdx create mode 100644 www/src/pages/vi/usage/env-variables.mdx create mode 100644 www/src/pages/vi/usage/first-steps.md create mode 100644 www/src/pages/vi/usage/index.astro create mode 100644 www/src/pages/vi/usage/next-auth.mdx create mode 100644 www/src/pages/vi/usage/next-js.md create mode 100644 www/src/pages/vi/usage/prisma.md create mode 100644 www/src/pages/vi/usage/tailwind.md create mode 100644 www/src/pages/vi/usage/trpc.md create mode 100644 www/src/pages/vi/usage/typescript.md create mode 100644 www/src/pages/vi/why.md diff --git a/www/src/config.ts b/www/src/config.ts index 2b697735b7..965ec6ed67 100644 --- a/www/src/config.ts +++ b/www/src/config.ts @@ -37,6 +37,7 @@ export const KNOWN_LANGUAGES = { no: "Norsk", pl: "Polski", uk: "Українська", + vi: "Tiếng Việt", "zh-hans": "简体中文", } as const; export type KnownLanguageCode = keyof typeof KNOWN_LANGUAGES; @@ -413,6 +414,42 @@ export const SIDEBAR: Sidebar = { { text: "Docker", link: "zh-hans/deployment/docker" }, ], }, + vi: { + "Create T3 App": [ + { text: "Giới thiệu", link: "vi/introduction" }, + { text: "Tại sao chọn CT3A?", link: "vi/why" }, + { text: "Cài đặt", link: "vi/installation" }, + { + text: "Cấu trúc thư mục (Pages Router)", + link: "vi/folder-structure-pages", + }, + { + text: "Cấu trúc thư mục (App Router)", + link: "vi/folder-structure-app", + }, + { text: "Câu hỏi thường gặp", link: "vi/faq" }, + { text: "T3 Collection", link: "vi/t3-collection" }, + { text: "Các khuyến nghị khác", link: "vi/other-recs" }, + ], + Usage: [ + { text: "Bước đầu tiên", link: "vi/usage/first-steps" }, + { text: "Next.js", link: "vi/usage/next-js" }, + { text: "TypeScript", link: "vi/usage/typescript" }, + { text: "tRPC", link: "vi/usage/trpc" }, + { text: "Prisma", link: "vi/usage/prisma" }, + { text: "NextAuth.js", link: "vi/usage/next-auth" }, + { + text: "Biến môi trường", + link: "vi/usage/env-variables", + }, + { text: "Tailwind CSS", link: "vi/usage/tailwind" }, + ], + Deployment: [ + { text: "Vercel", link: "vi/deployment/vercel" }, + { text: "Netlify", link: "vi/deployment/netlify" }, + { text: "Docker", link: "vi/deployment/docker" }, + ], + }, }; export const SIDEBAR_HEADER_MAP: Record< @@ -475,4 +512,9 @@ export const SIDEBAR_HEADER_MAP: Record< Usage: "用法", Deployment: "部署", }, + vi: { + "Create T3 App": "Create T3 App", + Usage: "Sử dụng", + Deployment: "Triển khai", + }, }; diff --git a/www/src/pages/vi/deployment/docker.md b/www/src/pages/vi/deployment/docker.md new file mode 100644 index 0000000000..5ca553cc08 --- /dev/null +++ b/www/src/pages/vi/deployment/docker.md @@ -0,0 +1,209 @@ +--- +title: Docker +description: Deployment with Docker +layout: ../../../layouts/docs.astro +lang: en +--- + +You can containerize this stack and deploy it as a single container using Docker, or as a part of a group of containers using docker-compose. See [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) for an example repo based on this doc. + +## Docker Project Configuration + +Please note that Next.js requires a different process for build time (available in the frontend, prefixed by `NEXT_PUBLIC`) and runtime environment, server-side only, variables. In this demo we are using two variables, pay attention to their positions in the `Dockerfile`, command-line arguments, and `docker-compose.yml`: + +- `DATABASE_URL` (used by the server) +- `NEXT_PUBLIC_CLIENTVAR` (used by the client) + +### 1. Next Configuration + +In your [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js), add the `standalone` output-option configuration to [reduce image size by automatically leveraging output traces](https://nextjs.org/docs/advanced-features/output-file-tracing): + +```diff +export default defineNextConfig({ + reactStrictMode: true, + swcMinify: true, ++ output: "standalone", +}); +``` + +### 2. Create dockerignore file + +
+ + Click here and include contents in .dockerignore: + +
+ +``` +.env +Dockerfile +.dockerignore +node_modules +npm-debug.log +README.md +.next +.git +``` + +
+ +
+ +### 3. Create Dockerfile + +> Since we're not pulling the server environment variables into our container, the [environment schema validation](/en/usage/env-variables) will fail. To prevent this, we have to add a `SKIP_ENV_VALIDATION=1` flag to the build command so that the env-schemas aren't validated at build time. + +
+ + Click here and include contents in Dockerfile: + +
+ +```docker +##### DEPENDENCIES + +FROM --platform=linux/amd64 node:20-alpine AS deps +RUN apk add --no-cache libc6-compat openssl +WORKDIR /app + +# Install Prisma Client - remove if not using Prisma + +COPY prisma ./ + +# Install dependencies based on the preferred package manager + +COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./ + +RUN \ + if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ + elif [ -f package-lock.json ]; then npm ci; \ + elif [ -f pnpm-lock.yaml ]; then npm install -g pnpm && pnpm i; \ + else echo "Lockfile not found." && exit 1; \ + fi + +##### BUILDER + +FROM --platform=linux/amd64 node:20-alpine AS builder +ARG DATABASE_URL +ARG NEXT_PUBLIC_CLIENTVAR +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# ENV NEXT_TELEMETRY_DISABLED 1 + +RUN \ + if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \ + elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \ + elif [ -f pnpm-lock.yaml ]; then npm install -g pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \ + else echo "Lockfile not found." && exit 1; \ + fi + +##### RUNNER + +FROM --platform=linux/amd64 gcr.io/distroless/nodejs20-debian12 AS runner +WORKDIR /app + +ENV NODE_ENV production + +# ENV NEXT_TELEMETRY_DISABLED 1 + +COPY --from=builder /app/next.config.js ./ +COPY --from=builder /app/public ./public +COPY --from=builder /app/package.json ./package.json + +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static + +EXPOSE 3000 +ENV PORT 3000 + +CMD ["server.js"] +``` + +> **_Notes_** +> +> - _Emulation of `--platform=linux/amd64` may not be necessary after moving to Node 18._ +> - _See [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) to understand why `libc6-compat` might be needed._ +> - _Using Alpine 3.17 based images [can cause issues with Prisma](https://github.com/t3-oss/create-t3-app/issues/975). Setting `engineType = "binary"` solves the issue in Alpine 3.17, [but has an associated performance cost](https://www.prisma.io/docs/concepts/components/prisma-engines/query-engine#the-query-engine-at-runtime)._ +> - _Next.js collects [anonymous telemetry data about general usage](https://nextjs.org/telemetry). Uncomment the first instance of `ENV NEXT_TELEMETRY_DISABLED 1` to disable telemetry during the build. Uncomment the second instance to disable telemetry during runtime._ + +
+
+ +## Build and Run Image Locally + +Build and run this image locally with the following commands: + +```bash +docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar . +docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker +``` + +Open [localhost:3000](http://localhost:3000/) to see your running application. + +## Docker Compose + +You can also use Docker Compose to build the image and run the container. + +
+ + Follow steps 1-3 above, click here, and include contents in docker-compose.yml: + +
+ +```yaml +version: "3.9" +services: + app: + platform: "linux/amd64" + build: + context: . + dockerfile: Dockerfile + args: + NEXT_PUBLIC_CLIENTVAR: "clientvar" + working_dir: /app + ports: + - "3000:3000" + image: t3-app + environment: + - DATABASE_URL=database_url_goes_here +``` + +Build and run this using the `docker compose up --build` command: + +```bash +docker compose up --build +``` + +Open [localhost:3000](http://localhost:3000/) to see your running application. + +
+
+ +## Deploy to Railway + +You can use a PaaS such as [Railway's](https://railway.app) automated [Dockerfile deployments](https://docs.railway.app/deploy/dockerfiles) to deploy your app. If you have the [Railway CLI installed](https://docs.railway.app/develop/cli#install) you can deploy your app with the following commands: + +```bash +railway login +railway init +railway link +railway up +railway open +``` + +Go to "Variables" and include your `DATABASE_URL`. Then go to "Settings" and select "Generate Domain." To view a running example on Railway, visit [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/). + +## Useful Resources + +| Resource | Link | +| ------------------------------------ | -------------------------------------------------------------------- | +| Dockerfile reference | https://docs.docker.com/engine/reference/builder/ | +| Compose file version 3 reference | https://docs.docker.com/compose/compose-file/compose-file-v3/ | +| Docker CLI reference | https://docs.docker.com/engine/reference/commandline/docker/ | +| Docker Compose CLI reference | https://docs.docker.com/compose/reference/ | +| Next.js Deployment with Docker Image | https://nextjs.org/docs/deployment#docker-image | +| Next.js in Docker | https://benmarte.com/blog/nextjs-in-docker/ | +| Next.js with Docker Example | https://github.com/vercel/next.js/tree/canary/examples/with-docker | +| Create Docker Image of a Next.js app | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ | diff --git a/www/src/pages/vi/deployment/index.astro b/www/src/pages/vi/deployment/index.astro new file mode 100644 index 0000000000..22aec56d1d --- /dev/null +++ b/www/src/pages/vi/deployment/index.astro @@ -0,0 +1,24 @@ +--- +import IndexPage from "../../../components/docs/indexPage.astro"; +import { SIDEBAR, type Frontmatter } from "../../../config"; +import { getLanguageFromURL } from "../../../languages"; +import Layout from "../../../layouts/docs.astro"; + +const frontmatter: Frontmatter = { + title: "Deployment", + layout: "docs", + description: "Learn how to deploy your T3 app to production.", +}; + +const lang = getLanguageFromURL(Astro.url.pathname); +const sidebarEntries = SIDEBAR[lang]["Deployment"]!; +const files = await Astro.glob("./*.{md,mdx,astro}"); +--- + + + + diff --git a/www/src/pages/vi/deployment/netlify.mdx b/www/src/pages/vi/deployment/netlify.mdx new file mode 100644 index 0000000000..f794bdea5a --- /dev/null +++ b/www/src/pages/vi/deployment/netlify.mdx @@ -0,0 +1,93 @@ +--- +title: Netlify +description: Deploying to Netlify +layout: ../../../layouts/docs.astro +lang: en +isMdx: true +--- + +import Callout from "../../../components/docs/callout.tsx"; + +Netlify is an alternative deployment provider in a similar vein to Vercel. See [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) for an example repo based on this doc. + +## Why Host on Netlify + +Conventional wisdom says Vercel has superior Next.js support because Vercel develops Next.js. They have a vested interest in ensuring the platform is tuned for optimal performance and DX with Next.js. For the majority of use cases, this will be true and it won't make sense to deviate from the standard path. + +There's also a common sentiment that many Next.js features are only supported on Vercel. While it's true that new Next.js features will be tested and supported on Vercel at the time of release by default, it's also the case that other providers like Netlify will [quickly implement and release support](https://www.netlify.com/blog/deploy-nextjs-13/) for [stable Next.js features](https://docs.netlify.com/integrations/frameworks/next-js/overview/). + +There are relative pros and cons for all deployment providers since no single host can have the best support for all use cases. For example, Netlify built their own [custom Next.js runtime](https://github.com/netlify/next-runtime) for Netlify's Edge Functions (which run on Deno Deploy) and [maintain unique middleware to access and modify HTTP responses](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify). + + + To track the status of non-stable Next 13 features see [Using the Next 13 + `app` directory on + Netlify](https://github.com/netlify/next-runtime/discussions/1724). + + +## Project Configuration + +There are numerous ways to configure your build instructions including directly through the Netlify CLI or Netlify dashboard. While not required, it is advisable to create and include a [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/) file. This ensures that forked and cloned versions of the project will be easier to reproducibly deploy. + +```toml +[build] + command = "next build" + publish = ".next" +``` + +## Using the Netlify Dashboard + +1. Push your code to a GitHub repository and sign up for [Netlify](https://app.netlify.com/signup). After you've created an account, click on **Add new site** and then **Import an existing project**. + +![New project on Netlify](/images/netlify-01-new-project.webp) + +2. Connect your Git provider. + +![Import repository](/images/netlify-02-connect-to-git-provider.webp) + +3. Select your project's repository. + +![Select your project's repository](/images/netlify-03-pick-a-repository-from-github.webp) + +4. Netlify will detect if you have a `netlify.toml` file and automatically configure your build command and publish directory. + +![Nextjs build settings](/images/netlify-04-configure-build-settings.webp) + +5. Click **Show advanced** and then **New variable** to add your environment variables. + +![Add environment variables](/images/netlify-05-env-vars.webp) + +6. Click **Deploy site**, wait for the build to complete, and view your new site. + +## Using the Netlify CLI + +To deploy from the command line you must first push your project to a GitHub repo and [install the Netlify CLI](https://docs.netlify.com/cli/get-started/). You can install `netlify-cli` as a project dependency or install it globally on your machine with the following command: + +```bash +npm i -g netlify-cli +``` + +To test your project locally, run the [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) command and open [`localhost:8888`](http://localhost:8888/) to view your locally running Netlify app: + +```bash +ntl dev +``` + +Run the [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) command to configure your project: + +```bash +ntl init +``` + +Import your project's environment variables from your `.env` file with [`ntl env:import`](https://cli.netlify.com/commands/env#envimport): + +```bash +ntl env:import .env +``` + +Deploy your project with [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). You'll need to pass the `--build` flag to run the build command before deployment and the `--prod` flag to deploy to your site's main URL: + +```bash +ntl deploy --prod --build +``` + +To view a running example on Netlify, visit [ct3a.netlify.app](https://ct3a.netlify.app/). diff --git a/www/src/pages/vi/deployment/vercel.md b/www/src/pages/vi/deployment/vercel.md new file mode 100644 index 0000000000..a9ee5344fd --- /dev/null +++ b/www/src/pages/vi/deployment/vercel.md @@ -0,0 +1,62 @@ +--- +title: Vercel +description: Deploying to Vercel +layout: ../../../layouts/docs.astro +lang: en +--- + +We recommend deploying your app to [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). It makes it super easy to deploy Next.js apps. + +## Project Configuration + +Vercel will likely configure your build command and publish the directory automatically. However, you can also specify this information along with other configurations by creating a file called [`vercel.json`](https://vercel.com/docs/project-configuration) and including the following commands. **This is not required for most projects.** + +```json +{ + "buildCommand": "npm run build", + "devCommand": "npm run dev", + "installCommand": "npm install" +} +``` + +## Using the Vercel Dashboard + +1. After pushing your code to a GitHub repository, sign up for [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) with GitHub and click on **Add New Project**. + +![New project on Vercel](/images/vercel-new-project.webp) + +2. Import the GitHub repository with your project. + +![Import repository](/images/vercel-import-project.webp) + +3. Add your environment variables. + +![Add environment variables](/images/vercel-env-vars.webp) + +4. Click **Deploy**. Now whenever you push a change to your repository, Vercel will automatically redeploy your app! + +## Using the Vercel CLI + +To deploy from the command line you must first [install the Vercel CLI globally](https://vercel.com/docs/cli#installing-vercel-cli). + +```bash +npm i -g vercel +``` + +Run the [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) command to deploy your project. + +```bash +vercel +``` + +Include `--env DATABASE_URL=YOUR_DATABASE_URL_HERE` for environment variables like the database connection string. Use `--yes` if you want to skip the deployment questions and give the default answer for each. + +```bash +vercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes +``` + +After the first deployment, this command will deploy to a preview branch. You will need to include `--prod` to push changes directly to the live site for future deployments. + +```bash +vercel --prod +``` diff --git a/www/src/pages/vi/examples.mdx b/www/src/pages/vi/examples.mdx new file mode 100644 index 0000000000..bc7e45fb62 --- /dev/null +++ b/www/src/pages/vi/examples.mdx @@ -0,0 +1,22 @@ +--- +title: Examples +description: Examples of different live apps +layout: ../../layouts/docs.astro +lang: en +isMdx: true +--- + +import Callout from "../../components/docs/callout.tsx"; +import Form from "../../components/docs/exampleOptionForm.astro"; + +You can try out different combinations of technologies that create-t3-app offers. + + + You cannot select `prisma` and `drizzle` at the same time. + + +
+ + + Some features might not work unless you create an env file + diff --git a/www/src/pages/vi/faq.mdx b/www/src/pages/vi/faq.mdx new file mode 100644 index 0000000000..b90a5b1587 --- /dev/null +++ b/www/src/pages/vi/faq.mdx @@ -0,0 +1,78 @@ +--- +title: FAQ +description: Frequently asked questions about Create T3 App +layout: ../../layouts/docs.astro +lang: en +isMdx: true +--- + +import Callout from "../../components/docs/callout.tsx"; + +Here are some commonly asked questions about Create T3 App. + +## What's next? How do I make an app with this? + +We try to keep this project as simple as possible, so you can start with just the scaffolding we set up for you, and add additional things later when they become necessary. + +If you are not familiar with the different technologies used in this project, please refer to the respective docs. If you still are in the wind, please join our [Discord](https://t3.gg/discord) and ask for help. + +- [Next.js](https://nextjs.org/) +- [NextAuth.js](https://next-auth.js.org) +- [Prisma](https://prisma.io) +- [Tailwind CSS](https://tailwindcss.com) +- [tRPC](https://trpc.io) +- [Drizzle](https://orm.drizzle.team/docs/overview) + +## How do I keep my app up to date? + +Create T3 App is a scaffolding tool, not a framework. This means that once you initialize an app, it's yours. There is no postinstall CLI tool similar to help you stay up to date. If you want to keep track of any improvements we make to the template, you could [enable notifications for releases](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository) on our repository. That being said it is not really necessary to implement every change we make to the template in your app. + +## What learning resources are currently available? + +Although the resources listed below are some of the best that exist for the T3 Stack, the community (and [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) recommend that you just start using the stack and learn along the way by building with it. + +If you are considering Create T3 App, chances are you might have already used some of the parts of the stack. So why not just dive in head first and learn the other parts while you build something? + +Now, we realize this path doesn't work for everyone. So, if you feel like you've tried the recommendation and would still like some resources, or you just aren't confident doing it by yourself and/or feel overwhelmed by the stack, checkout these awesome tutorials on Create T3 App: + +### Articles + +Some of these might be outdated. + +- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f) +- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo) +- [Integrating Stripe into your T3 App](https://blog.nickramkissoon.com/posts/integrate-stripe-t3) + +### Videos + +- [From 0 to Production - The Modern React Tutorial (RSCs, Next.js, Shadui, Drizzle, TS and more)](https://www.youtube.com/watch?v=d5x0JCZbAJs) **(recommended)** (updated 2024)* +- [Jack Herrington - Build a Note Taking app with the T3 Stack](https://www.youtube.com/watch?v=J1gzN1SAhyM) +- [Build a Twitter Clone with the T3 Stack - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80) +- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY) +- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk) +- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI) +- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU) + +## Why are there `.js` files in the project? + +As per [T3-Axiom #3](/en/introduction#typesafety-isnt-optional), we treat typesafety as a first class citizen. Unfortunately, not all frameworks and plugins support TypeScript which means some of the configuration files have to be `.js` files. + +We try to emphasize that these files are JavaScript for a reason, by explicitly declaring each file's type (`cjs` or `mjs`) depending on what's supported by the library it is used by. Also, all the `js` files in this project are still typechecked using a checkJs option in the compiler (tsconfig). + +## I'm struggling to add i18n to my app. Is there any reference I can use? + +We have decided against including i18n by default in `create-t3-app` because it's a very opinionated topic and there are many ways to implement it. + +However, if you struggle to implement it and want to see a reference project, we have a [reference repo](https://github.com/juliusmarminge/t3-i18n) that shows how you can add i18n to a T3 App using [next-i18next](https://github.com/i18next/next-i18next). + +## Should I use `/app` from Next.js 13 or the more mature `/pages` paradigm? + +You have the option when scaffolding an app using Create T3 App to opt into the `/app` directory structure. As of the time of writing, this feature is generally considered mature enough to be used in production by the T3 stack community. For an explanation of why it took us so long to include, you can watch [this video](https://www.youtube.com/watch?v=PmBfq-SpzCU). + +Nevertheless, if you strongly prefer to use the old `/pages` paradigm, that's still an option. Porting over your existing router can be a monumental effort, so do not feel undue pressure to do so unnecessarily. + + + For a list of supported, planned, and worked on features in the `/app` dir, + visit the [beta Next.js + docs](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features). + diff --git a/www/src/pages/vi/folder-structure-app.mdx b/www/src/pages/vi/folder-structure-app.mdx new file mode 100644 index 0000000000..e0f3d77b85 --- /dev/null +++ b/www/src/pages/vi/folder-structure-app.mdx @@ -0,0 +1,254 @@ +--- +title: Folder Structure (App) +description: Folder structure of a newly scaffolded T3 App with the App Router +layout: ../../layouts/docs.astro +lang: en +isMdx: true +--- + +import Diagram from "../../components/docs/folderStructureDiagramApp.astro"; +import Form from "../../components/docs/folderStructureForm.astro"; + +Please select your packages to see the folder structure of a newly scaffolded app with those selections. Further down, you will find a description of each entry. + + + + + +
+ +### `prisma` + +The `prisma` folder contains the `schema.prisma` file which is used to configure the database connection and the database schema. It is also the location to store migration files and/or seed scripts, if used. See [Prisma usage](/en/usage/prisma) for more information. + +
+
+ +### `public` + +The `public` folder contains static assets that are served by the web server. The `favicon.ico` file is an example of a static asset. + +
+
+ +### `src/env` + +Used for environment variable validation and type definitions - see [Environment Variables](usage/env-variables). + +
+
+ +### `src/app` + +The `app` folder contains all the routes of the Next.js application. The `page.tsx` file at the root directory of `/app` is the homepage of the application. The `layout.tsx` file is used to wrap the application with providers. See [Next.js documentation](https://nextjs.org/docs/basic-features/pages) for more information. + +
+
+ +#### `src/app/_components/post.tsx` + +The `post.tsx` file is an example of a client component that calls a tRPC mutation. + +
+
+ +#### `src/app/api/auth/[...nextauth]/route.ts` + +The `[...nextauth]/route.ts` file is the NextAuth.js authentication slug route. It is used to handle authentication requests. See [NextAuth.js usage](usage/next-auth) for more information on NextAuth.js, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) for info on catch-all/slug routes. + +
+
+ +#### `src/app/api/trpc/[trpc]/route.ts` + +The `[trpc].ts` file is the tRPC API entrypoint. It is used to handle tRPC requests. See [tRPC usage](usage/trpc#-pagesapitrpctrpcts) for more information on this file, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/app/routing/dynamic-routes) for info on catch-all/slug routes. + +
+
+ +### `src/server` + +The `server` folder is used to clearly separate code that is only used on the server. + +
+
+ +#### `src/server/auth.ts` + +The main entrypoint for server-side authentication logic. Here, we setup the NextAuth.js [configuration options](usage/next-auth), perform [module augmentation](usage/next-auth#inclusion-of-userid-on-the-session) as well as provide some DX utilities for authentication such as retrieving the user's session on the server-side. See [NextAuth.js usage](usage/next-auth#usage-with-trpc) for more information. + +
+
+ +#### `src/server/db.ts` + +The `db.ts` file is used to instantiate the Prisma client at global scope. See [Prisma usage](usage/prisma#prisma-client) and [best practices for using Prisma with Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) for more information. + +
+
+ +### `src/server/db` + +The `db` folder contains the Drizzle client and schema. Note that drizzle also requires the `drizzle.config.ts` file (see below). + +
+
+ +#### `src/server/db/index.ts` + +The `index.ts` file is used to instantiate the Drizzle client at global scope. See [Drizzle usage](usage/drizzle#drizzle-client) for more information. + +
+
+ +#### `src/server/db/schema.ts` + +The `schema.ts` file is used to define the database schema. See [Drizzle usage](usage/drizzle#drizzle-client) and [Drizzle schema docs](https://orm.drizzle.team/docs/sql-schema-declaration) for more information. + +
+
+ +### `src/server/api` + +The `api` folder contains the tRPC server-side code. + +
+
+ +#### `src/server/api/routers` + +The `routers` folder contains all your tRPC sub-routers. + +
+
+ +#### `src/server/api/routers/example.ts` + +The `example.ts` file is an example tRPC router utilizing the `publicProcedure` helper to demonstrate how to create a public tRPC route. + +Depending on your chosen packages this router contains more or less routes to best demonstrate the usage to your needs. + +
+
+ +#### `src/server/api/trpc.ts` + +The `trpc.ts` file is the main configuration file for your tRPC back-end. In here we: + +1. Define context used in tRPC requests. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information. +2. Export procedure helpers. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information. + +
+ +
+ +#### `src/server/api/root.ts` + +The `root.ts` file is used to merge tRPC routers and export them as a single router, as well as the router's type definition. See [tRPC usage](usage/trpc#-serverapirootts) for more information. + +
+
+ +### `src/trpc` + +The `trpc` folder contains the setup to let you call tRPC procedures from server components and client components. + +
+
+ +#### `src/trpc/query-client.ts` + +The `query-client.ts` file creates the Query Client that tRPC uses to cache and deduplicate data in client components. + +
+
+ +#### `src/trpc/react.tsx` + +The `react.tsx` file is the front-end entrypoint to tRPC. It also contains utility types for the router inputs and outputs. See [tRPC usage](usage/trpc#-utilsapits) for more information. + +
+
+ +#### `src/trpc/server.ts` + +The `server.ts` file is the entrypoint for using tRPC in Server Components. + +
+
+ +### `.env` + +The `.env` file is used to store environment variables. See [Environment Variables](usage/env-variables) for more information. This file should **not** be committed to git history. + +
+
+ +### `.env.example` + +The `.env.example` file shows example environment variables based on the chosen libraries. This file should be committed to git history. + +
+
+ +### `.eslintrc.cjs` + +The `.eslintrc.cjs` file is used to configure ESLint. See [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) for more information. + +
+
+ +### `db.sqlite (sqlite only)` + +The `db.sqlite` file contains your development database. This file is only created after running the `db:push` parseCommandLine, and ignored by git. + +
+
+ +### `drizzle.config.ts` + +The `drizzle.config.ts` file is used to configure drizzle kit. See [the documentation](https://orm.drizzle.team/kit-docs/config-reference) for more information. + +
+
+ +### `next-env.d.ts` + +The `next-env.d.ts` file ensures Next.js types are picked up by the TypeScript compiler. **You should not remove it or edit it as it can change at any time.** See [Next.js Docs](https://nextjs.org/docs/app/building-your-application/configuring/typescript) for more information. + +
+
+ +### `next.config.mjs` + +The `next.config.mjs` file is used to configure Next.js. See [Next.js Docs](https://nextjs.org/docs/api-reference/next.config.js/introduction) for more information. Note: The .mjs extension is used to allow for ESM imports. + +
+
+ +### `postcss.config.js` + +The `postcss.config.js` file is used for Tailwind PostCSS usage. See [Tailwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss) for more information. + +
+
+ +### `prettier.config.mjs` + +The `prettier.config.mjs` file is used to configure Prettier to include the prettier-plugin-tailwindcss for formatting Tailwind CSS classes. See the [Tailwind CSS blog post](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) for more information. + +
+
+ +### `start-database.sh (mysql or postgres only)` + +The `start-database.sh` file is used to start the database. Please see the comments inside the file for information on how to start the database with your operating system. + +
+
+ +### `tsconfig.json` + +The `tsconfig.json` file is used to configure TypeScript. Some non-defaults, such as `strict mode`, have been enabled to ensure the best usage of TypeScript for Create T3 App and its libraries. See [TypeScript Docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) or [TypeScript Usage](usage/typescript) for more information. + +
diff --git a/www/src/pages/vi/folder-structure-pages.mdx b/www/src/pages/vi/folder-structure-pages.mdx new file mode 100644 index 0000000000..a9c49aed4d --- /dev/null +++ b/www/src/pages/vi/folder-structure-pages.mdx @@ -0,0 +1,247 @@ +--- +title: Folder Structure (Pages) +description: Folder structure of a newly scaffolded T3 App with the Pages Router +layout: ../../layouts/docs.astro +lang: en +isMdx: true +--- + +import Diagram from "../../components/docs/folderStructureDiagramPages.astro"; +import Form from "../../components/docs/folderStructureForm.astro"; + +Please select your packages to see the folder structure of a newly scaffolded app with those selections. Further down, you will find a description of each entry. + + + + + +
+ +### `prisma` + +The `prisma` folder contains the `schema.prisma` file which is used to configure the database connection and the database schema. It is also the location to store migration files and/or seed scripts, if used. See [Prisma usage](/en/usage/prisma) for more information. + +
+
+ +### `public` + +The `public` folder contains static assets that are served by the web server. The `favicon.ico` file is an example of a static asset. + +
+
+ +### `src/env` + +Used for environment variable validation and type definitions - see [Environment Variables](usage/env-variables). + +
+
+ +### `src/pages` + +The `pages` folder contains all the pages of the Next.js application. The `index.tsx` file at the root directory of `/pages` is the homepage of the application. The `_app.tsx` file is used to wrap the application with providers. See [Next.js documentation](https://nextjs.org/docs/basic-features/pages) for more information. + +
+
+ +#### `src/pages/api` + +The `api` folder contains all the API routes of the Next.js application. See [Next.js Api Routes Docs](https://nextjs.org/docs/api-routes/introduction) for info on api routes. + +
+
+ +#### `src/pages/api/auth/[...nextauth].ts` + +The `[...nextauth].ts` file is the NextAuth.js authentication slug route. It is used to handle authentication requests. See [NextAuth.js usage](usage/next-auth) for more information on NextAuth.js, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) for info on catch-all/slug routes. + +
+
+ +#### `src/pages/api/trpc/[trpc].ts` + +The `[trpc].ts` file is the tRPC API entrypoint. It is used to handle tRPC requests. See [tRPC usage](usage/trpc#-pagesapitrpctrpcts) for more information on this file, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) for info on catch-all/slug routes. + +
+
+ +### `src/server` + +The `server` folder is used to clearly separate code that is only used on the server. + +
+
+ +#### `src/server/auth.ts` + +The main entrypoint for server-side authentication logic. Here, we setup the NextAuth.js [configuration options](usage/next-auth), perform [module augmentation](usage/next-auth#inclusion-of-userid-on-the-session) as well as provide some DX utilities for authentication such as retrieving the user's session on the server-side. See [NextAuth.js usage](usage/next-auth#usage-with-trpc) for more information. + +
+
+ +#### `src/server/db.ts` + +The `db.ts` file is used to instantiate the Prisma client at global scope. See [Prisma usage](usage/prisma#prisma-client) and [best practices for using Prisma with Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) for more information. + +
+
+ +### `src/server/db` + +The `db` folder contains the Drizzle client and schema. Note that drizzle also requires the `drizzle.config.ts` file (see below). + +
+
+ +#### `src/server/db/index.ts` + +The `index.ts` file is used to instantiate the Drizzle client at global scope. See [Drizzle usage](usage/drizzle#drizzle-client) for more information. + +
+
+ +#### `src/server/db/schema.ts` + +The `schema.ts` file is used to define the database schema. See [Drizzle usage](usage/drizzle#drizzle-client) and [Drizzle schema docs](https://orm.drizzle.team/docs/sql-schema-declaration) for more information. + +
+
+ +### `src/server/api` + +The `api` folder contains the tRPC server-side code. + +
+
+ +#### `src/server/api/routers` + +The `routers` folder contains all your tRPC sub-routers. + +
+
+ +#### `src/server/api/routers/example.ts` + +The `example.ts` file is an example tRPC router utilizing the `publicProcedure` helper to demonstrate how to create a public tRPC route. + +Depending on your chosen packages this router contains more or less routes to best demonstrate the usage to your needs. + +
+
+ +#### `src/server/api/trpc.ts` + +The `trpc.ts` file is the main configuration file for your tRPC back-end. In here we: + +1. Define context used in tRPC requests. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information. +2. Export procedure helpers. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information. + +
+ +
+ +#### `src/server/api/root.ts` + +The `root.ts` file is used to merge tRPC routers and export them as a single router, as well as the router's type definition. See [tRPC usage](usage/trpc#-serverapirootts) for more information. + +
+
+ +### `src/styles` + +The `styles` folder contains the global styles of the application. + +
+
+ +### `src/utils` + +The `utils` folder is used to store commonly re-used utility functions. + +
+
+ +#### `src/utils/api.ts` + +The `api.ts` file is the front-end entrypoint to tRPC. See [tRPC usage](usage/trpc#-utilsapits) for more information. + +
+
+ +### `.env` + +The `.env` file is used to store environment variables. See [Environment Variables](usage/env-variables) for more information. This file should **not** be committed to git history. + +
+
+ +### `.env.example` + +The `.env.example` file shows example environment variables based on the chosen libraries. This file should be committed to git history. + +
+
+ +### `.eslintrc.cjs` + +The `.eslintrc.cjs` file is used to configure ESLint. See [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) for more information. + +
+
+ +### `db.sqlite (sqlite only)` + +The `db.sqlite` file contains your development database. This file is only created after running the `db:push` parseCommandLine, and ignored by git. + +
+
+ +### `drizzle.config.ts` + +The `drizzle.config.ts` file is used to configure drizzle kit. See [the documentation](https://orm.drizzle.team/kit-docs/config-reference) for more information. + +
+
+ +### `next-env.d.ts` + +The `next-env.d.ts` file ensures Next.js types are picked up by the TypeScript compiler. **You should not remove it or edit it as it can change at any time.** See [Next.js Docs](https://nextjs.org/docs/basic-features/typescript#existing-projects) for more information. + +
+
+ +### `next.config.mjs` + +The `next.config.mjs` file is used to configure Next.js. See [Next.js Docs](https://nextjs.org/docs/api-reference/next.config.js/introduction) for more information. Note: The .mjs extension is used to allow for ESM imports. + +
+
+ +### `postcss.config.js` + +The `postcss.config.js` file is used for Tailwind PostCSS usage. See [Tailwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss) for more information. + +
+
+ +### `prettier.config.mjs` + +The `prettier.config.mjs` file is used to configure Prettier to include the prettier-plugin-tailwindcss for formatting Tailwind CSS classes. See the [Tailwind CSS blog post](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) for more information. + +
+
+ +### `start-database.sh (mysql or postgres only)` + +The `start-database.sh` file is used to start the database. Please see the comments inside the file for information on how to start the database with your operating system. + +
+
+ +### `tsconfig.json` + +The `tsconfig.json` file is used to configure TypeScript. Some non-defaults, such as `strict mode`, have been enabled to ensure the best usage of TypeScript for Create T3 App and its libraries. See [TypeScript Docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) or [TypeScript Usage](usage/typescript) for more information. + +
diff --git a/www/src/pages/vi/installation.mdx b/www/src/pages/vi/installation.mdx new file mode 100644 index 0000000000..34d183f1a5 --- /dev/null +++ b/www/src/pages/vi/installation.mdx @@ -0,0 +1,83 @@ +--- +title: Installation +description: Installation instructions for Create T3 App +layout: ../../layouts/docs.astro +lang: en +isMdx: true +--- + +import Callout from "../../components/docs/callout.tsx"; + +To scaffold an app using `create-t3-app`, run any of the following commands and answer the command prompt questions: + +### npm + +```bash +npm create t3-app@latest +``` + +### yarn + +```bash +yarn create t3-app +``` + +### pnpm + +```bash +pnpm create t3-app@latest +``` + +### bun + +```bash +bun create t3-app@latest +``` + +After your app has been scaffolded, check out the [first steps](/en/usage/first-steps) to get started on your new application. + +## Advanced usage + +| Option/Flag | Description | +| ----------------- | ----------------------------------------------------------------------- | +| `[dir]` | Include a directory argument with a name for the project | +| `--noGit` | Explicitly tell the CLI to not initialize a new git repo in the project | +| `-y`, `--default` | Bypass the CLI and bootstrap a new t3-app with all options selected | +| `--noInstall` | Generate project without installing dependencies | + +## Experimental usage + +For our CI, we have some experimental flags that allow you to scaffold any app without any prompts. If this use case applies to you, you can use these flags. Please note that these flags are experimental and may change in the future without following semver versioning. + +| Flag | Description | +| ------------------------- | -------------------------------------------- | +| `--CI` | Let the CLI know you're in CI mode | +| `--trpc` | Include tRPC in the project | +| `--prisma` | Include Prisma in the project | +| `--drizzle` | Include Drizzle in the project | +| `--nextAuth` | Include NextAuth.js in the project | +| `--tailwind` | Include Tailwind CSS in the project | +| `--dbProvider [provider]` | Include a configured database in the project | +| `--appRouter` | Use Next.js App Router in the project | + + + If you don't provide the `CI` flag, the rest of these flags have no effect. + + +You don't need to explicitly opt-out of the packages you don't want. However, if you prefer to be explicit, you can pass `false`, e.g. `--nextAuth false`. + +The --dbProvider command has 4 database values to choose from: mysql, postgres, planetscale, sqlite. If the command is not provided the default value will be sqlite. + +### Example + +The following would scaffold a T3 App with tRPC and Tailwind CSS. + +```bash +pnpm dlx create-t3-app@latest --CI --trpc --tailwind +``` + +The following would scaffold a T3 App with NextAuth.js, Tailwind CSS, Drizzle, and PostgreSQL. + +```bash +pnpm dlx create-t3-app@latest --CI --nextAuth --tailwind --drizzle --dbProvider postgres +``` diff --git a/www/src/pages/vi/introduction.mdx b/www/src/pages/vi/introduction.mdx new file mode 100644 index 0000000000..02ee650fdb --- /dev/null +++ b/www/src/pages/vi/introduction.mdx @@ -0,0 +1,41 @@ +--- +title: Giới thiệu +description: Giới thiệu về T3 Stack +layout: ../../layouts/docs.astro +lang: vi +--- + +import { IntroductionTab } from "../../components/docs/introductionTab"; + + +## T3 Stack + +_"T3 Stack"_ là một stack dùng để phát triển web được tạo bởi [Theo](https://twitter.com/t3dotgg), nó tập trung vào sự đơn giản, mô-đun hóa và đảm bảo tính toàn vẹn của kiểu dữ liệu trong lập trình full-stack. + +T3 Stack được xây dựng dựa trên [**Next.js**](https://nextjs.org/) và [**TypeScript**](https://typescriptlang.org/). [**Tailwind CSS**](https://tailwindcss.com/) thường được dùng để thiết kế giao diện người dùng. Và nếu bạn đang làm bất cứ điều gì liên quan đến backend, đừng lo, hãy để [**tRPC**](https://trpc.io/), [**Prisma**](https://prisma.io/), và [**NextAuth.js**](https://next-auth.js.org/) là những "món ăn" kèm theo tuyệt vời. + +Bạn có thể thấy rằng stack này có nhiều phần khác nhau. Cái này chính là điểm mạnh của nó. Bạn có thể thêm hoặc bớt các phần theo nhu cầu của bạn - vì stack này được thiết kế mô-đun hóa ở mức cơ sở :) + +## Vậy... create-t3-app là gì? Là một template sao? + +Bạn cũng có thể coi là như vậy? `create-t3-app` là một CLI được xây dựng bởi các nhà phát triển T3 Stack dày dạn kinh nghiệm để hợp lý hóa việc thiết lập một ứng dụng T3 Stack dạng mô-đun. Chính vì vậy, bạn có thể thêm hoặc bớt các phần theo nhu cầu của bạn, và "template" được tạo ra để đáp ứng trên nhu cầu cụ thể của bạn. + +Sau vô số dự án và nhiều năm làm việc với công nghệ này, chúng tôi có rất nhiều kiến thức, kinh nghiệm và trải nghiệm sâu sắc với những công nghệ này. Chính vì vậy, chúng tôi đã cố gắng hết sức để "gộp" chúng vào chiếc CLI này. + +Hãy lưu ý rằng, đây **KHÔNG** phải là một template bao gồm tất cả mọi thứ. Chúng tôi **khuyến khích** bạn sẽ mang các thư viện của riêng mình vào T3 Stack để giải quyết nhu cầu của ứng dụng **CỦA BẠN**. Mặc dù chúng tôi không ràng buộc các giải pháp cho các vấn đề cụ thể hơn như quản lý trạng thái và triển khai, nhưng chúng tôi [có một số khuyến nghị được liệt kê ở đây](/vi/other-recs). + +## Các Nguyên tắc của T3 + +Chúng tôi sẽ thẳng thắn - đây là một dự án _có chính kiến_. Chúng tôi chia sẻ một số niềm tin cốt lõi về việc xây dựng và chúng tôi coi chúng là cơ sở cho các quyết định của mình. + +### Giải quyết Vấn đề + +Bạn có thể sẽ dễ rơi vào cái bẫy "thêm mọi thứ" - chúng tôi rõ ràng không muốn điều đó xảy ra. Vì vậy, những công nghệ được tích hợp vào trong `create-t3-app` sẽ được sử dụng để giải quyết những vấn đề hiễn hữu còn có trong những công nghệ chủ đạo. Điều này có nghĩa là chúng tôi sẽ không thêm những thứ như thư viện quản lý trạng thái (`zustand`, `redux`), thay vì đó, chúng tôi sẽ thêm những thứ như NextAuth.js và tích hợp Prisma và tRPC cho bạn. + +### Chuyển đổi công nghệ một cách Có Trách nhiệm (Bleed Responsibly) + +Chúng tôi yêu thích những công nghệ tiên tiến (bleeding edge). Vì nó nhanh và, thành thật mà nói, niềm vui đến từ những thứ mới mẻ thực sự rất tuyệt. Chúng tôi nghĩ rằng chuyển đổi công nghệ một cách có trách nhiệm (Bleed Responsibly) là một điều quan trọng, sử dụng công nghệ rủi ro hơn để bù đắp những phần ít rủi ro hơn. Và đồng thời, chúng tôi sẽ không ⛔️ tất tay vào công nghệ cơ sở dữ liệu mới đầy rủi ro (Tôi yêu SQL!). Nhưng chúng tôi rất vui vẻ ✅ "tất tay" vào tRPC vì bản chất nó chỉ là các hàm và nó cũng không mất nhiều cônng sức để chuyển đổi khỏi nó. + +### Đảm bảo Tính Toàn Vẹn của Kiểu dữ liệu (Typesafety) Không Phải Là Tùy Chọn + +Mục tiêu đã nêu của Create T3 App là cung cấp cách nhanh nhất để bắt đầu một ứng dụng web full-stack mà vẫn đảm bảo **tính toàn vẹn của kiểu dữ liệu (typesafe)** . Chúng tôi rất coi trọng việc đảm bảo tính toàn vẹn của kiểu dữ liệu vì nó cải thiện năng suất của chúng tôi và giúp chúng tôi gặp ít lỗi hơn khi phát hành. Bất kỳ quyết định nào mà không tuân thủ tính toàn vẹn của kiểu dữ liệu của Create T3 App là một quyết định nên được thực hiện trong một dự án khác. diff --git a/www/src/pages/vi/other-recs.md b/www/src/pages/vi/other-recs.md new file mode 100644 index 0000000000..ae774aac2c --- /dev/null +++ b/www/src/pages/vi/other-recs.md @@ -0,0 +1,169 @@ +--- +title: Other Recommendations +description: Libraries and Services that we recommend for many projects +layout: ../../layouts/docs.astro +lang: en +--- + +We recognize that the libraries included in `create-t3-app` don't solve every problem. While we encourage you to begin your project with the things that we provide, there will come a time when you need to bring in other packages. Only you can know what your project needs, but here are some things that we find ourselves recommending frequently. + +These are recommendations by individual Create T3 App contributors and should not be seen as "official" endorsements by the Create T3 App team or T3-OSS. _**Please do your own research, especially before committing to paid services**_. + +## State Management + +_**Editor's Note**_: State management libraries can be great, but often aren't necessary. tRPC's React Query hooks should be able to take care of your server state. For client state, start with React's `useState`, and reach for one of these options when you need more. + +### Zustand + +**For never using Redux again** + +The "modern, simple Redux" you didn't know you needed. [Poimandres](https://github.com/pmndrs) can always be trusted. You can build everything from video call apps to games to servers with this little library. + +- [Zustand Homepage](https://zustand-demo.pmnd.rs/) +- [Zustand GitHub](https://github.com/pmndrs/zustand) + +### Jotai + +**For never using Context again** + +For a more atomic approach, Jotai is hard to beat. Also by [Poimandres](https://github.com/pmndrs), Jotai lets you define singletons that feel like global useState. A great option for stateful behaviors that don't need a state machine just yet. + +- [Jotai Homepage](https://jotai.org/) +- [Jotai GitHub](https://github.com/pmndrs/jotai) + +## Component Libraries + +Most apps need the same handful of components - toggle buttons, dropdown menus, modals, and so on. These libraries provide great, accessible components that you can use and customize to your liking. + +### Unstyled Component Libraries + +Also known as headless libraries, they provide great unstyled, and accessible components that you can customize to your liking. Here are a few recommendations. + +- [Radix UI](https://www.radix-ui.com/) gives you a powerful set of convenient and accessible primitives that you can style with vanilla or Tailwind CSS. + +- [Headless UI](https://headlessui.com/) made by the Tailwind CSS team also provides unstyled, accessible components that integrate seamlessly with Tailwind CSS. + +- [React Aria](https://react-spectrum.adobe.com/react-aria/) provides accessible UI primitives for your design system. Their Date Picker component is top tier. + +### Styled Component Libraries + +**For when you just want your app to look OK** + +Sometimes you're building a project where you just want the UI to look decent out of the box. For Admin Dashboards and other similar projects, any of these component libraries will get the job done. + +- [Chakra UI](https://chakra-ui.com) +- [Mantine](https://mantine.dev) +- [@shadcn/ui](https://ui.shadcn.com/) + +### Class Variance Authority + +**For building UI Libraries** + +Declaratively build a UI Library with different color, size, etc. variants. When your project reaches a scale where you want a standardized set of UI components with multiple variants using Tailwind CSS, CVA is a great tool. + +- [Class Variance Authority GitHub](https://github.com/joe-bell/cva) + +## Animations + +For when you need animations in your app, here are our recommendations. + +### AutoAnimate + +**For animations with a single line of code** + +Most animation libraries try to satisfy every possible use case, and become clunky as a result. AutoAnimate is a zero-configuration tool that will give you a significant improvement in UX with no additional developer effort. + +- [AutoAnimate Homepage](https://auto-animate.formkit.com/) +- [AutoAnimate GitHub](https://github.com/formkit/auto-animate) +- [AutoAnimate Component Snippet](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb) + +### Framer Motion + +**For complex animations with declarative code** + +Framer Motion provides a simple, declarative syntax and allows you to write less code to craft everything from complex animations to even gestures. + +- [Framer Motion Homepage](https://framer.com/motion) +- [Framer Motion Documentation](https://www.framer.com/docs/) + +## Deployments, Infrastructure, Databases and CI + +### Vercel + +**For hosting your app** + +Vercel took the hell of web deployments and made it a set-and-forget GitHub integration. We've scaled to hundreds of thousands of users without issue. AWS-powered, just a way better interface :) + +- [Vercel Homepage](https://vercel.com/) +- [Create T3 App Vercel deployment guide](/en/deployment/vercel) + +### PlanetScale + +**For databases without the worry** + +PlanetScale is the best "serverless database platform" we've used by far. Insane scale, great developer experience, and fantastic pricing. If you're using SQL (and hopefully Prisma), this is hard to beat. + +- [PlanetScale Homepage](https://planetscale.com/) + +### Railway + +**For hosting your infra** + +"Modern Heroku". The easiest way to get a real server up and running. If Vercel and PlanetScale aren't enough, Railway probably is. Point it at a GitHub repo and go. + +- [Railway Homepage](https://railway.app/) + +### Upstash + +**For serverless Redis** + +We love Prisma and PlanetScale, but some projects require a more performant solution. Upstash allows you to get the in-memory performance of Redis in your serverless project, without having to manage the infrastructure and scaling yourself. + +- [Upstash Homepage](https://upstash.com/) + +### Pusher + +**For serverless WebSockets** + +If WebSockets are the primary focus of your project, you may want to consider a more traditional backend such as [Fastify](https://www.fastify.io/) (which [also works with tRPC!](https://trpc.io/docs/v10/fastify)). But for quickly adding WebSockets to a T3 App, Pusher is an excellent choice. + +- [Pusher Homepage](https://pusher.com/) + +### Soketi + +Soketi is a self-hostable, simple, and fast alternative to Pusher. It's fully compatible with the Pusher SDK which you can use to connect to the server. Soketi serverless is also in beta. + +- [Soketi Homepage](https://soketi.app) +- [Soketi GitHub](https://github.com/soketi/soketi) + +## Analytics + +User data is very valuable when you're building an app. Here are some analytics providers we recommend. + +### PostHog + +PostHog is a full-featured, open-source, and self-hostable solution for bringing in depth analytics to your product. They have SDKs for every library/framework imaginable. + +- [PostHog Homepage](https://posthog.com/) + +### Plausible + +Need analytics? Plausible is one of the quickest ways to get them. Super minimal. It even has a [simple plugin for Next.js](https://plausible.io/docs/proxy/guides/nextjs). + +- [Plausible Homepage](https://plausible.io/) + +### Umami + +Umami is an open-sourced, self-hostable, simple, fast, privacy-focused alternative to Google Analytics. You can deploy it really easily to Vercel, Railway, etc. with PlanetScale as your database or you can also use its cloud version. + +- [Umami Homepage](https://umami.is/) +- [Umami GitHub](https://github.com/umami-software/umami) +- [Umami Cloud](https://cloud.umami.is/) + +## Other + +### Next Bundle Analyzer + +It can sometimes be difficult to determine what will be included in the build output for your app. Next Bundle Analyzer is an easy way to visualize and analyze the JavaScript bundles that are generated. + +- [@next/bundle-analyzer on npm](https://www.npmjs.com/package/@next/bundle-analyzer) diff --git a/www/src/pages/vi/t3-collection.mdx b/www/src/pages/vi/t3-collection.mdx new file mode 100644 index 0000000000..8c8cfcb9b1 --- /dev/null +++ b/www/src/pages/vi/t3-collection.mdx @@ -0,0 +1,29 @@ +--- +title: T3 Collection +description: Cool open source projects and companies using the T3 stack +layout: ../../layouts/docs.astro +lang: en +isMdx: true +--- + +import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx"; +import CompanyList from "../../components/docs/companyList.tsx"; +import Callout from "../../components/docs/callout.tsx"; + +Made a project using the T3 stack and want to share it? Add it to the list! + +## Open Source apps made using the T3 Stack + + + +## Companies using the T3 Stack + +We'd love to know of companies that use the T3 stack for their apps. Is your company using the T3 stack and would like to share it? Add it to the list! + + + + + Have a cool project using the T3 stack? Make a [pull + request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx) + and add it here! + diff --git a/www/src/pages/vi/usage/_next-auth-app-router.mdx b/www/src/pages/vi/usage/_next-auth-app-router.mdx new file mode 100644 index 0000000000..b610105d13 --- /dev/null +++ b/www/src/pages/vi/usage/_next-auth-app-router.mdx @@ -0,0 +1,206 @@ +import Callout from "../../../components/docs/callout.tsx"; +import Tabs from "../../../components/docs/tabs.astro"; + + + The newest version of NextAuth has migrated to [Auth.js](https://authjs.dev/) + + +## Retrieving session server side + +Sometimes you might want to request the session on the server. To do so, use the `auth` helper function that `create-t3-app` provides. + +```tsx:app/page.tsx +import { auth } from "~/server/auth"; + +export default async function Home() { + const session = await auth(); + ... +} +``` + +## Inclusion of `user.id` on the Session + +Create T3 App is configured to utilise the [session callback](https://authjs.dev/guides/extending-the-session) in the NextAuth.js config to include the user's ID within the `session` object. + +```ts:server/auth/config.ts +callbacks: { + session: ({ session, user }) => ({ + ...session, + user: { + ...session.user, + id: user.id, + }, + }), + }, +``` + +This is coupled with a type declaration file to make sure the `user.id` is typed when accessed on the `session` object. Read more about [`Module Augmentation`](https://authjs.dev/getting-started/typescript#resources*module-augmentation) on NextAuth.js's docs. + +```ts:server/auth/config.ts +import { DefaultSession } from "next-auth"; + +declare module "next-auth" { + interface Session extends DefaultSession { + user: { + id: string; + } & DefaultSession["user"]; + } +``` + +The same pattern can be used to add any other data to the `session` object, such as a `role` field, but **should not be misused to store sensitive data** on the client. + +## Usage with tRPC + +When using NextAuth.js with tRPC, you can create reusable, protected procedures using [middleware](https://trpc.io/docs/v10/middlewares). This allows you to create procedures that can only be accessed by authenticated users. `create-t3-app` sets all of this up for you, allowing you to easily access the session object within authenticated procedures. + +This is done in a two step process: + +1. Pass the authentication session into the tRPC context: + +```ts:server/api/trpc.ts +import { auth } from "~/server/auth"; +import { db } from "~/server/db"; + +export const createTRPCContext = async (opts: { headers: Headers }) => { + const session = await auth(); + + return { + db, + session, + ...opts, + }; +}; +``` + +2. Create a tRPC middleware that checks if the user is authenticated. We then use the middleware in a `protectedProcedure`. Any caller to these procedures must be authenticated, or else an error will be thrown which can be appropriately handled by the client. + +```ts:server/api/trpc.ts +export const protectedProcedure = t.procedure + .use(({ ctx, next }) => { + if (!ctx.session?.user) { + throw new TRPCError({ code: "UNAUTHORIZED" }); + } + return next({ + ctx: { + session: { ...ctx.session, user: ctx.session.user }, + }, + }); + }); +``` + +The session object is a light, minimal representation of the user and only contains a few fields. When using the `protectedProcedures`, you have access to the user's id which can be used to fetch more data from the database. + +```ts:server/api/routers/user.ts +const userRouter = router({ + me: protectedProcedure.query(async ({ ctx }) => { + const user = await prisma.user.findUnique({ + where: { + id: ctx.session.user.id, + }, + }); + return user; + }), +}); +``` + +## Usage with a database provider + + +
+ Getting NextAuth.js to work with Prisma requires a lot of [initial + setup](https://authjs.dev/reference/adapter/prisma/). `create-t3-app` + handles all of this for you, and if you select both Prisma and NextAuth.js, + you'll get a fully working authentication system with all the required + models preconfigured. We ship your scaffolded app with a preconfigured + Discord OAuth provider, which we chose because it is one of the easiest to + get started with - just provide your tokens in the `.env` and you're good to + go. However, you can easily add more providers by following the [Auth.js + docs](https://authjs.dev/getting-started/authentication/oauth). Note that + certain providers require extra fields to be added to certain models. We + recommend you read the documentation for the provider you would like to use + to make sure you have all the required fields. +
+
+ Getting NextAuth.js to work with Drizzle requires a lot of [initial + setup](https://authjs.dev/getting-started/adapters/drizzle). `create-t3-app` + handles all of this for you, and if you select both Drizzle and NextAuth.js, + you'll get a fully working authentication system with all the required + models preconfigured. We ship your scaffolded app with a preconfigured + Discord OAuth provider, which we chose because it is one of the easiest to + get started with - just provide your tokens in the `.env` and you're good to + go. However, you can easily add more providers by following the [Auth.js + docs](https://authjs.dev/getting-started/authentication/oauth). Note that + certain providers require extra fields to be added to certain models. We + recommend you read the documentation for the provider you would like to use + to make sure you have all the required fields. +
+
+ +### Adding new fields to your models + +When adding new fields to any of the `User`, `Account`, `Session`, or `VerificationToken` models (most likely you'd only need to modify the `User` model), you need to keep in mind that the [Prisma adapter](https://authjs.dev/reference/adapter/prisma/) automatically creates fields on these models when new users sign up and log in. Therefore, when adding new fields to these models, you must provide default values for them, since the adapter is not aware of these fields. + +If for example, you'd like to add a `role` to the `User` model, you would need to provide a default value to the `role` field. This is done by adding a `@default` value to the `role` field in the `User` model: + +```diff:prisma/schema.prisma ++ enum Role { ++ USER ++ ADMIN ++ } + + model User { + ... ++ role Role @default(USER) + } +``` + +## Usage with Next.js middleware + +With Next.js 12+, the easiest way to protect a set of pages is using the [middleware file](https://authjs.dev/getting-started/session-management/protecting?framework=express#nextjs-middleware). You can create a middleware.ts file in your root pages directory with the following contents. + +```middleware.ts +export { auth as middleware } from "@/auth" +``` + +Then define authorized callback in your auth.ts file. For more details check out the [reference docs.](https://authjs.dev/reference/nextjs#authorized) + +```app/auth.ts +async authorized({ request, auth }) { + const url = request.nextUrl + + if(request.method === "POST") { + const { authToken } = (await request.json()) ?? {} + // If the request has a valid auth token, it is authorized + const valid = await validateAuthToken(authToken) + if(valid) return true + return NextResponse.json("Invalid auth token", { status: 401 }) + } + + // Logged in users are authenticated, otherwise redirect to login page + return !!auth.user +} +``` + + + You should not rely on middleware exclusively for authorization. Always ensure + that the session is verified as close to your data fetching as possible. + + +## Setting up the default DiscordProvider + +1. Head to [the Applications section in the Discord Developer Portal](https://discord.com/developers/applications), and click on "New Application" +2. In the settings menu, go to "OAuth2 => General" + +- Copy the Client ID and paste it in `DISCORD_CLIENT_ID` in `.env`. +- Under Client Secret, click "Reset Secret" and copy that string to `DISCORD_CLIENT_SECRET` in `.env`. Be careful as you won't be able to see this secret again, and resetting it will cause the existing one to expire. +- Click "Add Redirect" and paste in `/api/auth/callback/discord` (example for local development: http://localhost:3000/api/auth/callback/discord) +- Save your changes +- It is possible, but not recommended, to use the same Discord Application for both development and production. You could also consider [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) during development. + +## Useful Resources + +| Resource | Link | +| --------------------------------- | --------------------------------------- | +| NextAuth.js Docs | https://authjs.dev/ | +| NextAuth.js GitHub | https://github.com/nextauthjs/next-auth | +| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth | diff --git a/www/src/pages/vi/usage/_next-auth-pages.mdx b/www/src/pages/vi/usage/_next-auth-pages.mdx new file mode 100644 index 0000000000..7d21099805 --- /dev/null +++ b/www/src/pages/vi/usage/_next-auth-pages.mdx @@ -0,0 +1,218 @@ +import Callout from "../../../components/docs/callout.tsx"; + +## Context Provider + +In your app's entrypoint, you'll see that your application is wrapped in a [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider): + +```tsx:pages/_app.tsx + + + +``` + +This context provider allows your application to access the session data from anywhere in your application, without having to pass it down as props: + +```tsx:pages/users/[id].tsx +import { useSession } from "next-auth/react"; + +const User = () => { + const { data: session } = useSession(); + + if (!session) { + // Handle unauthenticated state, e.g. render a SignIn component + return ; + } + + return

Welcome {session.user.name}!

; +}; +``` + +## Retrieving session server-side + +Sometimes you might want to request the session on the server. To do so, prefetch the session using the `getServerAuthSession` helper function that `create-t3-app` provides, and pass it down to the client using `getServerSideProps`: + +```tsx:pages/users/[id].tsx +import { getServerAuthSession } from "../server/auth"; +import { type GetServerSideProps } from "next"; + +export const getServerSideProps: GetServerSideProps = async (ctx) => { + const session = await getServerAuthSession(ctx); + return { + props: { session }, + }; +}; + +const User = () => { + const { data: session } = useSession(); + // NOTE: `session` wont have a loading state since it's already prefetched on the server + + ... +} +``` + +## Inclusion of `user.id` on the Session + +Create T3 App is configured to utilise the [session callback](https://next-auth.js.org/configuration/callbacks#session-callback) in the NextAuth.js config to include the user's ID within the `session` object. + +```ts:server/auth.ts +callbacks: { + session({ session, user }) { + if (session.user) { + session.user.id = user.id; + } + return session; + }, + }, +``` + +This is coupled with a type declaration file to make sure the `user.id` is typed when accessed on the `session` object. Read more about [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) on NextAuth.js's docs. + +```ts:server/auth.ts +import { DefaultSession } from "next-auth"; + +declare module "next-auth" { + interface Session { + user?: { + id: string; + } & DefaultSession["user"]; + } +} +``` + +The same pattern can be used to add any other data to the `session` object, such as a `role` field, but **should not be misused to store sensitive data** on the client. + +## Usage with tRPC + +When using NextAuth.js with tRPC, you can create reusable, protected procedures using [middleware](https://trpc.io/docs/v10/middlewares). This allows you to create procedures that can only be accessed by authenticated users. `create-t3-app` sets all of this up for you, allowing you to easily access the session object within authenticated procedures. + +This is done in a two step process: + +1. Grab the session from the request headers using the [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession) function. The advantage of using `getServerSession` instead of the regular `getSession` is that it's a server-side only function and doesn't trigger unnecessary fetch calls. `create-t3-app` creates a helper function that abstracts this peculiar API away so that you don't need to import both your NextAuth.js options as well as the `getServerSession` function every time you need to access the session. + +```ts:server/auth.ts +export const getServerAuthSession = (ctx: { + req: GetServerSidePropsContext["req"]; + res: GetServerSidePropsContext["res"]; +}) => { + return getServerSession(ctx.req, ctx.res, authOptions); +}; +``` + +Using this helper function, we can grab the session and pass it through to the tRPC context: + +```ts:server/api/trpc.ts +import { getServerAuthSession } from "../auth"; + +export const createContext = async (opts: CreateNextContextOptions) => { + const { req, res } = opts; + const session = await getServerAuthSession({ req, res }); + return await createContextInner({ + session, + }); +}; +``` + +2. Create a tRPC middleware that checks if the user is authenticated. We then use the middleware in a `protectedProcedure`. Any caller to these procedures must be authenticated, or else an error will be thrown which can be appropriately handled by the client. + +```ts:server/api/trpc.ts +export const protectedProcedure = t.procedure.use(({ ctx, next }) => { + if (!ctx.session?.user) { + throw new TRPCError({ code: "UNAUTHORIZED" }); + } + return next({ + ctx: { + // infers the `session` as non-nullable + session: { ...ctx.session, user: ctx.session.user }, + }, + }); +}) +``` + +The session object is a light, minimal representation of the user and only contains a few fields. When using the `protectedProcedures`, you have access to the user's id which can be used to fetch more data from the database. + +```ts:server/api/routers/user.ts +const userRouter = router({ + me: protectedProcedure.query(async ({ ctx }) => { + const user = await prisma.user.findUnique({ + where: { + id: ctx.session.user.id, + }, + }); + return user; + }), +}); +``` + +## Usage with Prisma + +Getting NextAuth.js to work with Prisma requires a lot of [initial setup](https://authjs.dev/reference/adapter/prisma/). `create-t3-app` handles all of this for you, and if you select both Prisma and NextAuth.js, you'll get a fully working authentication system with all the required models preconfigured. We ship your scaffolded app with a preconfigured Discord OAuth provider, which we chose because it is one of the easiest to get started with - just provide your tokens in the `.env` and you're good to go. However, you can easily add more providers by following the [NextAuth.js docs](https://next-auth.js.org/providers/). Note that certain providers require extra fields to be added to certain models. We recommend you read the documentation for the provider you would like to use to make sure you have all the required fields. + +### Adding new fields to your models + +When adding new fields to any of the `User`, `Account`, `Session`, or `VerificationToken` models (most likely you'd only need to modify the `User` model), you need to keep in mind that the [Prisma adapter](https://next-auth.js.org/adapters/prisma) automatically creates fields on these models when new users sign up and log in. Therefore, when adding new fields to these models, you must provide default values for them, since the adapter is not aware of these fields. + +If for example, you'd like to add a `role` to the `User` model, you would need to provide a default value to the `role` field. This is done by adding a `@default` value to the `role` field in the `User` model: + +```diff:prisma/schema.prisma ++ enum Role { ++ USER ++ ADMIN ++ } + + model User { + ... ++ role Role @default(USER) + } +``` + +## Usage with Next.js middleware + +Usage of NextAuth.js with Next.js middleware [requires the use of the JWT session strategy](https://next-auth.js.org/configuration/nextjs#caveats) for authentication. This is because the middleware is only able to access the session cookie if it is a JWT. By default, Create T3 App is configured to use the **default** database strategy, in combination with Prisma as the database adapter. + + + Using database sessions is the recommended approach and you should read up on + JWTs before switching to the JWT session strategy to avoid any security + issues. + + +After switching to the JWT session strategy. Make sure to update the `session` callback in `src/server/auth.ts`. +The `user` object will be `undefined`. Instead, retrieve the user's ID from the `token` object. +I.e.: + +```diff:server/auth.ts + export const authOptions: NextAuthOptions = { ++ session: { ++ strategy: "jwt", ++ }, + callbacks: { +- session: ({ session, user }) => ({ ++ session: ({ session, token }) => ({ + ...session, + user: { + ...session.user, +- id: user.id, ++ id: token.sub, + }, + }), + }, + } +``` + +## Setting up the default DiscordProvider + +1. Head to [the Applications section in the Discord Developer Portal](https://discord.com/developers/applications), and click on "New Application" +2. In the settings menu, go to "OAuth2 => General" + +- Copy the Client ID and paste it in `DISCORD_CLIENT_ID` in `.env`. +- Under Client Secret, click "Reset Secret" and copy that string to `DISCORD_CLIENT_SECRET` in `.env`. Be careful as you won't be able to see this secret again, and resetting it will cause the existing one to expire. +- Click "Add Redirect" and paste in `/api/auth/callback/discord` (example for local development: http://localhost:3000/api/auth/callback/discord) +- Save your changes +- It is possible, but not recommended, to use the same Discord Application for both development and production. You could also consider [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) during development. + +## Useful Resources + +| Resource | Link | +| --------------------------------- | --------------------------------------- | +| NextAuth.js Docs | https://next-auth.js.org/ | +| NextAuth.js GitHub | https://github.com/nextauthjs/next-auth | +| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth | diff --git a/www/src/pages/vi/usage/drizzle.mdx b/www/src/pages/vi/usage/drizzle.mdx new file mode 100644 index 0000000000..6f735de94d --- /dev/null +++ b/www/src/pages/vi/usage/drizzle.mdx @@ -0,0 +1,84 @@ +--- +title: Drizzle +description: Usage of Drizzle +layout: ../../../layouts/docs.astro +lang: en +isMdx: true +--- + +Drizzle is a headless Typescript ORM with [relational](https://orm.drizzle.team/docs/rqb) and [SQL-like](https://orm.drizzle.team/docs/select) query APIs. It can handle database migrations and schemas, and provides a type safe database client. It also comes with [Drizzle-Kit](https://orm.drizzle.team/drizzle-studio/overview), a set of companion tools that help with querying your database. + +## Drizzle Client + +The Drizzle Client is located at `src/server/db/index.ts`. In this file, you can define your database connection url and connect your schema to the database object. + +```ts:src/server/db/index.ts +import { env } from "~/env"; +import * as schema from "./schema"; +import postgres from "postgres"; + + +const conn = postgres(env.DATABASE_URL) + +export const db = drizzle(conn, { schema }); +``` + +We reccommend including the database client in your tRPC Context: + +```ts:src/server/api/trpc.ts +import { db } from "~/server/db"; + +export const createTRPCContext = async (opts: { headers: Headers }) => { + const session = await auth(); + + return { + db, + session, + ...opts, + }; +}; +``` + +## Schema + +The Drizzle schema file can be found at `src/server/db/schema.ts`. This file is where you can define your database schema and models, and connects to the Drizzle Client. + +When you select NextAuth.js in combination with Drizzle, the schema file is generated and set up for you with the recommended values for the `User`, `Session`, `Account`, and `VerificationToken` models, as per the [Auth.js documentation](https://authjs.dev/getting-started/adapters/drizzle). + +## Drizzle Kit + +Drizzle Kit is a collection of command line tools designed to help you manage your database. T3 Stack automatically includes drizzle kit when you select Drizzle as your ORM. + +```json:package.json +"scripts": { + ... + "db:generate": "drizzle-kit generate", + "db:migrate": "drizzle-kit migrate", + "db:push": "drizzle-kit push", + "db:studio": "drizzle-kit studio", + ... + }, +``` + +### Script Explanations + +`db:generate` +Generates TypeScript types and models from your database schema, ensuring type safety and easy integration with Drizzle ORM. + +`db:migrate` +Applies pending migrations to your database, keeping your schema in sync with changes and updates in your project. + +`db:push` +Pushes local schema changes directly to the database without needing explicit migration files. This can be useful for quick syncing in development. + +`db:studio` +Opens a visual interface for managing and inspecting your database tables, data, and relationships. + +## Useful Resources + +| Resource | Link | +| --------------------------- | --------------------------------------------------- | +| Drizzle Docs | https://orm.drizzle.team/docs/overview | +| Drizzle GitHub | https://github.com/drizzle-team/drizzle-orm | +| Auth.JS Drizzle Adapter | https://authjs.dev/getting-started/adapters/drizzle | +| Drizzle Kit Migration Guide | https://orm.drizzle.team/docs/kit-overview | diff --git a/www/src/pages/vi/usage/env-variables.mdx b/www/src/pages/vi/usage/env-variables.mdx new file mode 100644 index 0000000000..a0807eec96 --- /dev/null +++ b/www/src/pages/vi/usage/env-variables.mdx @@ -0,0 +1,149 @@ +--- +title: Environment Variables +description: Getting started with Create T3 App +layout: ../../../layouts/docs.astro +lang: en +isMdx: true +--- + +import Callout from "../../../components/docs/callout.tsx"; + +Create T3 App uses its own package [@t3-oss/env-nextjs](https://env.t3.gg) along with [zod](https://zod.dev) under the hood for validating environment variables at runtime _and_ buildtime by providing a simple logic in `src/env.js`. + +## env.js + +_TLDR; If you want to add a new environment variable, you must add a validator for it in `src/env.js`, and then add the KV-pair in `.env`_ + +```ts:env.js +import { createEnv } from "@t3-oss/env-nextjs"; +import { z } from "zod"; + +export const env = createEnv({ + server: { + NODE_ENV: z.enum(["development", "test", "production"]), + }, + client: { + // NEXT_PUBLIC_CLIENTVAR: z.string(), + }, + runtimeEnv: { + NODE_ENV: process.env.NODE_ENV, + }, +}); +``` + +T3 Env uses the `createEnv` function to create the schema validate both client and server-side environment variables. + + + For more information about how `createEnv` works internally, check out the [T3 + Env](https://env.t3.gg/docs/introduction) docs + + +## Using Environment Variables + +When you want to use your environment variables, you can import them from the created `env.js` and use them as you would normally do. If you import this on the client and try accessing a server-side environment variable, you will get a runtime error. + +```ts:pages/api/hello.ts +import { env } from "../../env.js"; + +// `env` is fully typesafe and provides autocompletion +const dbUrl = env.DATABASE_URL; +``` + +```ts:pages/index.tsx +import { env } from "../env.js"; + +// ❌ This will throw a runtime error +const dbUrl = env.DATABASE_URL; + +// ✅ This is fine +const wsKey = env.NEXT_PUBLIC_WS_KEY; +``` + +## .env.example + +Since the default `.env` file is not committed to version control, we have also included a `.env.example` file, in which you can optionally keep a copy of your `.env` file with any secrets removed. This is not required, but we recommend keeping the example up to date to make it as easy as possible for contributors to get started with their environment. + +Some frameworks and build tools, like Next.js, suggest that you store secrets in a `.env.local` file and commit `.env` files to your project. This is not recommended, as it could make it easy to accidentally commit secrets to your project. Instead, we recommend that you store secrets in `.env`, keep your `.env` file in your `.gitignore` and only commit `.env.example` files to your project. + +## Adding Environment Variables + +To ensure your build never completes without the environment variables the project needs, you will need to add new environment variables in **two** locations: + +📄 `.env`: Enter your environment variable like you would normally do in a `.env` file, i.e. `KEY=VALUE` + +📄 `env.js`: Add the appropriate validation logic for the environment variables by defining a Zod schema inside `createEnv` for each one, e.g. `KEY: z.string()`. Besides that, make sure to destruct them in the `runtimeEnv` option, e.g.: `KEY: process.env.KEY` + + + Why do I need to destructure the environment variable in the `runtimeEnv`? + This is due to how Next.js bundles environment variables in certain runtimes. + By destructuring it manually, you ensure that the variable will never be + stripped out from the bundle. + + +Optionally, you can also keep `.env.example` updated: + +📄 `.env.example`: Enter your environment variable, but be sure to not include the value if it is secret, i.e. `KEY=VALUE` or `KEY=` + +### Example + +_I want to add my Twitter API Token as a server-side environment variable_ + +1. Add the environment variable to `.env`: + +``` +TWITTER_API_TOKEN=1234567890 +``` + +2. Add the environment variable to `env.js`: + +```ts +import { createEnv } from "@t3-oss/env-nextjs"; +import { z } from "zod"; + +export const env = createEnv({ + server: { + TWITTER_API_TOKEN: z.string(), + }, + // ... + runtimeEnv: { + // ... + TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN, + }, +}); +``` + +3. _Optional:_ Add the environment variable to `.env.example` and make sure not to include the secret in the `runtimeEnv` option + +```bash +TWITTER_API_TOKEN= +``` + +## Type Coercion + +All variables you add to `.env` will be imported as strings, even if their value is intended to represent a different type. If you want to use your environment variables as a different type at runtime, you can use Zod's `coerce` to convert the string to the type you want. It will throw if the coercion fails. + +Add the variables to your `.env`: + +``` +SOME_NUMBER=123 +SOME_BOOLEAN=true +``` + +Then, validate them in `env.js`: + +```ts +import { createEnv } from "@t3-oss/env-nextjs"; +import { z } from "zod"; + +export const env = createEnv({ + server: { + SOME_NUMBER: z.coerce.number(), + SOME_BOOLEAN: z.coerce.boolean(), + }, + // ... + runtimeEnv: { + SOME_NUMBER: process.env.SOME_NUMBER, + SOME_BOOLEAN: process.env.SOME_BOOLEAN, + }, +}); +``` diff --git a/www/src/pages/vi/usage/first-steps.md b/www/src/pages/vi/usage/first-steps.md new file mode 100644 index 0000000000..a90b52c600 --- /dev/null +++ b/www/src/pages/vi/usage/first-steps.md @@ -0,0 +1,53 @@ +--- +title: First Steps +description: Getting started with your new T3 App +layout: ../../../layouts/docs.astro +lang: en +--- + +You just scaffolded a new T3 App and are ready to go. Here is the bare minimum to get your app working. + +## Database + +### MySQL, PostgreSQL + +If you chose MySQL or PostgreSQL as your database, your T3 app will come with a `start-database.sh` bash script that can create a docker container with a database for local development. If you already have a database, feel free to delete this file and put your database credentials in `.env`. On macOS, you can also use [DBngin](https://dbngin.com/) if you don't want to use docker. + +### Prisma + +If your app includes Prisma, make sure to run `npx prisma db push` from the root directory of your app. This command will sync your Prisma schema with your database and will generate the TypeScript types for the Prisma Client based on your schema. Note that you need to [restart the TypeScript server](https://tinytip.co/tips/vscode-restart-ts/) after doing this so that it can detect the generated types. + +### Drizzle + +If your app includes Drizzle, check the `.env` file for instructions on how to construct your `DATABASE_URL` env variable. Once your env file is ready, run `pnpm db:push` (or the equivalent for other package managers) to push your schema. + +## Authentication + +If your app includes NextAuth.js, we get you started with the `DiscordProvider`. This is one of the simplest providers that NextAuth.js offers, but it still requires a bit of initial setup on your part. + +Of course, if you prefer to use a different auth provider, you can also use one of the [many providers](https://next-auth.js.org/providers/) that NextAuth.js offers. + +1. You will need a Discord account, so register one if you haven't already. +2. Navigate to https://discord.com/developers/applications and click "New Application" in the top right corner. Give your application a name and agree to the Terms of Service. +3. Once your application has been created, navigate to "Settings → OAuth2 → General". +4. Copy the "Client ID" and add it to your `.env` as `AUTH_DISCORD_ID`. +5. Click "Reset Secret", copy the new secret, and add it to your `.env` as `AUTH_DISCORD_SECRET`. +6. Click "Add Redirect" and type in `http://localhost:3000/api/auth/callback/discord`. + - For production deployment, follow the previous steps to create another Discord Application, but this time replace `http://localhost:3000` with the URL that you are deploying to. +7. Save Changes. + +You should now be able to log in. + +## Editor Setup + +The following extensions are recommended for an optimal developer experience. The links below provide editor specific plugin support. + +- [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup) +- [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup) +- [Prettier Extension](https://prettier.io/docs/en/editors.html) + +## Next Steps + +- If your app includes tRPC, check out `src/pages/index.tsx` and `src/server/api/routers/post.ts` to see how tRPC queries work. +- Have a look around the Create T3 App docs, as well as the docs of the packages that your app includes. +- Join our [Discord](https://t3.gg/discord) and give us a star on [GitHub](https://github.com/t3-oss/create-t3-app)! :) diff --git a/www/src/pages/vi/usage/index.astro b/www/src/pages/vi/usage/index.astro new file mode 100644 index 0000000000..4c31ec7bf1 --- /dev/null +++ b/www/src/pages/vi/usage/index.astro @@ -0,0 +1,24 @@ +--- +import IndexPage from "../../../components/docs/indexPage.astro"; +import { SIDEBAR, type Frontmatter } from "../../../config"; +import { getLanguageFromURL } from "../../../languages"; +import Layout from "../../../layouts/docs.astro"; + +const frontmatter: Frontmatter = { + title: "Usage", + layout: "docs", + description: "Learn how to use the different technology from the T3 Stack.", +}; + +const lang = getLanguageFromURL(Astro.url.pathname); +const sidebarEntries = SIDEBAR[lang]["Usage"]!; +const files = await Astro.glob("./*.{md,mdx,astro}"); +--- + + + + diff --git a/www/src/pages/vi/usage/next-auth.mdx b/www/src/pages/vi/usage/next-auth.mdx new file mode 100644 index 0000000000..50f6b9fc82 --- /dev/null +++ b/www/src/pages/vi/usage/next-auth.mdx @@ -0,0 +1,18 @@ +--- +title: NextAuth.js +description: Usage of NextAuth.js +layout: ../../../layouts/docs.astro +lang: en +isMdx: true +--- + +import Tabs from "../../../components/docs/tabs.astro"; +import AppRouter from "./_next-auth-app-router.mdx"; +import Pages from "./_next-auth-pages.mdx"; + +When you want an authentication system in your Next.js application, NextAuth.js is an excellent solution to bring in the complexity of security without the hassle of having to build it yourself. It comes with an extensive list of providers to quickly add OAuth authentication and provides adapters for many databases and ORMs. + + + + + diff --git a/www/src/pages/vi/usage/next-js.md b/www/src/pages/vi/usage/next-js.md new file mode 100644 index 0000000000..77bf718134 --- /dev/null +++ b/www/src/pages/vi/usage/next-js.md @@ -0,0 +1,37 @@ +--- +title: Next.js +description: Usage of Next.js +layout: ../../../layouts/docs.astro +lang: en +--- + +Next.js is a backend framework for your React applications. + +
+ +
+ +Check out [Theo's Next.js Conf talk](https://www.youtube.com/watch?v=W4UhNo3HAMw) to get a better understanding of what Next.js is and how it works.

+ +## Why should I use it? + +We love React. It has made UI development accessible in ways we never imagined before. It also can lead developers down some rough paths. Next.js offers a lightly opinionated, heavily optimized approach to creating applications using React. From routing to API definitions to image rendering, we trust Next.js to lead developers towards good decisions. + +Pairing Next.js with [Vercel](https://vercel.com/) makes developing and deploying web apps easier than ever before. Their extremely generous free-tier and super intuitive interface provides a point and click solution to deploy your site (We ❤️ Vercel) + +## Get Static/Server Props + +A key feature of Next.js is its data fetching capabilities. We highly recommend reading through the [official documentation](https://nextjs.org/docs/basic-features/data-fetching) to understand how to use each method and how they differ. `getServerSideProps` is generally discouraged unless there is a good reason for it, due to the fact that it is a blocking call and will slow down your site. [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) is a great alternative to `getServerSideProps` when the data is dynamic and can be fetched incrementally. + +If you need to use this feature anyway, check these links out: [Advanced tRPC - Callers, functions, and gSSP](https://www.youtube.com/watch?v=G2ZzmgShHgQ) and [SSG-Helpers](https://trpc.io/docs/v9/ssg-helpers) + +## Useful Resources + +| Resource | Link | +| ------------------------------ | ---------------------------------- | +| Next.js Documentation | https://nextjs.org/docs | +| Next.js GitHub | https://github.com/vercel/next.js | +| Next.js Blog | https://nextjs.org/blog | +| Next.js Discord | https://nextjs.org/discord | +| Next.js Twitter | https://twitter.com/nextjs | +| Vercel/Next.js YouTube Channel | https://www.youtube.com/c/VercelHQ | diff --git a/www/src/pages/vi/usage/prisma.md b/www/src/pages/vi/usage/prisma.md new file mode 100644 index 0000000000..fc82701ca0 --- /dev/null +++ b/www/src/pages/vi/usage/prisma.md @@ -0,0 +1,78 @@ +--- +title: Prisma +description: Usage of Prisma +layout: ../../../layouts/docs.astro +lang: en +--- + +Prisma is an ORM for TypeScript, that allows you to define your database schema and models in a `schema.prisma` file, and then generate a type-safe client that can be used to interact with your database from your backend. + +## Prisma Client + +Located at `src/server/db.ts`, the Prisma Client is instantiated as a global variable (as recommended as [best practice](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) by the team at Prisma) and exported to be used in your API routes. We include the Prisma Client in [Context](/en/usage/trpc#-serverapitrpcts) by default and recommend using this instead of importing it separately in each file. + +## Schema + +You will find the Prisma schema file at `/prisma/schema.prisma`. This file is where you define your database schema and models, and is used when generating the Prisma Client. + +### With NextAuth.js + +When you select NextAuth.js in combination with Prisma, the schema file is generated and set up for you with the recommended values for the `User`, `Session`, `Account`, and `VerificationToken` models, as per the [NextAuth.js documentation](https://next-auth.js.org/adapters/prisma). + +## Default Database + +The default database is an SQLite database, which is great for development and quickly spinning up a proof-of-concept but is not recommended for production. You can change the database to use by changing the `provider` in the `datasource` block to either `postgresql` or `mysql`, and then updating the connection string within environment variables to point to your database. + +## Seeding your Database + +[Seeding your database](https://www.prisma.io/docs/guides/database/seed-database) is a great way to quickly populate your database with test data to help you get started. In order to setup seeding, you will need to create a `seed.ts` file in the `/prisma` directory, and then add a `seed` script to your `package.json` file. You'll also need a TypeScript runner that can execute the seed-script. We recommend [tsx](https://github.com/esbuild-kit/tsx), which is a very performant TypeScript runner that uses esbuild and doesn't require any ESM configuration, but `ts-node` or other runners will work as well. + +```jsonc:package.json +{ + "scripts": { + "db-seed": "NODE_ENV=development prisma db seed" + }, + "prisma": { + "seed": "tsx prisma/seed.ts" + } +} +``` + +```ts:prisma/seed.ts +import { db } from "../src/server/db"; + +async function main() { + const id = "cl9ebqhxk00003b600tymydho"; + await db.example.upsert({ + where: { + id, + }, + create: { + id, + }, + update: {}, + }); +} + +main() + .then(async () => { + await db.$disconnect(); + }) + .catch(async (e) => { + console.error(e); + await db.$disconnect(); + process.exit(1); + }); +``` + +Then, just run `pnpm db-seed` (or `npm`/`yarn`) to seed your database. + +## Useful Resources + +| Resource | Link | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| Prisma Docs | https://www.prisma.io/docs/ | +| Prisma GitHub | https://github.com/prisma/prisma | +| Prisma Migrate Playground | https://playground.prisma.io/guides | +| NextAuth.JS Prisma Adapter | https://next-auth.js.org/adapters/prisma | +| PlanetScale Connection Guide | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale | diff --git a/www/src/pages/vi/usage/tailwind.md b/www/src/pages/vi/usage/tailwind.md new file mode 100644 index 0000000000..bdb355a4b0 --- /dev/null +++ b/www/src/pages/vi/usage/tailwind.md @@ -0,0 +1,96 @@ +--- +title: Tailwind CSS +description: Usage of Tailwind CSS +layout: ../../../layouts/docs.astro +lang: en +--- + +## What is Tailwind CSS? + +Tailwind CSS is a tiny, [utility first](https://tailwindcss.com/docs/utility-first) CSS framework for building custom designs, without the context switching that regular CSS requires. It is purely a CSS framework and does not provide any pre-built components or logic, and provides [a very different set of benefits](https://www.youtube.com/watch?v=CQuTF-bkOgc) compared to a component library like Material UI. + +It makes CSS incredibly easy and quick to write, as shown by the following example: + +Old CSS: + +1. Write CSS, often in a separate file + +```css +.my-class { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: #fff; + border: 1px solid #e2e8f0; + border-radius: 0.25rem; + padding: 1rem; +} +``` + +2. Import CSS into your component + +```jsx +import "./my-class.css"; +``` + +3. Add the class to your HTML + +```html +
...
+``` + +Equivalent in Tailwind: + +1. Just write classes in your HTML + +```html +
+ ... +
+``` + +When used together with React Components, it is extremely powerful for quickly building UIs. + +Tailwind CSS has a beautiful built-in design system, that comes out of the box with a carefully chosen color palette, sizing patterns for styles such as width/height and padding/margin for a uniform design, as well as media breakpoints for creating responsive layouts. This design system can be customized and extended to create the exact toolbox of styles that your project needs. + +
+ +
+ +Tru Narla better known as [mewtru](https://twitter.com/trunarla) gave an amazing talk on [building a design system using Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI). + +## Usage + +Make sure you have editor plugins for Tailwind installed to improve your experience writing Tailwind. + +### Extensions and Plugins + +- [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) +- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install) +- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss) + +### Formatting + +Tailwind CSS classes can easily get a bit messy, so a formatter for the classes is a must have. [Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) sorts the classes in the [recommended order](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) so that the classes match the outputted css bundle. When selecting Tailwind in the CLI, we will install and configure this for you. + +### Conditionally Applying Classes + +Conditionally adding classes using ternaries can get very messy and hard to read. These packages help in organizing your classes when using some conditional logic. + +- [clsx](https://github.com/lukeed/clsx) +- [classnames](https://github.com/JedWatson/classnames) + +## Useful Resources + +| Resource | Link | +| ---------------------------- | -------------------------------------------------------- | +| Tailwind Docs | https://tailwindcss.com/docs/editor-setup/ | +| Tailwind Cheat Sheet | https://nerdcave.com/tailwind-cheat-sheet/ | +| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ | +| Tailwind Community | https://github.com/tailwindlabs/tailwindcss/discussions/ | +| Tailwind Discord Server | https://tailwindcss.com/discord/ | +| TailwindLabs Youtube Channel | https://www.youtube.com/tailwindlabs/ | +| Tailwind Playground | https://play.tailwindcss.com/ | diff --git a/www/src/pages/vi/usage/trpc.md b/www/src/pages/vi/usage/trpc.md new file mode 100644 index 0000000000..9cd65bdfb0 --- /dev/null +++ b/www/src/pages/vi/usage/trpc.md @@ -0,0 +1,382 @@ +--- +title: tRPC +description: Usage of tRPC +layout: ../../../layouts/docs.astro +lang: en +--- + +tRPC allows us to write end-to-end typesafe APIs without any code generation or runtime bloat. It uses TypeScript's great inference to infer your API router's type definitions and lets you call your API procedures from your frontend with full typesafety and auto-completion. When using tRPC, your frontend and backend feel closer together than ever before, allowing for an outstanding developer experience. + +
+
+

+ I built tRPC to allow people to move faster by removing the need for a traditional API-layer, while still having confidence that our apps won't break as we rapidly iterate. +

+
+ + Avatar of @alexdotjs +
+ Alex - creator of tRPC + + @alexdotjs + +
+
+
+ +## How do I use tRPC? + +
+ +
+ +tRPC contributor [trashh_dev](https://twitter.com/trashh_dev) made [a killer talk at Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) about tRPC. We highly recommend you watch it if you haven't already. + +With tRPC, you write TypeScript functions on your backend, and then call them from your frontend. A simple tRPC procedure could look like this: + +```ts:server/api/routers/user.ts +const userRouter = createTRPCRouter({ + getById: publicProcedure.input(z.string()).query(({ ctx, input }) => { + return ctx.prisma.user.findFirst({ + where: { + id: input, + }, + }); + }), +}); +``` + +This is a tRPC procedure (equivalent to a route handler in a traditional backend) that first validates the input using Zod (which is the same validation library that we use for [environment variables](./env-variables)) - in this case, it's making sure that the input is a string. If the input is not a string it will send an informative error instead. + +After the input, we chain a resolver function which can be either a [query](https://trpc.io/docs/client/react/useQuery), [mutation](https://trpc.io/docs/v11/client/react/useMutation), or a [subscription](https://trpc.io/docs/v11/subscriptions). In our example, the resolver calls our database using our [prisma](./prisma) client and returns the user whose `id` matches the one we passed in. + +You define your procedures in `routers` which represent a collection of related procedures with a shared namespace. You may have one router for `users`, one for `posts`, and another one for `messages`. These routers can then be merged into a single, centralized `appRouter`: + +```ts:server/api/root.ts +const appRouter = createTRPCRouter({ + users: userRouter, + posts: postRouter, + messages: messageRouter, +}); + +export type AppRouter = typeof appRouter; +``` + +Notice that we only need to export our router's type definitions, which means we are never importing any server code on our client. + +Now let's call the procedure on our frontend. tRPC provides a wrapper for `@tanstack/react-query` which lets you utilize the full power of the hooks they provide, but with the added benefit of having your API calls typed and inferred. We can call our procedures from our frontend like this: + +```tsx:pages/users/[id].tsx +import { useRouter } from "next/router"; +import { api } from "../../utils/api"; + +const UserPage = () => { + const { query } = useRouter(); + const userQuery = api.users.getById.useQuery(query.id); + + return ( +
+

{userQuery.data?.name}

+
+ ); +}; +``` + +You'll immediately notice how good the autocompletion and typesafety is. As soon as you write `api.`, your routers will show up in autocomplete, and when you select a router, its procedures will show up as well. You'll also get a TypeScript error if your input doesn't match the validator that you defined on the backend. + +## Inferring errors + +By default, `create-t3-app` sets up an [error formatter](https://trpc.io/docs/v11/server/error-formatting) that lets you infer your Zod Errors if you get validation errors on the backend. + +Example usage: + +```tsx +function MyComponent() { + const { mutate, error } = api.post.create.useMutation(); + + return ( + { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + mutate({ title: formData.get('title') }); + }}> + + {error?.data?.zodError?.fieldErrors.title && ( + {/** `mutate` returned with an error on the `title` */} + + {error.data.zodError.fieldErrors.title} + + )} + + ... + + ); +} +``` + +## Files + +tRPC requires quite a lot of boilerplate that `create-t3-app` sets up for you. Let's go over the files that are generated: + +### 📄 `pages/api/trpc/[trpc].ts` + +This is the entry point for your API and exposes the tRPC router. Normally, you won't touch this file very much, but if you need to, for example, enable CORS middleware or similar, it's useful to know that the exported `createNextApiHandler` is a [Next.js API handler](https://nextjs.org/docs/api-routes/introduction) which takes a [request](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [response](https://developer.mozilla.org/en-US/docs/Web/API/Response) object. This means that you can wrap the `createNextApiHandler` in any middleware you want. See below for an [example snippet](#enabling-cors) of adding CORS. + +### 📄 `server/api/trpc.ts` + +This file is split up in two parts, context creation and tRPC initialization: + +1. We define the context that is passed to your tRPC procedures. Context is data that all of your tRPC procedures will have access to, and is a great place to put things like database connections, authentication information, etc. In create-t3-app we use two functions, to enable using a subset of the context when we do not have access to the request object. + +- `createInnerTRPCContext`: This is where you define context which doesn't depend on the request, e.g. your database connection. You can use this function for [integration testing](#sample-integration-test) or [ssg-helpers](https://trpc.io/docs/v10/client/nextjs/server-side-helpers) where you don't have a request object. + +- `createTRPCContext`: This is where you define context which depends on the request, e.g. the user's session. You request the session using the `opts.req` object, and then pass the session down to the `createInnerTRPCContext` function to create the final context. + +2. We initialize tRPC and define reusable [procedures](https://trpc.io/docs/v11/server/procedures) and [middlewares](https://trpc.io/docs/v11/server/middlewares). By convention, you shouldn't export the entire `t`-object but instead, create reusable procedures and middlewares and export those. + +You'll notice we use `superjson` as [data transformer](https://trpc.io/docs/v10/server/data-transformers). This makes it so that your data types are preserved when they reach the client, so if you for example send a `Date` object, the client will return a `Date` and not a string which is the case for most APIs. + +### 📄 `server/api/routers/*.ts` + +This is where you define the routes and procedures of your API. By convention, you [create separate routers](https://trpc.io/docs/v11/server/routers) for related procedures. + +### 📄 `server/api/root.ts` + +Here we [merge](https://trpc.io/docs/v11/server/merging-routers) all the sub-routers defined in `routers/**` into a single app router. + +### 📄 `utils/api.ts` + +This is the frontend entry point for tRPC. This is where you'll import the router's **type definition** and create your tRPC client along with the react-query hooks. Since we enabled `superjson` as our data transformer on the backend, we need to enable it on the frontend as well. This is because the serialized data from the backend is deserialized on the frontend. + +You'll define your tRPC [links](https://trpc.io/docs/v11/client/links) here, which determines the request flow from the client to the server. We use the "default" [`httpBatchLink`](https://trpc.io/docs/v11/client/links/httpBatchLink) which enables [request batching](https://cloud.google.com/compute/docs/api/how-tos/batch), as well as a [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink) which outputs useful request logs during development. + +Lastly, we export a [helper type](https://trpc.io/docs/client/vanilla/infer-types) which you can use to infer your types on the frontend. + +
+ +
+ +Create T3 App contributor [Christopher Ehrlich](https://twitter.com/ccccjjjjeeee) made [a video about data flows in tRPC](https://www.youtube.com/watch?v=x4mu-jOiA0Q). This video is recommended if you have used tRPC but still feel a bit unclear about how it works. + +## How do I call my API externally? + +With regular APIs, you can call your endpoints using any HTTP client such as `curl`, `Postman`, `fetch` or straight from your browser. With tRPC, it's a bit different. If you want to call your procedures without the tRPC client, there are two recommended ways to do it: + +### Expose a single procedure externally + +If you want to expose a single procedure externally, you're looking for [server side calls](https://trpc.io/docs/server/server-side-calls). That would allow you to create a normal Next.js API endpoint, but reuse the resolver part of your tRPC procedure. + +```ts:pages/api/users/[id].ts +import { type NextApiRequest, type NextApiResponse } from "next"; +import { appRouter, createCaller } from "../../../server/api/root"; +import { createTRPCContext } from "../../../server/api/trpc"; + +const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => { + // Create context and caller + const ctx = await createTRPCContext({ req, res }); + const caller = createCaller(ctx); + try { + const { id } = req.query; + const user = await caller.user.getById(id); + res.status(200).json(user); + } catch (cause) { + if (cause instanceof TRPCError) { + // An error from tRPC occurred + const httpCode = getHTTPStatusCodeFromError(cause); + return res.status(httpCode).json(cause); + } + // Another error occurred + console.error(cause); + res.status(500).json({ message: "Internal server error" }); + } +}; + +export default userByIdHandler; +``` + +### Exposing every procedure as a REST endpoint + +If you want to expose every single procedure externally, checkout the community built plugin [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). By providing some extra meta-data to your procedures, you can generate an OpenAPI compliant REST API from your tRPC router. + +### It's just HTTP Requests + +tRPC communicates over HTTP, so it is also possible to call your tRPC procedures using "regular" HTTP requests. However, the syntax can be cumbersome due to the [RPC protocol](https://trpc.io/docs/rpc) that tRPC uses. If you're curious, you can check what tRPC requests and responses look like in your browser's network tab, but we suggest doing this only as an educational exercise and sticking to one of the solutions outlined above. + +## Comparison to a Next.js API endpoint + +Let's compare a Next.js API endpoint to a tRPC procedure. Let's say we want to fetch a user object from our database and return it to the frontend. We could write a Next.js API endpoint like this: + +```ts:pages/api/users/[id].ts +import { type NextApiRequest, type NextApiResponse } from "next"; +import { prisma } from "../../../server/db"; + +const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => { + if (req.method !== "GET") { + return res.status(405).end(); + } + + const { id } = req.query; + + if (!id || typeof id !== "string") { + return res.status(400).json({ error: "Invalid id" }); + } + + const examples = await prisma.example.findFirst({ + where: { + id, + }, + }); + + res.status(200).json(examples); +}; + +export default userByIdHandler; +``` + +```ts:pages/users/[id].tsx +import { useState, useEffect } from "react"; +import { useRouter } from "next/router"; + +const UserPage = () => { + const router = useRouter(); + const { id } = router.query; + + const [user, setUser] = useState(null); + useEffect(() => { + fetch(`/api/user/${id}`) + .then((res) => res.json()) + .then((data) => setUser(data)); + }, [id]); +}; +``` + +Compare this to the tRPC example above and you can see some of the advantages of tRPC: + +- Instead of specifying a url for each route, which can become annoying to debug if you move something, your entire router is an object with autocomplete. +- You don’t need to validate which HTTP method was used. +- You don’t need to validate that the request query or body contains the correct data in the procedure, because Zod takes care of this. +- Instead of creating a response, you can throw errors and return a value or object as you would in any other TypeScript function. +- Calling the procedure on the frontend provides autocompletion and type safety. + +## Useful snippets + +Here are some snippets that might come in handy. + +### Enabling CORS + +If you need to consume your API from a different domain, for example in a monorepo that includes a React Native app, you might need to enable CORS: + +```ts:pages/api/trpc/[trpc].ts +import { type NextApiRequest, type NextApiResponse } from "next"; +import { createNextApiHandler } from "@trpc/server/adapters/next"; +import { appRouter } from "~/server/api/root"; +import { createTRPCContext } from "~/server/api/trpc"; +import cors from "nextjs-cors"; + +const handler = async (req: NextApiRequest, res: NextApiResponse) => { + // Enable cors + await cors(req, res); + + // Create and call the tRPC handler + return createNextApiHandler({ + router: appRouter, + createContext: createTRPCContext, + })(req, res); +}; + +export default handler; +``` + +### Optimistic updates + +Optimistic updates are when we update the UI before the API call has finished. This gives the user a better experience because they don't have to wait for the API call to finish before the UI reflects the result of their action. However, apps that value data correctness highly should avoid optimistic updates as they are not a "true" representation of backend state. You can read more on the [React Query docs](https://tanstack.com/query/latest/docs/framework/react/guides/optimistic-updates). + +```tsx +const MyComponent = () => { + const listPostQuery = api.post.list.useQuery(); + + const utils = api.useUtils(); + const postCreate = api.post.create.useMutation({ + async onMutate(newPost) { + // Cancel outgoing fetches (so they don't overwrite our optimistic update) + await utils.post.list.cancel(); + + // Get the data from the queryCache + const prevData = utils.post.list.getData(); + + // Optimistically update the data with our new post + utils.post.list.setData(undefined, (old) => [...old, newPost]); + + // Return the previous data so we can revert if something goes wrong + return { prevData }; + }, + onError(err, newPost, ctx) { + // If the mutation fails, use the context-value from onMutate + utils.post.list.setData(undefined, ctx.prevData); + }, + onSettled() { + // Sync with server once mutation has settled + utils.post.list.invalidate(); + }, + }); +}; +``` + +### Sample Integration Test + +Here is a sample integration test that uses [Vitest](https://vitest.dev) to check that your tRPC router is working as expected, the input parser infers the correct type, and that the returned data matches the expected output. + +```ts +import { type inferProcedureInput } from "@trpc/server"; +import { expect, test } from "vitest"; + +import { appRouter, type AppRouter } from "~/server/api/root"; +import { createInnerTRPCContext } from "~/server/api/trpc"; + +test("example router", async () => { + const ctx = await createInnerTRPCContext({ session: null }); + const caller = appRouter.createCaller(ctx); + + type Input = inferProcedureInput; + const input: Input = { + text: "test", + }; + + const example = await caller.example.hello(input); + + expect(example).toMatchObject({ greeting: "Hello test" }); +}); +``` + +If your procedure is protected, you can pass in a mocked `session` object when you create the context: + +```ts +test("protected example router", async () => { + const ctx = await createInnerTRPCContext({ + session: { + user: { id: "123", name: "John Doe" }, + expires: "1", + }, + }); + const caller = appRouter.createCaller(ctx); + + // ... +}); +``` + +## Useful Resources + +| Resource | Link | +| ---------------------- | ----------------------------------------------- | +| tRPC Docs | https://www.trpc.io | +| Bunch of tRPC Examples | https://github.com/trpc/trpc/tree/next/examples | +| React Query Docs | https://tanstack.com/query/latest/docs | diff --git a/www/src/pages/vi/usage/typescript.md b/www/src/pages/vi/usage/typescript.md new file mode 100644 index 0000000000..833fd5b2bc --- /dev/null +++ b/www/src/pages/vi/usage/typescript.md @@ -0,0 +1,67 @@ +--- +title: TypeScript +description: Usage of TypeScript +layout: ../../../layouts/docs.astro +lang: en +--- + +
+
+

+ Build safety nets, not guard rails +

+
+ + Avatar of @t3dotgg +
+ Theo - creator of the T3 Stack + + @t3dotgg + +
+
+
+ +Whether you're a new or seasoned developer, we think that TypeScript is a must have. It can look intimidating at first, but much like a lot of tools, is something that many never look back from after starting to use it. + +It provides live feedback as you write your code by defining expected data types, and either provides helpful autocomplete in your code editor, or yells at you with red squiggly lines if you're trying to access a property that doesn't exist or trying to pass a value of the wrong type, which you would otherwise have to debug further down the line. + +It is, perhaps, the tool that provides the most productivity to developers; providing documentation of the code you're writing or consuming directly in your editor, and having instant feedback as you inevitably make mistakes is absolutely priceless. + +## Type Inference + +While many new TypeScript developers are concerned with _writing_ TypeScript, many of its benefits don't actually require you to change your code at all, in particular inference. Inference means that if something is typed, that type will follow it throughout the flow of the application without having to be re-declared in other places. This means that for example once you have defined the types of the arguments that a function takes, the remainder of the function will usually be typesafe without requiring any further TypeScript-specific code. Library developers put a ton of work into maintaining the types for their libraries, which means that we as application developers can benefit from both the inference and the built-in documentation in your code editor that these types provide. + +
+ +
+ +Check out Theo's video on how [you might be using TypeScript wrong](https://www.youtube.com/watch?v=RmGHnYUqQ4k). + +## Powerful uses of type inference + +### Zod + +[Zod](https://github.com/colinhacks/zod) is a schema validation library that is built on top of TypeScript. Write a schema that represents a single source of truth for your data, and Zod will ensure that your data is valid throughout your application, even across network boundaries and external APIs. + +### Tanstack Query + +[Tanstack Query](https://tanstack.com/query/v4/) gives you declarative, always-up-to-date auto-managed queries and mutations that directly improve both your developer and user experiences. + +## Useful Resources + +| Resource | Link | +| --------------------------------------------------------- | ----------------------------------------------------------------- | +| TypeScript Handbook | https://www.typescriptlang.org/docs/handbook/ | +| Beginners TypeScript Tutorial | https://github.com/total-typescript/beginners-typescript-tutorial | +| Type Challenges | https://github.com/type-challenges/type-challenges | +| Rodney Mullen of TypeScript (Matt Pocock) Youtube Channel | https://www.youtube.com/c/MattPocockUk/videos | diff --git a/www/src/pages/vi/why.md b/www/src/pages/vi/why.md new file mode 100644 index 0000000000..0c1cf9e344 --- /dev/null +++ b/www/src/pages/vi/why.md @@ -0,0 +1,50 @@ +--- +title: Why CT3A? +description: Why you should pick Create T3 App for your next project +layout: ../../layouts/docs.astro +lang: en +--- + +We started Create T3 App because [Theo](https://twitter.com/t3dotgg) refused to make a template of his favorite technologies. Inspired by create-next-app, [Astro's CLI](https://astro.build), and a general love for typesafety, the Create T3 App team worked hard to build the best possible starting point for new T3 Stack projects. + +If you're interested in using Next.js in a typesafe way, this is the place to start. If you're curious about any of the specific technology choices we made, read on :) + +## Why TypeScript? + +JavaScript is hard. Why add more rules? + +We firmly believe the experience TypeScript provides will help you be a better developer. It provides live feedback as you write your code by defining expected data types, and either provides helpful autocomplete in your editor or yells at you with red squiggly lines if you're trying to access a property that doesn't exist or trying to pass a value of the wrong type, which you would otherwise have to debug further down the line. Whether you're new to web development or a seasoned pro, the "strictness" of TypeScript will provide a less frustrating, more consistent experience than vanilla JS. + +Typesafety makes you faster. If you're not convinced, you [might be using TypeScript wrong...](https://www.youtube.com/watch?v=RmGHnYUqQ4k) + +## Why Next.js? + +We love React. It has made UI development accessible in ways we never imagined before. It also can lead developers down some rough paths. + +Next.js offers a lightly opinionated, heavily optimized approach to creating applications using React. From routing to API definitions to image rendering, we trust Next.js to lead developers toward good decisions. + +## Why tRPC/Prisma/Tailwind/etc? + +While we believe in keeping things as simple as possible, we find these pieces being used in every "app" like project we build. `create-t3-app` does a great job of letting you adopt the pieces you need. + +### tRPC + +tRPC delivers on GraphQL's promise of seamless client development against a typesafe server without all of the boilerplate. It's a clever abuse of TypeScript that provides an incredible dev experience. + +### Prisma + +Prisma is to SQL what TypeScript is to JS. It created a developer experience that didn't exist before. By generating types from a user-defined schema compatible with [several databases](https://www.prisma.io/docs/concepts/database-connectors), Prisma guarantees end-to-end typesafety from your database to your app. + +Prisma provides a whole [suite of tools](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows) making daily interactions with your database easier. Notably, the Prisma Client is responsible for querying and making SQL so easy you'll barely notice you're using it, and Prisma Studio is a convenient GUI for your database that lets you read and manipulate your data quickly without having to write code. + +### Tailwind CSS + +Tailwind feels like "zen-mode CSS". + +By providing building blocks in the form of good default colors, spacing, and other primitives, Tailwind makes it easy to create a good-looking app. And unlike component libraries, it does not hold you back when you want to take your app to the next level and create something beautiful and unique. + +Additionally, with its inline-like approach, Tailwind encourages you to style without worrying about naming classes, organizing files, or any other issue not directly tied to the problem you're trying to solve. + +### NextAuth.js + +When you want an authentication system in your NextJS application, NextAuth.js is an excellent solution to bring in the complexity of security without the hassle of having to build it yourself. It comes with an extensive list of providers to quickly add OAuth authentication and provides adapters for many databases and ORMs. From 56e308dfc82f1b37a63868527ffe6d1d3150c9dc Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Tue, 22 Apr 2025 22:23:38 +1000 Subject: [PATCH 02/12] docs(vi): Update Vietnamese for Why CT3A Page --- www/src/pages/vi/why.md | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/www/src/pages/vi/why.md b/www/src/pages/vi/why.md index 0c1cf9e344..7e5917bbd0 100644 --- a/www/src/pages/vi/why.md +++ b/www/src/pages/vi/why.md @@ -1,50 +1,50 @@ --- -title: Why CT3A? -description: Why you should pick Create T3 App for your next project +title: Tại sao lại là CT3A? +description: Tại sao bạn nên chọn Create T3 App cho dự án tiếp theo của mình layout: ../../layouts/docs.astro -lang: en +lang: vi --- -We started Create T3 App because [Theo](https://twitter.com/t3dotgg) refused to make a template of his favorite technologies. Inspired by create-next-app, [Astro's CLI](https://astro.build), and a general love for typesafety, the Create T3 App team worked hard to build the best possible starting point for new T3 Stack projects. +Chúng tôi tạo ra Create T3 App vì [Theo](https://twitter.com/t3dotgg) từ chối việc có một template cho các công nghệ yêu thích của anh ấy. Được truyền cảm hứng từ create-next-app, [CLI của Astro](https://astro.build), và một tình yêu to bự dành cho tính toàn vẹn của kiểu dữ liệu (typesafety), đội ngũ Create T3 App đã làm việc chăm chỉ để tạo nên một nền móng vững chắc nhất có thể dành cho các dự án T3 Stack mới. -If you're interested in using Next.js in a typesafe way, this is the place to start. If you're curious about any of the specific technology choices we made, read on :) +Nếu bạn thích việc sử dụng Next.js một cách typesafe, đây chính là điểm bắt đầu của bạn. Nếu bạn tò mò về bất kỳ lựa chọn công nghệ cụ thể nào mà chúng tôi đã thực hiện, hãy bình tĩnh, lấy một ly cà phê và cùng đọc tiếp nhé :) -## Why TypeScript? +## Tại sao lại là TypeScript? -JavaScript is hard. Why add more rules? +JavaScript đã khó rồi. Tại sao lại thêm nhiều các quy tắc rắc rối hơn hơn? -We firmly believe the experience TypeScript provides will help you be a better developer. It provides live feedback as you write your code by defining expected data types, and either provides helpful autocomplete in your editor or yells at you with red squiggly lines if you're trying to access a property that doesn't exist or trying to pass a value of the wrong type, which you would otherwise have to debug further down the line. Whether you're new to web development or a seasoned pro, the "strictness" of TypeScript will provide a less frustrating, more consistent experience than vanilla JS. +Chúng tôi tin chắc rằng trải nghiệm mà TypeScript mang lại sẽ giúp bạn trở thành một lập trình viên tốt hơn. Nó cung cấp phản hồi trực tiếp khi bạn viết mã bằng cách xác định các kiểu dữ liệu bạn muốn, và nó cung cấp tính năng tự động hoàn thành (autocompletion) hữu ích trong trình soạn thảo (IDE) của bạn hoặc báo lỗi cho bạn bằng các đường lượn sóng màu đỏ nếu bạn đang cố gắng truy cập một thuộc tính không tồn tại hoặc cố gắng truyền một giá trị có kiểu sai, điều mà có thể khiến bạn phải đau đầu gỡ lỗi sau này nếu như không có chúng. Cho dù bạn là người mới làm quen với phát triển web hay một chuyên gia dày dạn kinh nghiệm, "sự nghiêm ngặt" của TypeScript sẽ mang lại trải nghiệm lập trình tuyệt vời hơn, nhất quán hơn so với JS thuần túy. -Typesafety makes you faster. If you're not convinced, you [might be using TypeScript wrong...](https://www.youtube.com/watch?v=RmGHnYUqQ4k) +Typesafety giúp bạn nhanh hơn. Nếu bạn chưa bị thuyết phục, có thể bạn [đang sử dụng TypeScript sai cách...](https://www.youtube.com/watch?v=RmGHnYUqQ4k) -## Why Next.js? +## Tại sao lại là Next.js? -We love React. It has made UI development accessible in ways we never imagined before. It also can lead developers down some rough paths. +Chúng tôi yêu React. Nó đã làm cho việc phát triển giao diện người dùng trở nên dễ tiếp cận theo những cách mà chúng tôi chưa bao giờ tưởng tượng được trước đây. Nhưng nó cũng có thể dẫn các bạn đi vào những con đường vô tận mà không có lối ra. -Next.js offers a lightly opinionated, heavily optimized approach to creating applications using React. From routing to API definitions to image rendering, we trust Next.js to lead developers toward good decisions. +Next.js cung cấp một cách tiếp cận nhẹ nhàng, nhưng cực kì được tối ưu hóa cao để tạo các ứng dụng bằng React. Từ hệ thống định tuyến (Routing) đến định nghĩa API (API Routes) đến kết xuất hình ảnh (Image Rendering), chúng tôi tin tưởng Next.js sẽ là "bạn đồng hành" tuyệt vời cho các nhà phát triển đưa ra những quyết định tốt. -## Why tRPC/Prisma/Tailwind/etc? +## Tại sao lại là tRPC/Prisma/Tailwind/etc? -While we believe in keeping things as simple as possible, we find these pieces being used in every "app" like project we build. `create-t3-app` does a great job of letting you adopt the pieces you need. +Mặc dù mục tiêu chúng tôi là giữ mọi thứ đơn giản nhất có thể, chúng tôi thấy rằng những công nghệ này thường được sử dụng trong mọi dự án mà chúng tôi xây dựng. `create-t3-app` làm rất tốt việc cho phép bạn chọn và sử dụng những công nghệ bạn cần. ### tRPC -tRPC delivers on GraphQL's promise of seamless client development against a typesafe server without all of the boilerplate. It's a clever abuse of TypeScript that provides an incredible dev experience. +tRPC là người viết tiếp sứ mệnh của GraphQL về việc kết nối liền mạch với client dựa trên một server typesafe mà không cần phải có các boilerplate code. Nó tận dụng kiểu dữ liệu của TypeScript một cách thông minh nhằm nâng cao trải nghiệm phát triển ứng dụng. ### Prisma -Prisma is to SQL what TypeScript is to JS. It created a developer experience that didn't exist before. By generating types from a user-defined schema compatible with [several databases](https://www.prisma.io/docs/concepts/database-connectors), Prisma guarantees end-to-end typesafety from your database to your app. +Prisma và SQL cũng giống như TypeScript và JS. Nó đã tạo ra một trải nghiệm phát triển chưa từng tồn tại trước đây. Bằng cách tạo ra các kiểu từ một file schema do người dùng định nghĩa và có tính tương thích cao với [nhiều cơ sở dữ liệu](https://www.prisma.io/docs/concepts/database-connectors), Prisma đảm bảo tính toàn vẹn dữ liệu (typesafety) từ đầu đến cuối từ cơ sở dữ liệu đến ứng dụng của bạn. -Prisma provides a whole [suite of tools](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows) making daily interactions with your database easier. Notably, the Prisma Client is responsible for querying and making SQL so easy you'll barely notice you're using it, and Prisma Studio is a convenient GUI for your database that lets you read and manipulate your data quickly without having to write code. +Prisma cung cấp cả một [bộ công cụ](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows) giúp việc tương tác hàng ngày với cơ sở dữ liệu của bạn trở nên dễ dàng hơn. Đáng chú ý, Prisma Client chịu trách nhiệm truy vấn và làm cho SQL trở nên dễ dàng đến mức bạn sẽ hầu như không nhận thấy mình đang làm việc với cơ sở dữ liệu, và Prisma Studio là một GUI tiện lợi cho cơ sở dữ liệu của bạn bằng cách cho phép bạn đọc và thao tác dữ liệu trực tiếp mà không cần viết mã. ### Tailwind CSS -Tailwind feels like "zen-mode CSS". +Tailwind giống như "CSS ở chế độ chill". -By providing building blocks in the form of good default colors, spacing, and other primitives, Tailwind makes it easy to create a good-looking app. And unlike component libraries, it does not hold you back when you want to take your app to the next level and create something beautiful and unique. +Bằng cách cung cấp các khối xây dựng dưới dạng các gam màu mặc định hiện đại, khoảng cách và các yếu tố cơ bản khác, Tailwind giúp dễ dàng tạo ra một ứng dụng đẹp mắt. Và không giống như các thư viện component khác, nó giúp bạn đưa ứng dụng của mình lên một tầm cao mới và tạo ra thứ gì đó đẹp đẽ và độc đáo. -Additionally, with its inline-like approach, Tailwind encourages you to style without worrying about naming classes, organizing files, or any other issue not directly tied to the problem you're trying to solve. +Ngoài ra, với cách tiếp cận giống như inline, Tailwind khuyến khích bạn tạo kiểu mà không cần lo lắng về việc đặt tên lớp, tổ chức tệp hoặc bất kỳ vấn đề nào khác không liên quan trực tiếp đến vấn đề bạn đang cố gắng giải quyết. ### NextAuth.js -When you want an authentication system in your NextJS application, NextAuth.js is an excellent solution to bring in the complexity of security without the hassle of having to build it yourself. It comes with an extensive list of providers to quickly add OAuth authentication and provides adapters for many databases and ORMs. +Khi bạn muốn có một hệ thống xác thực trong ứng dụng NextJS của mình, NextAuth.js là một giải pháp tuyệt vời để giải quyết sự phức tạp của bảo mật mà không gặp rắc rối khi phải tự xây dựng nó. Nó đi kèm với một dãy các nhà cung cấp xác thực thứ 3 để bạn có thể thêm xác thực OAuth một cách nhanh chóng và đồng thời cung cấp các adapter cho nhiều cơ sở dữ liệu và ORM. From 98dfd923a6229e29258c09baef3ed88f2fc2ba6f Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Tue, 22 Apr 2025 22:32:59 +1000 Subject: [PATCH 03/12] docs(vi): Update Vietnamese for Installation Page --- www/src/pages/vi/installation.mdx | 61 ++++++++++++++++--------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/www/src/pages/vi/installation.mdx b/www/src/pages/vi/installation.mdx index 34d183f1a5..c21c3b5e16 100644 --- a/www/src/pages/vi/installation.mdx +++ b/www/src/pages/vi/installation.mdx @@ -1,14 +1,14 @@ --- -title: Installation -description: Installation instructions for Create T3 App +title: Cài đặt +description: Hướng dẫn cài đặt Create T3 App layout: ../../layouts/docs.astro -lang: en +lang: vi isMdx: true --- import Callout from "../../components/docs/callout.tsx"; -To scaffold an app using `create-t3-app`, run any of the following commands and answer the command prompt questions: +Để khởi tạo một ứng dụng sử dụng `create-t3-app`, hãy chạy bất kỳ lệnh sau đây và trả lời các câu hỏi của được đưa ra: ### npm @@ -34,49 +34,50 @@ pnpm create t3-app@latest bun create t3-app@latest ``` -After your app has been scaffolded, check out the [first steps](/en/usage/first-steps) to get started on your new application. +Sau khi ứng dụng của bạn đã được khởi tạo, hãy đọc [bước đầu tiên](/vi/usage/first-steps) để bắt đầu phát triển ứng dụng mới của bạn. -## Advanced usage +## Sử dụng nâng cao -| Option/Flag | Description | -| ----------------- | ----------------------------------------------------------------------- | -| `[dir]` | Include a directory argument with a name for the project | -| `--noGit` | Explicitly tell the CLI to not initialize a new git repo in the project | -| `-y`, `--default` | Bypass the CLI and bootstrap a new t3-app with all options selected | -| `--noInstall` | Generate project without installing dependencies | +| Tùy chọn | Mô tả | +| ----------------- | ---------------------------------------------------------------- | +| `[dir]` | Bao gồm đối số thư mục với tên cho dự án | +| `--noGit` | Không khởi tạo repo git mới trong dự án | +| `-y`, `--default` | Bỏ qua câu hỏi và khởi tạo dự án mới với tất cả tùy chọn đã chọn | +| `--noInstall` | Tạo dự án mà không cài đặt các thư viện đi kèm | -## Experimental usage +## Sử dụng với những tùy chọn thử nghiệm -For our CI, we have some experimental flags that allow you to scaffold any app without any prompts. If this use case applies to you, you can use these flags. Please note that these flags are experimental and may change in the future without following semver versioning. +Đối với CI của chúng tôi, chúng tôi cung cấp một số tùy chọn thử nghiệm cho phép bạn khởi tạo bất kỳ ứng dụng nào mà không cần bất kỳ câu hỏi nào. Nếu trường hợp này áp dụng cho bạn, bạn có thể sử dụng các tùy chọn này. Xin lưu ý rằng chúng tôi đang thử nghiệm các tùy chọn này và có thể thay đổi trong tương lai mà không tuân theo phiên bản semver. -| Flag | Description | -| ------------------------- | -------------------------------------------- | -| `--CI` | Let the CLI know you're in CI mode | -| `--trpc` | Include tRPC in the project | -| `--prisma` | Include Prisma in the project | -| `--drizzle` | Include Drizzle in the project | -| `--nextAuth` | Include NextAuth.js in the project | -| `--tailwind` | Include Tailwind CSS in the project | -| `--dbProvider [provider]` | Include a configured database in the project | -| `--appRouter` | Use Next.js App Router in the project | +| Tùy chọn | Mô tả | +| ------------------------- | ------------------------------------------------ | +| `--CI` | Cho phép CLI biết bạn đang ở trong môi trường CI | +| `--trpc` | Sử dụng tRPC trong dự án | +| `--prisma` | Sử dụng Prisma trong dự án | +| `--drizzle` | Sử dụng Drizzle trong dự án | +| `--nextAuth` | Sử dụng NextAuth.js trong dự án | +| `--tailwind` | Sử dụng Tailwind CSS trong dự án | +| `--dbProvider [provider]` | Sử dụng cơ sở dữ liệu đã cấu hình trong dự án | +| `--appRouter` | Sử dụng Next.js App Router trong dự án | - If you don't provide the `CI` flag, the rest of these flags have no effect. + Nếu tùy chọn `CI` không được sử dụng, các tùy chọn còn lại sẽ không có hiệu + lực. -You don't need to explicitly opt-out of the packages you don't want. However, if you prefer to be explicit, you can pass `false`, e.g. `--nextAuth false`. +Bạn không nhất thiết phải loại bỏ các tùy chọn mà bạn không muốn. Tuy nhiên, nếu bạn muốn loại bỏ chúng, bạn có thể truyền `false` vào sau các tùy chọn, ví dụ: `--nextAuth false`. -The --dbProvider command has 4 database values to choose from: mysql, postgres, planetscale, sqlite. If the command is not provided the default value will be sqlite. +Tùy chọn `--dbProvider` cung cấp 4 cơ sở dữ liệu cho bạn chọn: mysql, postgres, planetscale, sqlite. Nếu tùy chọn này không được sử dụng, giá trị mặc định sẽ là sqlite. -### Example +### Ví dụ -The following would scaffold a T3 App with tRPC and Tailwind CSS. +Ví dụ sau sẽ tạo ra một ứng dụng T3 với tRPC và Tailwind CSS. ```bash pnpm dlx create-t3-app@latest --CI --trpc --tailwind ``` -The following would scaffold a T3 App with NextAuth.js, Tailwind CSS, Drizzle, and PostgreSQL. +Ví dụ sau sẽ tạo ra một ứng dụng T3 với NextAuth.js, Tailwind CSS, Drizzle, và PostgreSQL. ```bash pnpm dlx create-t3-app@latest --CI --nextAuth --tailwind --drizzle --dbProvider postgres From b64fdfb6b54e1f12eb539029343071f17b125a7b Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Wed, 23 Apr 2025 07:41:35 +1000 Subject: [PATCH 04/12] docs(vi): Update Vietnamese for Folder Structure (Pages and App Router) Page --- www/src/pages/vi/folder-structure-app.mdx | 84 ++++++++++----------- www/src/pages/vi/folder-structure-pages.mdx | 82 ++++++++++---------- 2 files changed, 83 insertions(+), 83 deletions(-) diff --git a/www/src/pages/vi/folder-structure-app.mdx b/www/src/pages/vi/folder-structure-app.mdx index e0f3d77b85..707df695c7 100644 --- a/www/src/pages/vi/folder-structure-app.mdx +++ b/www/src/pages/vi/folder-structure-app.mdx @@ -1,15 +1,15 @@ --- -title: Folder Structure (App) -description: Folder structure of a newly scaffolded T3 App with the App Router +title: Cấu trúc thư mục (App Router) +description: Cấu trúc thư mục của một ứng dụng T3 được tạo mới với App Router layout: ../../layouts/docs.astro -lang: en +lang: vi isMdx: true --- import Diagram from "../../components/docs/folderStructureDiagramApp.astro"; import Form from "../../components/docs/folderStructureForm.astro"; -Please select your packages to see the folder structure of a newly scaffolded app with those selections. Further down, you will find a description of each entry. +Vui lòng chọn các thư viện được đề cập ở dưới để xem cấu trúc thư mục của một ứng dụng T3 được tạo mới với các lựa chọn đó. Ở phía dưới, bạn sẽ tìm thấy mô tả chi tiết cho mỗi file trong cây thư mục.
@@ -19,124 +19,124 @@ Please select your packages to see the folder structure of a newly scaffolded ap ### `prisma` -The `prisma` folder contains the `schema.prisma` file which is used to configure the database connection and the database schema. It is also the location to store migration files and/or seed scripts, if used. See [Prisma usage](/en/usage/prisma) for more information. +Thư mục `prisma` chứa file `schema.prisma` được sử dụng để cấu hình kết nối với cơ sở dữ liệu và định nghĩa schema cho cơ sở dữ liệu. Đây cũng là nơi lưu trữ các file migration và/hoặc seed script, nếu được sử dụng. Tham khảo [Cách sử dụng Prisma](/vi/usage/prisma) để biết thêm thông tin.
### `public` -The `public` folder contains static assets that are served by the web server. The `favicon.ico` file is an example of a static asset. +Thư mục `public` chứa các file tĩnh (static assets) được phục vụ bởi web server. File `favicon.ico` là một ví dụ về file tĩnh.
### `src/env` -Used for environment variable validation and type definitions - see [Environment Variables](usage/env-variables). +Được sử dụng để xác thực biến môi trường (environment variables) và định nghĩa kiểu cho biến môi trường (environment variables) đó - Tham khảo [Biến môi trường](/vi/usage/env-variables).
### `src/app` -The `app` folder contains all the routes of the Next.js application. The `page.tsx` file at the root directory of `/app` is the homepage of the application. The `layout.tsx` file is used to wrap the application with providers. See [Next.js documentation](https://nextjs.org/docs/basic-features/pages) for more information. +Thư mục `app` chứa tất cả các định tuyến (routes) của ứng dụng Next.js. File `page.tsx` ở thư mục gốc `/app` là trang chủ của ứng dụng. File `layout.tsx` được sử dụng để định nghĩa layout cho ứng dụng và bao bọc ứng dụng với các provider. Tham khảo [tài liệu Next.js](https://nextjs.org/docs/app/building-your-application/routing) để biết thêm thông tin.
#### `src/app/_components/post.tsx` -The `post.tsx` file is an example of a client component that calls a tRPC mutation. +File `post.tsx` là một ví dụ về client component mà một tRPC mutation được sử dụng.
#### `src/app/api/auth/[...nextauth]/route.ts` -The `[...nextauth]/route.ts` file is the NextAuth.js authentication slug route. It is used to handle authentication requests. See [NextAuth.js usage](usage/next-auth) for more information on NextAuth.js, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) for info on catch-all/slug routes. +File `[...nextauth]/route.ts` là slug route xác thực của NextAuth.js. Nó được sử dụng để xử lý các yêu cầu xác thực. Tham khảo [Cách sử dụng NextAuth.js](/vi/usage/next-auth) để biết thêm thông tin về NextAuth.js, và [Tài liệu Next.js Dynamic Routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) để biết thông tin về các route catch-all/slug.
#### `src/app/api/trpc/[trpc]/route.ts` -The `[trpc].ts` file is the tRPC API entrypoint. It is used to handle tRPC requests. See [tRPC usage](usage/trpc#-pagesapitrpctrpcts) for more information on this file, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/app/routing/dynamic-routes) for info on catch-all/slug routes. +File `[trpc].ts` là điểm xuất phát (entrypoint) API của tRPC. Nó được sử dụng để xử lý các yêu cầu tRPC. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc) để biết thêm thông tin về file này, và [Tài liệu Next.js Dynamic Routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) để biết thông tin về các route catch-all/slug.
### `src/server` -The `server` folder is used to clearly separate code that is only used on the server. +Thư mục `server` được sử dụng để phân tách rõ ràng code chỉ được sử dụng và thực thi trên server.
#### `src/server/auth.ts` -The main entrypoint for server-side authentication logic. Here, we setup the NextAuth.js [configuration options](usage/next-auth), perform [module augmentation](usage/next-auth#inclusion-of-userid-on-the-session) as well as provide some DX utilities for authentication such as retrieving the user's session on the server-side. See [NextAuth.js usage](usage/next-auth#usage-with-trpc) for more information. +Điểm xuất phát (entrypoint) cho logic xác thực phía server. Tại đây, chúng ta thiết lập các [tùy chọn cấu hình](/vi/usage/next-auth) NextAuth.js, thực hiện [module augmentation](/vi/usage/next-auth#inclusion-of-userid-on-the-session) cũng như cung cấp một số tiện ích DX cho việc xác thực như lấy session của người dùng ở phía server. Tham khảo [Cách sử dụng NextAuth.js](/vi/usage/next-auth#usage-with-trpc) để biết thêm thông tin.
#### `src/server/db.ts` -The `db.ts` file is used to instantiate the Prisma client at global scope. See [Prisma usage](usage/prisma#prisma-client) and [best practices for using Prisma with Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) for more information. +File `db.ts` được sử dụng để khởi tạo Prisma client ở phạm vi toàn cục (global scope). Tham khảo [Cách sử dụng Prisma](/vi/usage/prisma#prisma-client) và [các phương pháp tốt nhất để sử dụng Prisma với Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) để biết thêm thông tin.
### `src/server/db` -The `db` folder contains the Drizzle client and schema. Note that drizzle also requires the `drizzle.config.ts` file (see below). +Thư mục `db` chứa Drizzle client và schema. Lưu ý rằng drizzle cũng yêu cầu file cấu hình `drizzle.config.ts` (xem bên dưới).
#### `src/server/db/index.ts` -The `index.ts` file is used to instantiate the Drizzle client at global scope. See [Drizzle usage](usage/drizzle#drizzle-client) for more information. +File `index.ts` được sử dụng để khởi tạo Drizzle client ở phạm vi toàn cục. Tham khảo [Cách sử dụng Drizzle](/vi/usage/drizzle#drizzle-client) để biết thêm thông tin.
#### `src/server/db/schema.ts` -The `schema.ts` file is used to define the database schema. See [Drizzle usage](usage/drizzle#drizzle-client) and [Drizzle schema docs](https://orm.drizzle.team/docs/sql-schema-declaration) for more information. +File `schema.ts` được sử dụng để định nghĩa schema cơ sở dữ liệu. Tham khảo [Cách sử dụng Drizzle](/vi/usage/drizzle#drizzle-client) và [tài liệu Drizzle schema](https://orm.drizzle.team/docs/sql-schema-declaration) để biết thêm thông tin.
### `src/server/api` -The `api` folder contains the tRPC server-side code. +Thư mục `api` chứa code tRPC phía server.
#### `src/server/api/routers` -The `routers` folder contains all your tRPC sub-routers. +Thư mục `routers` chứa tất cả các sub-router tRPC của bạn.
#### `src/server/api/routers/example.ts` -The `example.ts` file is an example tRPC router utilizing the `publicProcedure` helper to demonstrate how to create a public tRPC route. +File `example.ts` là một ví dụ về tRPC router sử dụng helper `publicProcedure` để minh họa cách tạo một tRPC route công khai. -Depending on your chosen packages this router contains more or less routes to best demonstrate the usage to your needs. +Tùy thuộc vào các thư viện bạn đã chọn, router này chứa nhiều hoặc ít route hơn để minh họa tốt nhất cách sử dụng phù hợp với nhu cầu của bạn.
#### `src/server/api/trpc.ts` -The `trpc.ts` file is the main configuration file for your tRPC back-end. In here we: +File `trpc.ts` là file cấu hình chính cho back-end tRPC của bạn. Tại đây chúng ta: -1. Define context used in tRPC requests. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information. -2. Export procedure helpers. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information. +1. Định nghĩa context được sử dụng trong các yêu cầu tRPC. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapitrpcts) để biết thêm thông tin. +2. Xuất các helper procedure. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapitrpcts) để biết thêm thông tin.
@@ -144,111 +144,111 @@ The `trpc.ts` file is the main configuration file for your tRPC back-end. In her #### `src/server/api/root.ts` -The `root.ts` file is used to merge tRPC routers and export them as a single router, as well as the router's type definition. See [tRPC usage](usage/trpc#-serverapirootts) for more information. +File `root.ts` được sử dụng để hợp nhất các tRPC router và xuất chúng dưới dạng một router duy nhất, cũng như định nghĩa kiểu của router. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapirootts) để biết thêm thông tin.
### `src/trpc` -The `trpc` folder contains the setup to let you call tRPC procedures from server components and client components. +Thư mục `trpc` chứa thiết lập để cho phép bạn gọi các procedure tRPC từ server component và client component.
#### `src/trpc/query-client.ts` -The `query-client.ts` file creates the Query Client that tRPC uses to cache and deduplicate data in client components. +File `query-client.ts` tạo ra Query Client mà tRPC sử dụng để cache và loại bỏ dữ liệu trùng lặp trong client component.
#### `src/trpc/react.tsx` -The `react.tsx` file is the front-end entrypoint to tRPC. It also contains utility types for the router inputs and outputs. See [tRPC usage](usage/trpc#-utilsapits) for more information. +File `react.tsx` là điểm bắt đầu phía front-end cho tRPC. Nó cũng chứa các kiểu dữ liệu được định nghĩa cho input và output của router. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc) để biết thêm thông tin.
#### `src/trpc/server.ts` -The `server.ts` file is the entrypoint for using tRPC in Server Components. +File `server.ts` là điểm bắt đầu để sử dụng tRPC trong Server Component.
### `.env` -The `.env` file is used to store environment variables. See [Environment Variables](usage/env-variables) for more information. This file should **not** be committed to git history. +File `.env` được sử dụng để lưu trữ các biến môi trường. Tham khảo [Biến môi trường](/vi/usage/env-variables) để biết thêm thông tin. File này **không** nên được commit vào lịch sử git.
### `.env.example` -The `.env.example` file shows example environment variables based on the chosen libraries. This file should be committed to git history. +File `.env.example` hiển thị các biến môi trường ví dụ dựa trên các thư viện đã chọn. File này **nên** được commit vào lịch sử git.
### `.eslintrc.cjs` -The `.eslintrc.cjs` file is used to configure ESLint. See [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) for more information. +File `.eslintrc.cjs` được sử dụng để cấu hình ESLint. Tham khảo [Tài liệu ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) để biết thêm thông tin.
-### `db.sqlite (sqlite only)` +### `db.sqlite (chỉ sqlite)` -The `db.sqlite` file contains your development database. This file is only created after running the `db:push` parseCommandLine, and ignored by git. +File `db.sqlite` chứa cơ sở dữ liệu phát triển của bạn. File này chỉ được tạo sau khi chạy lệnh `db:push` và bị bỏ qua bởi git.
### `drizzle.config.ts` -The `drizzle.config.ts` file is used to configure drizzle kit. See [the documentation](https://orm.drizzle.team/kit-docs/config-reference) for more information. +File `drizzle.config.ts` được sử dụng để cấu hình drizzle kit. Tham khảo [tài liệu](https://orm.drizzle.team/kit-docs/config-reference) để biết thêm thông tin.
### `next-env.d.ts` -The `next-env.d.ts` file ensures Next.js types are picked up by the TypeScript compiler. **You should not remove it or edit it as it can change at any time.** See [Next.js Docs](https://nextjs.org/docs/app/building-your-application/configuring/typescript) for more information. +File `next-env.d.ts` đảm bảo các kiểu của Next.js được trình biên dịch TypeScript nhận diện. **Bạn không nên xóa hoặc chỉnh sửa nó vì nó có thể thay đổi bất cứ lúc nào.** Tham khảo [Tài liệu Next.js](https://nextjs.org/docs/app/building-your-application/configuring/typescript) để biết thêm thông tin.
### `next.config.mjs` -The `next.config.mjs` file is used to configure Next.js. See [Next.js Docs](https://nextjs.org/docs/api-reference/next.config.js/introduction) for more information. Note: The .mjs extension is used to allow for ESM imports. +File `next.config.mjs` được sử dụng để cấu hình Next.js. Tham khảo [Tài liệu Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction) để biết thêm thông tin. Lưu ý: Phần mở rộng .mjs được sử dụng để cho phép import ESM.
### `postcss.config.js` -The `postcss.config.js` file is used for Tailwind PostCSS usage. See [Tailwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss) for more information. +File `postcss.config.js` được sử dụng cho việc sử dụng Tailwind PostCSS. Tham khảo [Tài liệu Tailwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss) để biết thêm thông tin.
### `prettier.config.mjs` -The `prettier.config.mjs` file is used to configure Prettier to include the prettier-plugin-tailwindcss for formatting Tailwind CSS classes. See the [Tailwind CSS blog post](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) for more information. +File `prettier.config.mjs` được sử dụng để cấu hình Prettier bao gồm `prettier-plugin-tailwindcss` để định dạng các lớp Tailwind CSS. Tham khảo [bài đăng blog Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) để biết thêm thông tin.
-### `start-database.sh (mysql or postgres only)` +### `start-database.sh (chỉ mysql hoặc postgres)` -The `start-database.sh` file is used to start the database. Please see the comments inside the file for information on how to start the database with your operating system. +File `start-database.sh` được sử dụng để khởi động cơ sở dữ liệu. Vui lòng xem các ghi chú chúng tôi đã đề cập ở bên trong file để biết thông tin về cách khởi động cơ sở dữ liệu với hệ điều hành của bạn.
### `tsconfig.json` -The `tsconfig.json` file is used to configure TypeScript. Some non-defaults, such as `strict mode`, have been enabled to ensure the best usage of TypeScript for Create T3 App and its libraries. See [TypeScript Docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) or [TypeScript Usage](usage/typescript) for more information. +File `tsconfig.json` được sử dụng để cấu hình TypeScript. Một số tùy chọn không mặc định, chẳng hạn như `strict mode`, đã được bật để đảm bảo việc sử dụng TypeScript tốt nhất cho Create T3 App và các thư viện của nó. Xem [Tài liệu TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) hoặc [Cách sử dụng TypeScript](/vi/usage/typescript) để biết thêm thông tin.
diff --git a/www/src/pages/vi/folder-structure-pages.mdx b/www/src/pages/vi/folder-structure-pages.mdx index a9c49aed4d..961fc3f2dc 100644 --- a/www/src/pages/vi/folder-structure-pages.mdx +++ b/www/src/pages/vi/folder-structure-pages.mdx @@ -1,15 +1,15 @@ --- -title: Folder Structure (Pages) -description: Folder structure of a newly scaffolded T3 App with the Pages Router +title: Cấu trúc thư mục (Pages Router) +description: Cấu trúc thư mục của một ứng dụng T3 được tạo mới với Pages Router layout: ../../layouts/docs.astro -lang: en +lang: vi isMdx: true --- import Diagram from "../../components/docs/folderStructureDiagramPages.astro"; import Form from "../../components/docs/folderStructureForm.astro"; -Please select your packages to see the folder structure of a newly scaffolded app with those selections. Further down, you will find a description of each entry. +Vui lòng chọn các thư viện được đề cập ở dưới để xem cấu trúc thư mục của một ứng dụng T3 được tạo mới với các lựa chọn đó. Ở phía dưới, bạn sẽ tìm thấy mô tả chi tiết cho mỗi file trong cây thư mục. @@ -19,124 +19,124 @@ Please select your packages to see the folder structure of a newly scaffolded ap ### `prisma` -The `prisma` folder contains the `schema.prisma` file which is used to configure the database connection and the database schema. It is also the location to store migration files and/or seed scripts, if used. See [Prisma usage](/en/usage/prisma) for more information. +Trong thư mục `prisma`, một file `schema.prisma` được sử dụng để cấu hình kết nối với cơ sở dữ liệu và định nghĩa schema cho cơ sở dữ liệu. Đây cũng là nơi lưu trữ các file migration và/hoặc seed script, nếu được sử dụng. Tham khảo [Cách sử dụng Prisma](/vi/usage/prisma) để biết thêm thông tin.
### `public` -The `public` folder contains static assets that are served by the web server. The `favicon.ico` file is an example of a static asset. +Thư mục `public` chứa các file tĩnh (static assets) được phục vụ bởi web server. File `favicon.ico` là một ví dụ về file tĩnh.
### `src/env` -Used for environment variable validation and type definitions - see [Environment Variables](usage/env-variables). +Được sử dụng để xác thực biến môi trường (environment variables) và định nghĩa kiểu cho biến môi trường (environment variables) đó - Tham khảo [Biến môi trường](/vi/usage/env-variables).
### `src/pages` -The `pages` folder contains all the pages of the Next.js application. The `index.tsx` file at the root directory of `/pages` is the homepage of the application. The `_app.tsx` file is used to wrap the application with providers. See [Next.js documentation](https://nextjs.org/docs/basic-features/pages) for more information. +Thư mục `pages` chứa tất cả các trang của ứng dụng Next.js. File `index.tsx` ở thư mục gốc `/pages` là trang chủ và là điểm bắt đầu của ứng dụng. File `_app.tsx` được sử dụng để bao bọc ứng dụng với các provider. Tham khảo [tài liệu Next.js](https://nextjs.org/docs/basic-features/pages) để biết thêm thông tin.
#### `src/pages/api` -The `api` folder contains all the API routes of the Next.js application. See [Next.js Api Routes Docs](https://nextjs.org/docs/api-routes/introduction) for info on api routes. +Thư mục `api` là nơi bạn định nghĩa các API route của ứng dụng Next.js. Tham khảo [Tài liệu Next.js Api Routes](https://nextjs.org/docs/api-routes/introduction) để biết thêm thông tin về các API route.
#### `src/pages/api/auth/[...nextauth].ts` -The `[...nextauth].ts` file is the NextAuth.js authentication slug route. It is used to handle authentication requests. See [NextAuth.js usage](usage/next-auth) for more information on NextAuth.js, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) for info on catch-all/slug routes. +File `[...nextauth].ts` là một slug route của Next.js được sử dụng để xử lý các yêu cầu xác thực của NextAuth.js. Tham khảo [Cách sử dụng NextAuth.js](/vi/usage/next-auth) để biết thêm thông tin về NextAuth.js, và [Tài liệu Next.js Dynamic Routes](https://nextjs.org/docs/routing/dynamic-routes) để biết thông tin về các route catch-all/slug.
#### `src/pages/api/trpc/[trpc].ts` -The `[trpc].ts` file is the tRPC API entrypoint. It is used to handle tRPC requests. See [tRPC usage](usage/trpc#-pagesapitrpctrpcts) for more information on this file, and [Next.js Dynamic Routes Docs](https://nextjs.org/docs/routing/dynamic-routes) for info on catch-all/slug routes. +File `[trpc].ts` là điểm xuất phát (entrypoint) API của tRPC. Nó được sử dụng để xử lý các yêu cầu tRPC. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-pagesapitrpctrpcts) để biết thêm thông tin về file này, và [Tài liệu Next.js Dynamic Routes](https://nextjs.org/docs/routing/dynamic-routes) để biết thông tin về các route catch-all/slug.
### `src/server` -The `server` folder is used to clearly separate code that is only used on the server. +Thư mục `server` được sử dụng để định nghĩa code chỉ được sử dụng và thực thi trên server.
#### `src/server/auth.ts` -The main entrypoint for server-side authentication logic. Here, we setup the NextAuth.js [configuration options](usage/next-auth), perform [module augmentation](usage/next-auth#inclusion-of-userid-on-the-session) as well as provide some DX utilities for authentication such as retrieving the user's session on the server-side. See [NextAuth.js usage](usage/next-auth#usage-with-trpc) for more information. +Điểm bắt đầu (Entrypoint) cho logic xác thực phía server. Tại đây, chúng ta thiết lập các [tùy chọn cấu hình](usage/next-auth) NextAuth.js, thực hiện [module augmentation](usage/next-auth#inclusion-of-userid-on-the-session) cũng như cung cấp một số tiện ích DX cho việc xác thực như lấy session của người dùng ở phía server. Tham khảo [Cách sử dụng NextAuth.js](/vi/usage/next-auth#usage-with-trpc) để biết thêm thông tin.
#### `src/server/db.ts` -The `db.ts` file is used to instantiate the Prisma client at global scope. See [Prisma usage](usage/prisma#prisma-client) and [best practices for using Prisma with Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) for more information. +File `db.ts` được sử dụng để khởi tạo Prisma client ở phạm vi toàn cục (global scope). Tham khảo [Cách sử dụng Prisma](/vi/usage/prisma#prisma-client) và [các phương pháp tốt nhất để sử dụng Prisma với Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) để biết thêm thông tin.
### `src/server/db` -The `db` folder contains the Drizzle client and schema. Note that drizzle also requires the `drizzle.config.ts` file (see below). +Thư mục `db` chứa Drizzle client và schema. Lưu ý rằng drizzle cũng yêu cầu file cấu hình `drizzle.config.ts` (xem bên dưới).
#### `src/server/db/index.ts` -The `index.ts` file is used to instantiate the Drizzle client at global scope. See [Drizzle usage](usage/drizzle#drizzle-client) for more information. +File `index.ts` được sử dụng để khởi tạo Drizzle client ở phạm vi toàn cục. Tham khảo [Cách sử dụng Drizzle](/vi/usage/drizzle#drizzle-client) để biết thêm thông tin.
#### `src/server/db/schema.ts` -The `schema.ts` file is used to define the database schema. See [Drizzle usage](usage/drizzle#drizzle-client) and [Drizzle schema docs](https://orm.drizzle.team/docs/sql-schema-declaration) for more information. +File `schema.ts` được sử dụng để định nghĩa schema cơ sở dữ liệu. Tham khảo [Cách sử dụng Drizzle](/vi/usage/drizzle#drizzle-client) và [tài liệu Drizzle schema](https://orm.drizzle.team/docs/sql-schema-declaration) để biết thêm thông tin.
### `src/server/api` -The `api` folder contains the tRPC server-side code. +Thư mục `api` chứa code tRPC phía server.
#### `src/server/api/routers` -The `routers` folder contains all your tRPC sub-routers. +Thư mục `routers` chứa tất cả các sub-router tRPC của bạn.
#### `src/server/api/routers/example.ts` -The `example.ts` file is an example tRPC router utilizing the `publicProcedure` helper to demonstrate how to create a public tRPC route. +File `example.ts` là một ví dụ về tRPC router sử dụng helper `publicProcedure` để minh họa cách tạo một route tRPC công khai không cần xác thực. -Depending on your chosen packages this router contains more or less routes to best demonstrate the usage to your needs. +Tùy thuộc vào các thư viện bạn đã chọn, router này có thể chứa nhiều hoặc ít route hơn tùy vào cách sử dụng phù hợp với nhu cầu của bạn.
#### `src/server/api/trpc.ts` -The `trpc.ts` file is the main configuration file for your tRPC back-end. In here we: +File `trpc.ts` là file định nghĩa cấu hình chính cho back-end tRPC của bạn. Tại đây chúng ta: -1. Define context used in tRPC requests. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information. -2. Export procedure helpers. See [tRPC usage](usage/trpc#-serverapitrpcts) for more information. +1. Định nghĩa context được sử dụng trong các yêu cầu tRPC. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapitrpcts) để biết thêm thông tin. +2. Định nghĩa các helper procedure. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapitrpcts) để biết thêm thông tin.
@@ -144,104 +144,104 @@ The `trpc.ts` file is the main configuration file for your tRPC back-end. In her #### `src/server/api/root.ts` -The `root.ts` file is used to merge tRPC routers and export them as a single router, as well as the router's type definition. See [tRPC usage](usage/trpc#-serverapirootts) for more information. +File `root.ts` được sử dụng để hợp nhất các tRPC router và đưa chúng dưới dạng một router duy nhất, cũng như được sử dụng để định nghĩa kiểu của router. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapirootts) để biết thêm thông tin.
### `src/styles` -The `styles` folder contains the global styles of the application. +Thư mục `styles` chứa các style toàn cục của ứng dụng.
### `src/utils` -The `utils` folder is used to store commonly re-used utility functions. +Thư mục `utils` được sử dụng để lưu trữ các hàm thường được tái sử dụng.
#### `src/utils/api.ts` -The `api.ts` file is the front-end entrypoint to tRPC. See [tRPC usage](usage/trpc#-utilsapits) for more information. +File `api.ts` là điểm bắt đầu phía front-end cho tRPC. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-utilsapits) để biết thêm thông tin.
### `.env` -The `.env` file is used to store environment variables. See [Environment Variables](usage/env-variables) for more information. This file should **not** be committed to git history. +File `.env` được sử dụng để lưu trữ các biến môi trường. Tham khảo [Biến môi trường](/vi/usage/env-variables) để biết thêm thông tin. File này **không** nên được commit vào lịch sử git.
### `.env.example` -The `.env.example` file shows example environment variables based on the chosen libraries. This file should be committed to git history. +File `.env.example` hiển thị các biến môi trường ví dụ dựa trên các thư viện đã chọn. File này **nên** được commit vào lịch sử git.
### `.eslintrc.cjs` -The `.eslintrc.cjs` file is used to configure ESLint. See [ESLint Docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) for more information. +File `.eslintrc.cjs` được sử dụng để cấu hình ESLint. Tham khảo [Tài liệu ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) để biết thêm thông tin.
-### `db.sqlite (sqlite only)` +### `db.sqlite (chỉ sqlite)` -The `db.sqlite` file contains your development database. This file is only created after running the `db:push` parseCommandLine, and ignored by git. +File `db.sqlite` chứa cơ sở dữ liệu phát triển của bạn. File này chỉ được tạo sau khi chạy lệnh `db:push` và bị bỏ qua bởi git.
### `drizzle.config.ts` -The `drizzle.config.ts` file is used to configure drizzle kit. See [the documentation](https://orm.drizzle.team/kit-docs/config-reference) for more information. +File `drizzle.config.ts` được sử dụng để cấu hình drizzle kit. Tham khảo [tài liệu](https://orm.drizzle.team/kit-docs/config-reference) để biết thêm thông tin.
### `next-env.d.ts` -The `next-env.d.ts` file ensures Next.js types are picked up by the TypeScript compiler. **You should not remove it or edit it as it can change at any time.** See [Next.js Docs](https://nextjs.org/docs/basic-features/typescript#existing-projects) for more information. +File `next-env.d.ts` đảm bảo các kiểu của Next.js được trình biên dịch TypeScript nhận diện. **Bạn không nên xóa hoặc chỉnh sửa nó vì nó có thể thay đổi bất cứ lúc nào.** Tham khảo [Tài liệu Next.js](https://nextjs.org/docs/basic-features/typescript#existing-projects) để biết thêm thông tin.
### `next.config.mjs` -The `next.config.mjs` file is used to configure Next.js. See [Next.js Docs](https://nextjs.org/docs/api-reference/next.config.js/introduction) for more information. Note: The .mjs extension is used to allow for ESM imports. +File `next.config.mjs` được sử dụng để cấu hình Next.js. Tham khảo [Tài liệu Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction) để biết thêm thông tin. Lưu ý: Phần mở rộng .mjs được sử dụng để cho phép import ESM.
### `postcss.config.js` -The `postcss.config.js` file is used for Tailwind PostCSS usage. See [Tailwind PostCSS Docs](https://tailwindcss.com/docs/installation/using-postcss) for more information. +File `postcss.config.js` được sử dụng cho việc sử dụng Tailwind PostCSS. Tham khảo [Tài liệu Tailwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss) để biết thêm thông tin.
### `prettier.config.mjs` -The `prettier.config.mjs` file is used to configure Prettier to include the prettier-plugin-tailwindcss for formatting Tailwind CSS classes. See the [Tailwind CSS blog post](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) for more information. +File `prettier.config.mjs` được sử dụng để cấu hình Prettier bao gồm `prettier-plugin-tailwindcss` để định dạng các lớp Tailwind CSS. Tham khảo [bài đăng blog Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) để biết thêm thông tin.
-### `start-database.sh (mysql or postgres only)` +### `start-database.sh (chỉ mysql hoặc postgres)` -The `start-database.sh` file is used to start the database. Please see the comments inside the file for information on how to start the database with your operating system. +File `start-database.sh` được sử dụng để khởi động cơ sở dữ liệu. Vui lòng xem các ghi chú chúng tôi đã đề cập ở bên trong file để biết thông tin về cách khởi động cơ sở dữ liệu với hệ điều hành của bạn.
### `tsconfig.json` -The `tsconfig.json` file is used to configure TypeScript. Some non-defaults, such as `strict mode`, have been enabled to ensure the best usage of TypeScript for Create T3 App and its libraries. See [TypeScript Docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) or [TypeScript Usage](usage/typescript) for more information. +File `tsconfig.json` được sử dụng để cấu hình TypeScript. Một số tùy chọn không mặc định, chẳng hạn như `strict mode`, đã được bật để đảm bảo việc sử dụng TypeScript tốt nhất cho Create T3 App và các thư viện của nó. Xem [Tài liệu TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) hoặc [Cách sử dụng TypeScript](/vi/usage/typescript) để biết thêm thông tin.
From a4d6cba7f7b73269ada3d1c170db8c534e774260 Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Wed, 23 Apr 2025 08:46:48 +1000 Subject: [PATCH 05/12] docs(vi): Update Vietnamese for Example, FAQ, Other Collections, T3 Collection Pages and add Example and Drizzle to config.ts --- www/src/config.ts | 2 + www/src/pages/vi/examples.mdx | 13 +-- www/src/pages/vi/faq.mdx | 58 ++++++------ www/src/pages/vi/other-recs.md | 142 ++++++++++++++--------------- www/src/pages/vi/t3-collection.mdx | 20 ++-- 5 files changed, 119 insertions(+), 116 deletions(-) diff --git a/www/src/config.ts b/www/src/config.ts index 965ec6ed67..1cb894cc77 100644 --- a/www/src/config.ts +++ b/www/src/config.ts @@ -429,6 +429,7 @@ export const SIDEBAR: Sidebar = { }, { text: "Câu hỏi thường gặp", link: "vi/faq" }, { text: "T3 Collection", link: "vi/t3-collection" }, + { text: "Ví dụ", link: "vi/examples" }, { text: "Các khuyến nghị khác", link: "vi/other-recs" }, ], Usage: [ @@ -437,6 +438,7 @@ export const SIDEBAR: Sidebar = { { text: "TypeScript", link: "vi/usage/typescript" }, { text: "tRPC", link: "vi/usage/trpc" }, { text: "Prisma", link: "vi/usage/prisma" }, + { text: "Drizzle", link: "vi/usage/drizzle" }, { text: "NextAuth.js", link: "vi/usage/next-auth" }, { text: "Biến môi trường", diff --git a/www/src/pages/vi/examples.mdx b/www/src/pages/vi/examples.mdx index bc7e45fb62..bbbbcd4063 100644 --- a/www/src/pages/vi/examples.mdx +++ b/www/src/pages/vi/examples.mdx @@ -1,22 +1,23 @@ --- -title: Examples -description: Examples of different live apps +title: Ví dụ +description: Ví dụ về các ứng dụng layout: ../../layouts/docs.astro -lang: en +lang: vi isMdx: true --- import Callout from "../../components/docs/callout.tsx"; import Form from "../../components/docs/exampleOptionForm.astro"; -You can try out different combinations of technologies that create-t3-app offers. +Bạn có thể thử nghiệm các tổ hợp các công nghệ khác nhau mà create-t3-app cung cấp. - You cannot select `prisma` and `drizzle` at the same time. + Hãy lưu ý rằng nạn không thể chọn cả `prisma` và `drizzle` cùng lúc. - Some features might not work unless you create an env file + Một số tính năng có thể không hoạt động nếu bạn không tạo tệp môi trường (env + file) diff --git a/www/src/pages/vi/faq.mdx b/www/src/pages/vi/faq.mdx index b90a5b1587..38abd2a817 100644 --- a/www/src/pages/vi/faq.mdx +++ b/www/src/pages/vi/faq.mdx @@ -1,20 +1,20 @@ --- -title: FAQ -description: Frequently asked questions about Create T3 App +title: Câu hỏi thường gặp +description: Câu hỏi thường gặp về Create T3 App layout: ../../layouts/docs.astro -lang: en +lang: vi isMdx: true --- import Callout from "../../components/docs/callout.tsx"; -Here are some commonly asked questions about Create T3 App. +Dưới đây là một số câu hỏi bạn sẽ thường gặp về Create T3 App. -## What's next? How do I make an app with this? +## Vậy bây giờ tôi có thể làm gì tiếp? Làm thế nào để tôi có thể tạo một ứng dụng với T3 Stack? -We try to keep this project as simple as possible, so you can start with just the scaffolding we set up for you, and add additional things later when they become necessary. +Chúng tôi luôn cố gắng giữ cho dự án này đơn giản nhất có thể, vì vậy bạn có thể bắt đầu với những thứ đã được thiết lập sẵn, và thêm những thứ khác sau nếu như bạn cần. -If you are not familiar with the different technologies used in this project, please refer to the respective docs. If you still are in the wind, please join our [Discord](https://t3.gg/discord) and ask for help. +Nếu bạn không quen với các công nghệ được sử dụng trong dự án này, vui lòng tham khảo tài liệu tương ứng với công nghệ đó. Nếu bạn vẫn còn gặp khó khăn, hãy tham gia [Discord](https://t3.gg/discord) để được giải đáp thắc mắc của bạn. - [Next.js](https://nextjs.org/) - [NextAuth.js](https://next-auth.js.org) @@ -23,29 +23,29 @@ If you are not familiar with the different technologies used in this project, pl - [tRPC](https://trpc.io) - [Drizzle](https://orm.drizzle.team/docs/overview) -## How do I keep my app up to date? +## Làm sao để ứng dụng của tôi được cập nhật ? -Create T3 App is a scaffolding tool, not a framework. This means that once you initialize an app, it's yours. There is no postinstall CLI tool similar to help you stay up to date. If you want to keep track of any improvements we make to the template, you could [enable notifications for releases](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository) on our repository. That being said it is not really necessary to implement every change we make to the template in your app. +Create T3 App là một công cụ dùng để tạo ra một bộ khung cho ứng dụng của bạn (scaffolding tool), không phải là một framework. Điều này có nghĩa là một khi bạn khởi tạo ứng dụng, nó hoàn toàn thuộc về bạn. Không có câu lệnh CLI nào tương tự như `postinstall` để giúp bạn cập nhật ứng dụng. Nếu bạn muốn theo dõi bất kỳ cập nhật nào chúng tôi thực hiện đối với template, bạn có thể [bật thông báo cho các bản phát hành](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository) trên kho lưu trữ (repository) của chúng tôi. Tuy nhiên, việc áp dụng mọi thay đổi chúng tôi thực hiện đối với template vào ứng dụng của bạn là không thực sự cần thiết. -## What learning resources are currently available? +## Hiện tại có bất kỳ tài liệu học tập nào không ? -Although the resources listed below are some of the best that exist for the T3 Stack, the community (and [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) recommend that you just start using the stack and learn along the way by building with it. +Mặc dù các tài liệu được liệt kê dưới đây là một số tài liệu tốt nhất hiện có dành cho T3 Stack, cộng đồng (và [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) khuyên bạn nên bắt đầu sử dụng và học hỏi stack trong quá trình xây dựng với nó. -If you are considering Create T3 App, chances are you might have already used some of the parts of the stack. So why not just dive in head first and learn the other parts while you build something? +Nếu bạn đang cân nhắc Create T3 App, có khả năng bạn đã biết sử dụng một số phần của chiếc stack này. Vậy tại sao bạn không bắt đầu học các phần khác trong khi bạn xây dựng một cái gì đó, đúng không ? -Now, we realize this path doesn't work for everyone. So, if you feel like you've tried the recommendation and would still like some resources, or you just aren't confident doing it by yourself and/or feel overwhelmed by the stack, checkout these awesome tutorials on Create T3 App: +Tuy nhiên, chúng tôi cũng nhận ra kiểu học này không phù hợp với tất cả mọi người. Vì vậy, nếu bạn cảm thấy đã thử cách trên và vẫn muốn có thêm tài liệu, hoặc bạn không tự tin làm điều đó một mình và/hoặc cảm thấy quá tải bởi stack, vui lòng tham khảo các hướng dẫn tuyệt vời này về Create T3 App: -### Articles +### Bài viết -Some of these might be outdated. +Một số bài viết này có thể đã cũ. - [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f) - [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo) - [Integrating Stripe into your T3 App](https://blog.nickramkissoon.com/posts/integrate-stripe-t3) -### Videos +### Video -- [From 0 to Production - The Modern React Tutorial (RSCs, Next.js, Shadui, Drizzle, TS and more)](https://www.youtube.com/watch?v=d5x0JCZbAJs) **(recommended)** (updated 2024)* +- [From 0 to Production - The Modern React Tutorial (RSCs, Next.js, Shadui, Drizzle, TS and more)](https://www.youtube.com/watch?v=d5x0JCZbAJs) **(recommended)** (updated 2024)\* - [Jack Herrington - Build a Note Taking app with the T3 Stack](https://www.youtube.com/watch?v=J1gzN1SAhyM) - [Build a Twitter Clone with the T3 Stack - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80) - [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY) @@ -53,26 +53,26 @@ Some of these might be outdated. - [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI) - [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU) -## Why are there `.js` files in the project? +## Tại sao lại có các file `.js` trong dự án? -As per [T3-Axiom #3](/en/introduction#typesafety-isnt-optional), we treat typesafety as a first class citizen. Unfortunately, not all frameworks and plugins support TypeScript which means some of the configuration files have to be `.js` files. +Theo [T3-Axiom #3](/en/introduction#typesafety-isnt-optional), chúng tôi đề cao tính toàn vẹn của kiểu dữ liệu (typesafety). Tuy vậy, không phải tất cả các framework và plugin đều hỗ trợ TypeScript, điều này có nghĩa là một số tệp cấu hình phải ở dưới dạng `.js`. -We try to emphasize that these files are JavaScript for a reason, by explicitly declaring each file's type (`cjs` or `mjs`) depending on what's supported by the library it is used by. Also, all the `js` files in this project are still typechecked using a checkJs option in the compiler (tsconfig). +Chúng tôi nhấn mạnh rằng các tệp này được viết dưới dạng JavaScript vì một lý do, đó chính là khai báo kiểu của mỗi tệp (`cjs` hoặc `mjs`) tùy thuộc vào những gì được hỗ trợ bởi thư viện mà nó được sử dụng. Ngoài ra, tất cả các tệp `js` trong dự án này vẫn được kiểm tra kiểu dữ liệu bằng tùy chọn `checkJs` trong trình biên dịch (được định nghĩa trong tsconfig). -## I'm struggling to add i18n to my app. Is there any reference I can use? +## Tôi đang gặp khó khăn khi thêm i18n vào ứng dụng của tôi. Có bất kỳ tài liệu tham khảo nào tôi có thể sử dụng không? -We have decided against including i18n by default in `create-t3-app` because it's a very opinionated topic and there are many ways to implement it. +Chúng tôi đã quyết định không bao gồm i18n mặc định trong `create-t3-app` vì có rất nhiều ý kiến trái chiều xoay quanh chủ đề này và có nhiều cách để thực hiện nó. -However, if you struggle to implement it and want to see a reference project, we have a [reference repo](https://github.com/juliusmarminge/t3-i18n) that shows how you can add i18n to a T3 App using [next-i18next](https://github.com/i18next/next-i18next). +Tuy nhiên, nếu bạn gặp khó khăn khi thực hiện điều này và tham khảo muốn một dự án, chúng tôi có một [repository](https://github.com/juliusmarminge/t3-i18n) cho thấy cách bạn có thể thêm i18n vào một ứng dụng T3 sử dụng [next-i18next](https://github.com/i18next/next-i18next). -## Should I use `/app` from Next.js 13 or the more mature `/pages` paradigm? +## Tôi nên sử dụng `/app` từ Next.js 13 hay là vẫn sử dụng `/pages`? -You have the option when scaffolding an app using Create T3 App to opt into the `/app` directory structure. As of the time of writing, this feature is generally considered mature enough to be used in production by the T3 stack community. For an explanation of why it took us so long to include, you can watch [this video](https://www.youtube.com/watch?v=PmBfq-SpzCU). +Bạn có thể chọn sử dụng cấu trúc thư mục `/app` khi khởi tạo một ứng dụng bằng Create T3 App. Tại thời điểm hiện tại, tính năng này đã được coi là đủ ổn định để được sử dụng trong môi trường production bởi cộng đồng T3 Stack. Để hiểu lý do tại sao chúng tôi đã tốn nhiều thời gian để đưa ra quyết định này, bạn có thể xem [video này](https://www.youtube.com/watch?v=PmBfq-SpzCU). -Nevertheless, if you strongly prefer to use the old `/pages` paradigm, that's still an option. Porting over your existing router can be a monumental effort, so do not feel undue pressure to do so unnecessarily. +Tuy nhiên, nếu bạn thực sự vẫn muốn sử dụng cấu trúc thư mục `/pages`, bạn vẫn có thể chọn nó. Chuyển đổi kiểu router của mà bạn đang dùng hiện tại có thể mất rất nhiều thời gian, vì vậy bạn đừng nên cảm thấy bị áp lực để làm điều đó không cần thiết. - For a list of supported, planned, and worked on features in the `/app` dir, - visit the [beta Next.js - docs](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features). + Để xem danh sách các tính năng đã được hỗ trợ, dự kiến sẽ được hỗ trợ và đang + được hỗ trợ trong thư mục `/app`, truy cập [tài liệu beta của + Next.js](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features). diff --git a/www/src/pages/vi/other-recs.md b/www/src/pages/vi/other-recs.md index ae774aac2c..f2f276d9a3 100644 --- a/www/src/pages/vi/other-recs.md +++ b/www/src/pages/vi/other-recs.md @@ -1,55 +1,55 @@ --- -title: Other Recommendations -description: Libraries and Services that we recommend for many projects +title: Các khuyến nghị khác +description: Thư viện và dịch vụ mà chúng tôi khuyến nghị cho nhiều dự án layout: ../../layouts/docs.astro -lang: en +lang: vi --- -We recognize that the libraries included in `create-t3-app` don't solve every problem. While we encourage you to begin your project with the things that we provide, there will come a time when you need to bring in other packages. Only you can know what your project needs, but here are some things that we find ourselves recommending frequently. +Chúng tôi nhận thấy rằng các thư viện đi kèm trong `create-t3-app` sẽ không giúp bạn giải quyết được mọi vấn đề. Mặc dù chúng tôi khuyến khích bạn bắt đầu dự án của mình với những thư viện chúng tôi cung cấp, sẽ đến một thời điểm nào đó mà bạn cần sử dụng những thư viện khác. Chỉ bạn mới biết dự án của mình cần gì, tuy nhiên, dưới đây là một số thứ mà chúng tôi thường xuyên đề xuất. -These are recommendations by individual Create T3 App contributors and should not be seen as "official" endorsements by the Create T3 App team or T3-OSS. _**Please do your own research, especially before committing to paid services**_. +Đây là những đề xuất của các cộng tác viên cá nhân của Create T3 App và không nên được xem là những đề xuất "chính thức" bởi nhóm Create T3 App hoặc T3-OSS. _**Hãy nghiên cứu kỹ lưỡng trước khi sử dụng, đặc biệt là trước khi cam kết sử dụng các dịch vụ trả phí**_. -## State Management +## Quản lý trạng thái (State Management) -_**Editor's Note**_: State management libraries can be great, but often aren't necessary. tRPC's React Query hooks should be able to take care of your server state. For client state, start with React's `useState`, and reach for one of these options when you need more. +_**Lưu ý của Editor**_: Các thư viện quản lý trạng thái (State Management Libraries) có thể rất tuyệt vời, nhưng chúng thường không cần thiết. Các hook React Query của tRPC có thể đảm nhiệm tốt việc quản lý trạng thái phía máy chủ (server state) của bạn. Đối với trạng thái phía máy khách (client state), hãy bắt đầu với `useState` của React và chỉ nên sử dụng một trong các tùy chọn này khi bạn cần nhiều hơn thế. ### Zustand -**For never using Redux again** +**Bạn sẽ không bao giờ phải dùng Redux nữa** -The "modern, simple Redux" you didn't know you needed. [Poimandres](https://github.com/pmndrs) can always be trusted. You can build everything from video call apps to games to servers with this little library. +Đây được coi là một "Redux hiện đại, đơn giản" mà bạn ước mình biết đến sớm hơn. [Poimandres](https://github.com/pmndrs) rất tín. Bạn có thể xây dựng mọi thứ từ ứng dụng gọi video đến trò chơi đến máy chủ với thư viện nhỏ bé này. -- [Zustand Homepage](https://zustand-demo.pmnd.rs/) -- [Zustand GitHub](https://github.com/pmndrs/zustand) +- [Trang chủ Zustand](https://zustand-demo.pmnd.rs/) +- [GitHub Zustand](https://github.com/pmndrs/zustand) ### Jotai -**For never using Context again** +**Bạn sẽ không bao giờ phải dùng Context nữa** -For a more atomic approach, Jotai is hard to beat. Also by [Poimandres](https://github.com/pmndrs), Jotai lets you define singletons that feel like global useState. A great option for stateful behaviors that don't need a state machine just yet. +Khi đề cập đến cách tiếp cận nguyên tử (atomic), Jotai gần như không thể bị đánh bại. Thư viện này cũng được tạo bởi [Poimandres](https://github.com/pmndrs), Jotai cho phép bạn định nghĩa các singleton giống như một useState, nhưng sử dụng một cách toàn cục. Đây sẽ là một lựa chọn tuyệt vời cho các hành vi có trạng thái (stateful behaviors) mà chưa cần đến trạng thái máy (state machine). -- [Jotai Homepage](https://jotai.org/) -- [Jotai GitHub](https://github.com/pmndrs/jotai) +- [Trang chủ Jotai](https://jotai.org/) +- [GitHub Jotai](https://github.com/pmndrs/jotai) -## Component Libraries +## Thư viện Component -Most apps need the same handful of components - toggle buttons, dropdown menus, modals, and so on. These libraries provide great, accessible components that you can use and customize to your liking. +Hầu hết các ứng dụng đều cần một số component giống nhau - nút bật tắt (toggle buttons), menu thả xuống (dropdown menus), modal, v.v. Các thư viện này cung cấp các component tuyệt vời, dễ tiếp cận mà bạn có thể sử dụng và tùy chỉnh theo ý thích. -### Unstyled Component Libraries +### Thư viện Component không định kiểu (Unstyled) -Also known as headless libraries, they provide great unstyled, and accessible components that you can customize to your liking. Here are a few recommendations. +Còn được gọi là thư viện headless, chúng cung cấp một danh sách component tuyệt vời, không có style sẵn và dễ tiếp cận, giúp bạn có thể tùy chỉnh theo ý thích cá nhân. Dưới đây là một vài đề xuất của chúng tôi. -- [Radix UI](https://www.radix-ui.com/) gives you a powerful set of convenient and accessible primitives that you can style with vanilla or Tailwind CSS. +- [Radix UI](https://www.radix-ui.com/) cung cấp cho bạn một bộ primitives mạnh mẽ, tiện lợi và dễ tiếp cận mà bạn có thể định nghĩa bằng CSS thuần hoặc Tailwind CSS. -- [Headless UI](https://headlessui.com/) made by the Tailwind CSS team also provides unstyled, accessible components that integrate seamlessly with Tailwind CSS. +- [Headless UI](https://headlessui.com/) được tạo bởi Tailwind, nó cung cấp các component không có style sẵn, dễ tiếp cận và dễ tích hợp với Tailwind CSS. -- [React Aria](https://react-spectrum.adobe.com/react-aria/) provides accessible UI primitives for your design system. Their Date Picker component is top tier. +- [React Aria](https://react-spectrum.adobe.com/react-aria/) cung cấp các UI primitives dễ tiếp cận cho hệ thống thiết kế (design system) của bạn. Date Picker của họ là một "wow" đáng kinh ngạc. -### Styled Component Libraries +### Thư viện Component có định kiểu (Styled) -**For when you just want your app to look OK** +**Khi ứng dụng của bạn chỉ ở mức ổn** -Sometimes you're building a project where you just want the UI to look decent out of the box. For Admin Dashboards and other similar projects, any of these component libraries will get the job done. +Đôi khi bạn đang xây dựng một dự án mà bạn chỉ muốn giao diện người dùng (UI) trông tươm tất ngay từ đầu. Đối với các Bảng điều khiển quản trị (Admin Dashboards) và các dự án tương tự khác, bất kỳ thư viện component nào trong số này cũng sẽ giúp bạn hoàn thành công việc trong thời gian ngắn nhất. - [Chakra UI](https://chakra-ui.com) - [Mantine](https://mantine.dev) @@ -57,113 +57,113 @@ Sometimes you're building a project where you just want the UI to look decent ou ### Class Variance Authority -**For building UI Libraries** +**Để xây dựng thư viện UI** -Declaratively build a UI Library with different color, size, etc. variants. When your project reaches a scale where you want a standardized set of UI components with multiple variants using Tailwind CSS, CVA is a great tool. +Để xây dựng một Thư viện UI, bạn cần cách khai báo các biến thể màu sắc, kích thước, v.v. khác nhau. Khi dự án của bạn đạt đến quy mô mà bạn muốn có một bộ component UI được chuẩn hóa với nhiều biến thể sử dụng Tailwind CSS, CVA sẽ là một "người đồng hành" không thể thiếu của bạn. -- [Class Variance Authority GitHub](https://github.com/joe-bell/cva) +- [GitHub Class Variance Authority](https://github.com/joe-bell/cva) -## Animations +## Hoạt ảnh (Animations) -For when you need animations in your app, here are our recommendations. +Khi bạn cần hoạt ảnh trong ứng dụng của mình, đây là những đề xuất của chúng tôi. ### AutoAnimate -**For animations with a single line of code** +**Tạo hoạt ảnh chỉ với một dòng code** -Most animation libraries try to satisfy every possible use case, and become clunky as a result. AutoAnimate is a zero-configuration tool that will give you a significant improvement in UX with no additional developer effort. +Hầu hết các thư viện hoạt ảnh cố gắng đáp ứng mọi trường hợp sử dụng có thể và kết quả là hầu hết chúng đều rất cồng kềnh. AutoAnimate là một công cụ không cần cấu hình (zero-configuration) mà đem lại cho bạn sự cải thiện đáng kể về UX mà không cần phải nghĩ nhiều về setup. -- [AutoAnimate Homepage](https://auto-animate.formkit.com/) -- [AutoAnimate GitHub](https://github.com/formkit/auto-animate) -- [AutoAnimate Component Snippet](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb) +- [Trang chủ AutoAnimate](https://auto-animate.formkit.com/) +- [GitHub AutoAnimate](https://github.com/formkit/auto-animate) +- [Đoạn mã Component AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb) ### Framer Motion -**For complex animations with declarative code** +**Tạo hoạt ảnh phức tạp với code khai báo đơn giản** -Framer Motion provides a simple, declarative syntax and allows you to write less code to craft everything from complex animations to even gestures. +Framer Motion cung cấp các cú pháp khai báo đơn giản và cho phép bạn viết ít code hơn để tạo ra mọi thứ từ hoạt ảnh phức tạp đến cả cử chỉ (gestures). -- [Framer Motion Homepage](https://framer.com/motion) -- [Framer Motion Documentation](https://www.framer.com/docs/) +- [Trang chủ Framer Motion](https://framer.com/motion) +- [Tài liệu Framer Motion](https://www.framer.com/docs/) -## Deployments, Infrastructure, Databases and CI +## Triển khai, Hạ tầng, Cơ sở dữ liệu và CI ### Vercel -**For hosting your app** +**Host ứng dụng của bạn một cách đơn giản nhất** -Vercel took the hell of web deployments and made it a set-and-forget GitHub integration. We've scaled to hundreds of thousands of users without issue. AWS-powered, just a way better interface :) +Vercel đã "vực dậy" việc triển khai web từ địa ngục đến việc chỉ cần thêm vào Github và "deploy". Chúng tôi đã mở rộng quy mô lên hàng trăm nghìn người dùng mà không gặp vấn đề gì. Được xây dựng trên nền của AWS, tuy nhiên giao diện của Vercel lại tốt hơn chục nghìn lần :) -- [Vercel Homepage](https://vercel.com/) -- [Create T3 App Vercel deployment guide](/en/deployment/vercel) +- [Trang chủ Vercel](https://vercel.com/) +- [Hướng dẫn triển khai Create T3 App trên Vercel](/vi/deployment/vercel) ### PlanetScale -**For databases without the worry** +**Chiếc cơ sở dữ liệu mà bạn không cần lo lắng** -PlanetScale is the best "serverless database platform" we've used by far. Insane scale, great developer experience, and fantastic pricing. If you're using SQL (and hopefully Prisma), this is hard to beat. +PlanetScale là "nền tảng cơ sở dữ liệu serverless" tốt nhất mà chúng tôi từng sử dụng. Nó có khả năng mở rộng đáng kinh ngạc, trải nghiệm lập trình tuyệt vời và giá cả phải chăng. Nếu bạn đang sử dụng SQL (và hy vọng là Prisma), thì bạn khó có thể không sử dụng nền tảng này. -- [PlanetScale Homepage](https://planetscale.com/) +- [Trang chủ PlanetScale](https://planetscale.com/) ### Railway -**For hosting your infra** +**Host hạ tầng của bạn** -"Modern Heroku". The easiest way to get a real server up and running. If Vercel and PlanetScale aren't enough, Railway probably is. Point it at a GitHub repo and go. +Được coi là một "Heroku hiện đại". Đây là cách dễ nhất để bạn khởi chạy và quản lý hạ tầng đám mây của bạn. Nếu Vercel và PlanetScale không đủ đối với bạn, Railway sẽ lấp đầy khoảng trống đó. Chỉ cần đưa nó vào một repo GitHub và bắt đầu hành trình của bạn. -- [Railway Homepage](https://railway.app/) +- [Trang chủ Railway](https://railway.app/) ### Upstash -**For serverless Redis** +**Một Redis serverless** -We love Prisma and PlanetScale, but some projects require a more performant solution. Upstash allows you to get the in-memory performance of Redis in your serverless project, without having to manage the infrastructure and scaling yourself. +Chúng tôi yêu thích Prisma và PlanetScale, nhưng một số dự án cần đòi hỏi giải pháp hiệu năng cao hơn. Upstash đẹm lại các tính năng của Redis trong dự án serverless của bạn mà không cần phải tự quản lý cơ sở hạ tầng và việc mở rộng quy mô. -- [Upstash Homepage](https://upstash.com/) +- [Trang chủ Upstash](https://upstash.com/) ### Pusher -**For serverless WebSockets** +**WebSockets serverless** -If WebSockets are the primary focus of your project, you may want to consider a more traditional backend such as [Fastify](https://www.fastify.io/) (which [also works with tRPC!](https://trpc.io/docs/v10/fastify)). But for quickly adding WebSockets to a T3 App, Pusher is an excellent choice. +Nếu WebSockets là trọng tâm chính của dự án của bạn, bạn có thể muốn xem xét sử dụng một backend server truyền thống như [Fastify](https://www.fastify.io/) (cũng [hoạt động với tRPC!](https://trpc.io/docs/v10/fastify)). Nhưng nếu bạn không đủ thời gian để thêm WebSockets vào một ứng dụng T3, đừng lo, Pusher sẽ là "món chính" tuyệt vời. -- [Pusher Homepage](https://pusher.com/) +- [Trang chủ Pusher](https://pusher.com/) ### Soketi -Soketi is a self-hostable, simple, and fast alternative to Pusher. It's fully compatible with the Pusher SDK which you can use to connect to the server. Soketi serverless is also in beta. +Soketi là một giải pháp tự host (self-hostable), đơn giản và nhanh chóng cho Pusher. Nó hoàn toàn tương thích với Pusher SDK mà bạn có thể sử dụng để kết nối với máy chủ. Hãy nhớ rằng, Soketi serverless hiện tại đang trong giai đoạn beta. -- [Soketi Homepage](https://soketi.app) -- [Soketi GitHub](https://github.com/soketi/soketi) +- [Trang chủ Soketi](https://soketi.app) +- [GitHub Soketi](https://github.com/soketi/soketi) -## Analytics +## Phân tích (Analytics) -User data is very valuable when you're building an app. Here are some analytics providers we recommend. +Dữ liệu người dùng rất có giá trị khi bạn xây dựng một ứng dụng. Dưới đây là một số nhà cung cấp dịch vụ phân tích mà chúng tôi đề xuất. ### PostHog -PostHog is a full-featured, open-source, and self-hostable solution for bringing in depth analytics to your product. They have SDKs for every library/framework imaginable. +PostHog là một giải pháp mã nguồn mở, đầy đủ tính năng và có thể tự host để mang lại phân tích chuyên sâu cho sản phẩm của bạn. Họ có SDK cho mọi thư viện/framework có thể tưởng tượng được. -- [PostHog Homepage](https://posthog.com/) +- [Trang chủ PostHog](https://posthog.com/) ### Plausible -Need analytics? Plausible is one of the quickest ways to get them. Super minimal. It even has a [simple plugin for Next.js](https://plausible.io/docs/proxy/guides/nextjs). +Bạn đang cần một nền tảng phân tích ưu việt? Plausible là một trong những cách nhanh nhất để có được chúng. Siêu tối giản. Nó thậm chí còn có hẳn cả [plugin đơn giản cho Next.js](https://plausible.io/docs/proxy/guides/nextjs). -- [Plausible Homepage](https://plausible.io/) +- [Trang chủ Plausible](https://plausible.io/) ### Umami -Umami is an open-sourced, self-hostable, simple, fast, privacy-focused alternative to Google Analytics. You can deploy it really easily to Vercel, Railway, etc. with PlanetScale as your database or you can also use its cloud version. +Umami là một giải pháp thay thế mã nguồn mở, có thể tự host, đơn giản, nhanh chóng và tập trung vào quyền riêng tư cho Google Analytics. Bạn có thể triển khai nó rất dễ dàng lên Vercel, Railway, v.v. với PlanetScale làm cơ sở dữ liệu hoặc bạn cũng có thể sử dụng phiên bản đám mây của nó. -- [Umami Homepage](https://umami.is/) -- [Umami GitHub](https://github.com/umami-software/umami) +- [Trang chủ Umami](https://umami.is/) +- [GitHub Umami](https://github.com/umami-software/umami) - [Umami Cloud](https://cloud.umami.is/) -## Other +## Khác ### Next Bundle Analyzer -It can sometimes be difficult to determine what will be included in the build output for your app. Next Bundle Analyzer is an easy way to visualize and analyze the JavaScript bundles that are generated. +Đôi khi có thể khó xác định những gì sẽ được bao gồm trong khi build (build output) ứng dụng của bạn. Next Bundle Analyzer là một cách dễ dàng để trực quan hóa và phân tích các gói JavaScript (JavaScript bundles) được tạo ra trong quá trình build sản phẩm của bạn. -- [@next/bundle-analyzer on npm](https://www.npmjs.com/package/@next/bundle-analyzer) +- [@next/bundle-analyzer trên npm](https://www.npmjs.com/package/@next/bundle-analyzer) diff --git a/www/src/pages/vi/t3-collection.mdx b/www/src/pages/vi/t3-collection.mdx index 8c8cfcb9b1..095b287069 100644 --- a/www/src/pages/vi/t3-collection.mdx +++ b/www/src/pages/vi/t3-collection.mdx @@ -1,29 +1,29 @@ --- title: T3 Collection -description: Cool open source projects and companies using the T3 stack +description: Dự án và công ty sử dụng T3 Stack layout: ../../layouts/docs.astro -lang: en +lang: vi isMdx: true --- -import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx"; -import CompanyList from "../../components/docs/companyList.tsx"; import Callout from "../../components/docs/callout.tsx"; +import CompanyList from "../../components/docs/companyList.tsx"; +import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx"; -Made a project using the T3 stack and want to share it? Add it to the list! +Bạn đã có sẵn một dự án sử dụng T3 Stack và muốn chia sẻ nó? Hãy chia sẻ nó bằng cách thêm nó vào danh sách! -## Open Source apps made using the T3 Stack +## Dự án mã nguồn mở được tạo bằng T3 Stack -## Companies using the T3 Stack +## Công ty sử dụng T3 Stack -We'd love to know of companies that use the T3 stack for their apps. Is your company using the T3 stack and would like to share it? Add it to the list! +Chúng tôi rất muốn biết các công ty sử dụng T3 Stack cho ứng dụng của họ. Nếu công ty của bạn đang sử dụng T3 Stack và bạn muốn chia sẻ nó? Đừng ngần ngại đưa nó vào danh sách! - Have a cool project using the T3 stack? Make a [pull + Bạn có một dự án thú vị sử dụng T3 Stack? Hãy tạo một [pull request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx) - and add it here! + và thêm nó vào danh sách! From db9fe530278b94bfdf08bc6ffff58ff02330dc2a Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Wed, 23 Apr 2025 11:28:26 +1000 Subject: [PATCH 06/12] docs(vi): Update Vietnamese for Vercel and Netlify deployment --- www/src/pages/vi/deployment/netlify.mdx | 50 ++++++++++++------------- www/src/pages/vi/deployment/vercel.md | 30 +++++++-------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/www/src/pages/vi/deployment/netlify.mdx b/www/src/pages/vi/deployment/netlify.mdx index f794bdea5a..b7bd3b9448 100644 --- a/www/src/pages/vi/deployment/netlify.mdx +++ b/www/src/pages/vi/deployment/netlify.mdx @@ -1,32 +1,32 @@ --- title: Netlify -description: Deploying to Netlify +description: Triển khai lên Netlify layout: ../../../layouts/docs.astro -lang: en +lang: vi isMdx: true --- import Callout from "../../../components/docs/callout.tsx"; -Netlify is an alternative deployment provider in a similar vein to Vercel. See [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) for an example repo based on this doc. +Netlify là một nhà cung cấp khác giúp bạn triển khai ứng dụng web của bạn tương tự như Vercel. Bạn có thể tham khảo [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) như là một repo ví dụ triển khai lên Netlify dựa trên tài liệu này. -## Why Host on Netlify +## Tại sao nên triển khai lên Netlify -Conventional wisdom says Vercel has superior Next.js support because Vercel develops Next.js. They have a vested interest in ensuring the platform is tuned for optimal performance and DX with Next.js. For the majority of use cases, this will be true and it won't make sense to deviate from the standard path. +Một sự thật mà chúng ta không thể phủ nhận được đó chính là việc Vercel chính là cha đẻ của Next.js, thế nên Vercel hỗ trợ Next.js tốt hơn là điều tất nhiên. Thế nên, họ luôn đi đầu trong việc đảm bảo nền tảng được tối ưu hóa cho hiệu suất và nâng cao DX cho Next.js. Đối với hầu hết các trường hợp sử dụng, điều này sẽ đúng và sẽ không có lý do gì để chúng ta tách biệt ra khỏi cái khuôn khổ này. -There's also a common sentiment that many Next.js features are only supported on Vercel. While it's true that new Next.js features will be tested and supported on Vercel at the time of release by default, it's also the case that other providers like Netlify will [quickly implement and release support](https://www.netlify.com/blog/deploy-nextjs-13/) for [stable Next.js features](https://docs.netlify.com/integrations/frameworks/next-js/overview/). +Và chúng ta cũng đều có chung một suy nghĩ rằng nhiều tính năng của Next.js chỉ được hỗ trợ trên Vercel. Mặc dù Vercel luôn đi đầu trong việc cho phép thử nghiệm các tính năng mới của Next.js và cho phép sử dụng chúng ngay khi được ra mắt, nhưng đồng thời cũng là trường hợp tương tự cho các nhà cung cấp khác như Netlify, khi mà họ cũng sẽ [nhanh chóng triển khai và phát hành hỗ trợ](https://www.netlify.com/blog/deploy-nextjs-13/) cho [các tính năng Next.js khi chúng được ra mắt](https://docs.netlify.com/integrations/frameworks/next-js/overview/). -There are relative pros and cons for all deployment providers since no single host can have the best support for all use cases. For example, Netlify built their own [custom Next.js runtime](https://github.com/netlify/next-runtime) for Netlify's Edge Functions (which run on Deno Deploy) and [maintain unique middleware to access and modify HTTP responses](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify). +Tất nhiên, tất cả các nhà cung cấp triển khai sẽ đều có nhiều ưu và nhược điểm của riêng mình, vì không có một nhà cung cấp nào có thể có hỗ trợ tốt nhất cho tất cả các trường hợp sử dụng. Ví dụ, Netlify đã xây dựng hẳn một [runtime Next.js riêng cho Netlify's Edge Functions](https://github.com/netlify/next-runtime) (chạy trên Deno Deploy) và [duy trì middleware riêng để truy cập và sửa đổi HTTP responses](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify). - To track the status of non-stable Next 13 features see [Using the Next 13 - `app` directory on + Để theo dõi những tính năng mới nhất của những phiên bản Next 13 non-stable, + xin mời tham khảo [Sử dụng Next 13 `app` directory trên Netlify](https://github.com/netlify/next-runtime/discussions/1724). -## Project Configuration +## Cấu hình dự án -There are numerous ways to configure your build instructions including directly through the Netlify CLI or Netlify dashboard. While not required, it is advisable to create and include a [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/) file. This ensures that forked and cloned versions of the project will be easier to reproducibly deploy. +Có muôn vàn cách để cấu hình lệnh build cho dự án của bạn, bao gồm việc cấu hình trực tiếp qua Netlify CLI hoặc Netlify dashboard. Trong khi việc tạo và bao gồm một tệp [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/) là việc không bắt buộc, chúng tôi **khuyến khích** bạn nên làm điều này nhằm đảm bảo rằng các phiên bản được fork và clone của dự án sẽ dễ dàng triển khai lại. ```toml [build] @@ -34,60 +34,60 @@ There are numerous ways to configure your build instructions including directly publish = ".next" ``` -## Using the Netlify Dashboard +## Sử dụng Netlify Dashboard -1. Push your code to a GitHub repository and sign up for [Netlify](https://app.netlify.com/signup). After you've created an account, click on **Add new site** and then **Import an existing project**. +1. Hãy đẩy code của bạn lên một repository GitHub và đăng ký tài khoản [Netlify](https://app.netlify.com/signup). Sau khi đã tạo tài khoản, hãy click vào **Add new site** và sau đó **Import an existing project**. ![New project on Netlify](/images/netlify-01-new-project.webp) -2. Connect your Git provider. +2. Kết nối với Git provider của bạn. ![Import repository](/images/netlify-02-connect-to-git-provider.webp) -3. Select your project's repository. +3. Chọn repository của dự án của bạn. ![Select your project's repository](/images/netlify-03-pick-a-repository-from-github.webp) -4. Netlify will detect if you have a `netlify.toml` file and automatically configure your build command and publish directory. +4. Netlify sẽ tự động phát hiện xem bạn có tệp `netlify.toml` hay không và tự động cấu hình lệnh build và thư mục publish. ![Nextjs build settings](/images/netlify-04-configure-build-settings.webp) -5. Click **Show advanced** and then **New variable** to add your environment variables. +5. Click **Show advanced** và sau đó **New variable** để thêm biến môi trường của bạn. ![Add environment variables](/images/netlify-05-env-vars.webp) -6. Click **Deploy site**, wait for the build to complete, and view your new site. +6. Chọn **Deploy site**, đợi cho quá trình build hoàn tất và xem trang web mới của bạn. -## Using the Netlify CLI +## Sử dụng Netlify CLI -To deploy from the command line you must first push your project to a GitHub repo and [install the Netlify CLI](https://docs.netlify.com/cli/get-started/). You can install `netlify-cli` as a project dependency or install it globally on your machine with the following command: +Để triển khai sử dụng Netlify CLI, bạn phải đầu tiên đẩy code của bạn lên một repository GitHub và [cài đặt Netlify CLI](https://docs.netlify.com/cli/get-started/). Bạn có thể cài đặt `netlify-cli` dưới dạng **Dev Dependency** cho dự án hoặc cài đặt nó toàn cục trên máy của bạn với lệnh sau: ```bash npm i -g netlify-cli ``` -To test your project locally, run the [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) command and open [`localhost:8888`](http://localhost:8888/) to view your locally running Netlify app: +Để chạy dự án của bạn trên máy của bạn, chạy lệnh [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) và mở [`localhost:8888`](http://localhost:8888/) để xem dự án Netlify của bạn đang chạy: ```bash ntl dev ``` -Run the [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) command to configure your project: +Chạy lệnh [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) để bắt đầu cấu hình dự án của bạn: ```bash ntl init ``` -Import your project's environment variables from your `.env` file with [`ntl env:import`](https://cli.netlify.com/commands/env#envimport): +Nhập biến môi trường của dự án của bạn từ tệp `.env` với lệnh [`ntl env:import`](https://cli.netlify.com/commands/env#envimport): ```bash ntl env:import .env ``` -Deploy your project with [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). You'll need to pass the `--build` flag to run the build command before deployment and the `--prod` flag to deploy to your site's main URL: +Triển khai dự án của bạn với lệnh [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). Bạn sẽ cần truyền `--build` để chạy lệnh build trước khi triển khai và `--prod` để triển khai lên URL chính của trang web của bạn: ```bash ntl deploy --prod --build ``` -To view a running example on Netlify, visit [ct3a.netlify.app](https://ct3a.netlify.app/). +Để xem một ví dụ chạy trên Netlify, hãy truy cập [ct3a.netlify.app](https://ct3a.netlify.app/). diff --git a/www/src/pages/vi/deployment/vercel.md b/www/src/pages/vi/deployment/vercel.md index a9ee5344fd..c618582637 100644 --- a/www/src/pages/vi/deployment/vercel.md +++ b/www/src/pages/vi/deployment/vercel.md @@ -1,15 +1,15 @@ --- title: Vercel -description: Deploying to Vercel +description: Triển khai lên Vercel layout: ../../../layouts/docs.astro -lang: en +lang: vi --- -We recommend deploying your app to [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). It makes it super easy to deploy Next.js apps. +Chúng tôi khuyến khích bạn nên triển khai ứng dụng của bạn lên [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). Nó làm cho việc triển khai ứng dụng Next.js trở nên vô cùng dễ dàng. -## Project Configuration +## Cấu hình dự án -Vercel will likely configure your build command and publish the directory automatically. However, you can also specify this information along with other configurations by creating a file called [`vercel.json`](https://vercel.com/docs/project-configuration) and including the following commands. **This is not required for most projects.** +Vercel sẽ cấu hình lệnh build và đọc các thư mục một cách tự động. Tuy nhiên, bạn cũng có thể tự cấu hình thông tin này cùng với các cấu hình Vercel khác bằng cách tạo một file tên là [`vercel.json`](https://vercel.com/docs/project-configuration) và ghi đè các lệnh sau. Tuy nhiên, **Điều này hầu như không bắt buộc cho hầu hết các dự án.** ```json { @@ -19,43 +19,43 @@ Vercel will likely configure your build command and publish the directory automa } ``` -## Using the Vercel Dashboard +## Sử dụng trong Vercel Dashboard -1. After pushing your code to a GitHub repository, sign up for [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) with GitHub and click on **Add New Project**. +1. Sau khi đẩy code của bạn lên repository của bạn ở Github, bạn hãy đăng ký tài khoản [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) với Github và click vào **Add New Project**. ![New project on Vercel](/images/vercel-new-project.webp) -2. Import the GitHub repository with your project. +2. Thêm repository chứa source code của bạn. ![Import repository](/images/vercel-import-project.webp) -3. Add your environment variables. +3. Thêm các biến môi trường. ![Add environment variables](/images/vercel-env-vars.webp) -4. Click **Deploy**. Now whenever you push a change to your repository, Vercel will automatically redeploy your app! +4. Chọn **Deploy**. Và kể từ bây giờ, mỗi khi nào bạn đẩy một thay đổi lên repository của bạn, Vercel sẽ tự động triển khai lại ứng dụng của bạn! -## Using the Vercel CLI +## Sử dụng CLI của Vercel -To deploy from the command line you must first [install the Vercel CLI globally](https://vercel.com/docs/cli#installing-vercel-cli). +Để triển khai sử dụng CLI của Vercel, bạn phải trước tiên [cài đặt CLI của Vercel](https://vercel.com/docs/cli#installing-vercel-cli). ```bash npm i -g vercel ``` -Run the [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) command to deploy your project. +Chạy lệnh [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) để triển khai dự án của bạn. ```bash vercel ``` -Include `--env DATABASE_URL=YOUR_DATABASE_URL_HERE` for environment variables like the database connection string. Use `--yes` if you want to skip the deployment questions and give the default answer for each. +Để thêm các biến môi trường như chuỗi kết nối cơ sở dữ liệu, bạn có thể sử dụng lệnh `--env DATABASE_URL=YOUR_DATABASE_URL_HERE`. Sử dụng `--yes` nếu bạn muốn bỏ qua các câu hỏi triển khai và mặc định đồng ý cho mỗi câu hỏi. ```bash vercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes ``` -After the first deployment, this command will deploy to a preview branch. You will need to include `--prod` to push changes directly to the live site for future deployments. +Sau khi triển khai lần đầu tiên, lệnh này sẽ triển khai lên một nhánh preview. Nếu bạn muốn đẩy các thay đổi trực tiếp lên trang web live cho các triển khai tương lai, bạn sẽ cần phải bao gồm `--prod`. ```bash vercel --prod From 83dde1c69e4e0322d1442ddda54ded3f52183d40 Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Thu, 24 Apr 2025 07:20:18 +1000 Subject: [PATCH 07/12] docs(vi): Update Vietnamese for Docker deployment --- www/src/pages/vi/deployment/docker.md | 78 +++++++++++++-------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/www/src/pages/vi/deployment/docker.md b/www/src/pages/vi/deployment/docker.md index 5ca553cc08..19b4a7c62a 100644 --- a/www/src/pages/vi/deployment/docker.md +++ b/www/src/pages/vi/deployment/docker.md @@ -1,22 +1,22 @@ --- title: Docker -description: Deployment with Docker +description: Triển khai với Docker layout: ../../../layouts/docs.astro -lang: en +lang: vi --- -You can containerize this stack and deploy it as a single container using Docker, or as a part of a group of containers using docker-compose. See [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) for an example repo based on this doc. +Bạn có thể containerize stack này và triển khai nó như một container duy nhất bằng Docker, hoặc như một phần của một nhóm container bằng docker-compose. Bạn có thể tham khảo [`ajcwebdev/ct3a-docker`](https://github.com/ajcwebdev/ct3a-docker) như là một repo ví dụ dựa trên tài liệu này. -## Docker Project Configuration +## Cấu hình dự án Docker -Please note that Next.js requires a different process for build time (available in the frontend, prefixed by `NEXT_PUBLIC`) and runtime environment, server-side only, variables. In this demo we are using two variables, pay attention to their positions in the `Dockerfile`, command-line arguments, and `docker-compose.yml`: +Đối với Next.js, sẽ có những quy trình khác nhau cho môi trường build time (có sẵn trong frontend, được đặt trước bằng `NEXT_PUBLIC`) và môi trường runtime (server-side only, biến). Trong ví dụ dưới đây, chúng tôi sử dụng hai biến môi trường, và bạn hãy chú ý tớ vị trí của chúng trong `Dockerfile`, đối số dòng lệnh, và file `docker-compose.yml`: -- `DATABASE_URL` (used by the server) -- `NEXT_PUBLIC_CLIENTVAR` (used by the client) +- `DATABASE_URL` (Dùng bên phía server) +- `NEXT_PUBLIC_CLIENTVAR` (Dùng bên phía client) ### 1. Next Configuration -In your [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js), add the `standalone` output-option configuration to [reduce image size by automatically leveraging output traces](https://nextjs.org/docs/advanced-features/output-file-tracing): +Trong file [`next.config.js`](https://github.com/t3-oss/create-t3-app/blob/main/cli/template/base/next.config.js), bạn hãy thêm cấu hình `standalone` để [tối ưu hóa kích thước hình ảnh bằng cách tự động sử dụng trace output](https://nextjs.org/docs/advanced-features/output-file-tracing): ```diff export default defineNextConfig({ @@ -26,11 +26,11 @@ export default defineNextConfig({ }); ``` -### 2. Create dockerignore file +### 2. Tạo file .dockerignore
- Click here and include contents in .dockerignore: + Click vào đây để xem nội dung của .dockerignore:
@@ -49,13 +49,13 @@ README.md
-### 3. Create Dockerfile +### 3. Tạo Dockerfile -> Since we're not pulling the server environment variables into our container, the [environment schema validation](/en/usage/env-variables) will fail. To prevent this, we have to add a `SKIP_ENV_VALIDATION=1` flag to the build command so that the env-schemas aren't validated at build time. +> Vì chúng tôi không muốn tạo biến môi trường (environment variables) server vào container, vì thế [các bước xác thực biến môi trường](/vi/usage/env-variables) sẽ không thành công. Để ngăn điều này, chúng tôi đã thêm flag `SKIP_ENV_VALIDATION=1` vào lệnh build để không xác thực biến môi trường tại thời điểm build.
- Click here and include contents in Dockerfile: + Click vào đây để xem nội dung của Dockerfile:
@@ -121,34 +121,34 @@ ENV PORT 3000 CMD ["server.js"] ``` -> **_Notes_** +> **_Ghi chú_** > -> - _Emulation of `--platform=linux/amd64` may not be necessary after moving to Node 18._ -> - _See [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) to understand why `libc6-compat` might be needed._ -> - _Using Alpine 3.17 based images [can cause issues with Prisma](https://github.com/t3-oss/create-t3-app/issues/975). Setting `engineType = "binary"` solves the issue in Alpine 3.17, [but has an associated performance cost](https://www.prisma.io/docs/concepts/components/prisma-engines/query-engine#the-query-engine-at-runtime)._ -> - _Next.js collects [anonymous telemetry data about general usage](https://nextjs.org/telemetry). Uncomment the first instance of `ENV NEXT_TELEMETRY_DISABLED 1` to disable telemetry during the build. Uncomment the second instance to disable telemetry during runtime._ +> - _Việc giả lập môi trường bằng `--platform=linux/amd64` có thể là không cần thiết sau khi chuyển sang Node 18._ +> - _Tham khảo [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) để hiểu tại sao `libc6-compat` có thể cần thiết._ +> - _Sử dụng Alpine 3.17 [có thể tạo ra một số vấn đề với Prisma](https://github.com/t3-oss/create-t3-app/issues/975). Vì thế, hãy đặt `engineType = "binary"` giải quyết vấn đề trong Alpine 3.17, tuy nhiên [hiệu suất sẽ bị ảnh hưởng](https://www.prisma.io/docs/concepts/components/prisma-engines/query-engine#the-query-engine-at-runtime)._ +> - _Next.js thu thập [dữ liệu sử dụng tổng quan](https://nextjs.org/telemetry). Bỏ comment dòng đầu tiên của `ENV NEXT_TELEMETRY_DISABLED 1` để tắt thu thập dữ liệu (telemetry) trong quá trình build. Bỏ comment dòng thứ hai để tắt thu thập dữ liệu (telemetry) trong quá trình runtime._
-## Build and Run Image Locally +## Xây dựng và chạy image cục bộ -Build and run this image locally with the following commands: +Xây dựng và chạy image này cục bộ với các lệnh sau: ```bash docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar . docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker ``` -Open [localhost:3000](http://localhost:3000/) to see your running application. +Mở [localhost:3000](http://localhost:3000/) để xem ứng dụng của bạn đang chạy. ## Docker Compose -You can also use Docker Compose to build the image and run the container. +Bạn có thể sử dụng Docker Compose để xây dựng image và chạy container.
- Follow steps 1-3 above, click here, and include contents in docker-compose.yml: + Theo các bước 1-3 ở trên, click vào đây, và bao gồm nội dung trong docker-compose.yml:
@@ -170,20 +170,20 @@ services: - DATABASE_URL=database_url_goes_here ``` -Build and run this using the `docker compose up --build` command: +Xây dựng và chạy bằng lệnh `docker compose up --build`: ```bash docker compose up --build ``` -Open [localhost:3000](http://localhost:3000/) to see your running application. +Mở [localhost:3000](http://localhost:3000/) để xem ứng dụng của bạn đang chạy.
-## Deploy to Railway +## Triển khai lên Railway -You can use a PaaS such as [Railway's](https://railway.app) automated [Dockerfile deployments](https://docs.railway.app/deploy/dockerfiles) to deploy your app. If you have the [Railway CLI installed](https://docs.railway.app/develop/cli#install) you can deploy your app with the following commands: +Bạn có thể sử dụng một PaaS như [Railway's](https://railway.app) để tự động triển khai [Dockerfile](https://docs.railway.app/deploy/dockerfiles) của bạn. Nếu bạn đã cài đặt [Railway CLI](https://docs.railway.app/develop/cli#install) bạn có thể triển khai ứng dụng của bạn với các lệnh sau: ```bash railway login @@ -193,17 +193,17 @@ railway up railway open ``` -Go to "Variables" and include your `DATABASE_URL`. Then go to "Settings" and select "Generate Domain." To view a running example on Railway, visit [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/). +Đi đến "Variables" và thêm `DATABASE_URL` của bạn. Sau đó đi đến "Settings" và chọn "Generate Domain". Để tham khảo một ví dụ được triển khai trên Railway, truy cập [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/). -## Useful Resources +## Tài liệu hữu ích -| Resource | Link | -| ------------------------------------ | -------------------------------------------------------------------- | -| Dockerfile reference | https://docs.docker.com/engine/reference/builder/ | -| Compose file version 3 reference | https://docs.docker.com/compose/compose-file/compose-file-v3/ | -| Docker CLI reference | https://docs.docker.com/engine/reference/commandline/docker/ | -| Docker Compose CLI reference | https://docs.docker.com/compose/reference/ | -| Next.js Deployment with Docker Image | https://nextjs.org/docs/deployment#docker-image | -| Next.js in Docker | https://benmarte.com/blog/nextjs-in-docker/ | -| Next.js with Docker Example | https://github.com/vercel/next.js/tree/canary/examples/with-docker | -| Create Docker Image of a Next.js app | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ | +| Tài liệu | Đường dẫn | +| ------------------------------------- | -------------------------------------------------------------------- | +| Tài liệu Dockerfile | https://docs.docker.com/engine/reference/builder/ | +| Tài liệu Compose file version 3 | https://docs.docker.com/compose/compose-file/compose-file-v3/ | +| Tài liệu Docker CLI | https://docs.docker.com/engine/reference/commandline/docker/ | +| Tài liệu Docker Compose CLI | https://docs.docker.com/compose/reference/ | +| Triển khai Next.js với Docker Image | https://nextjs.org/docs/deployment#docker-image | +| Next.js trong Docker | https://benmarte.com/blog/nextjs-in-docker/ | +| Ví dụ Next.js với Docker | https://github.com/vercel/next.js/tree/canary/examples/with-docker | +| Tạo Docker Image của ứng dụng Next.js | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ | From 59f4370ab152c439b1fcc009db4de6abcd5d61f1 Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Thu, 24 Apr 2025 16:08:38 +1000 Subject: [PATCH 08/12] docs(vi): Update lang to vi for Vietnamese-related pages --- www/src/pages/vi/usage/drizzle.mdx | 2 +- www/src/pages/vi/usage/env-variables.mdx | 2 +- www/src/pages/vi/usage/first-steps.md | 2 +- www/src/pages/vi/usage/next-auth.mdx | 2 +- www/src/pages/vi/usage/next-js.md | 2 +- www/src/pages/vi/usage/prisma.md | 2 +- www/src/pages/vi/usage/tailwind.md | 2 +- www/src/pages/vi/usage/trpc.md | 2 +- www/src/pages/vi/usage/typescript.md | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/www/src/pages/vi/usage/drizzle.mdx b/www/src/pages/vi/usage/drizzle.mdx index 6f735de94d..69e5c085d8 100644 --- a/www/src/pages/vi/usage/drizzle.mdx +++ b/www/src/pages/vi/usage/drizzle.mdx @@ -2,7 +2,7 @@ title: Drizzle description: Usage of Drizzle layout: ../../../layouts/docs.astro -lang: en +lang: vi isMdx: true --- diff --git a/www/src/pages/vi/usage/env-variables.mdx b/www/src/pages/vi/usage/env-variables.mdx index a0807eec96..bb3cb47e51 100644 --- a/www/src/pages/vi/usage/env-variables.mdx +++ b/www/src/pages/vi/usage/env-variables.mdx @@ -2,7 +2,7 @@ title: Environment Variables description: Getting started with Create T3 App layout: ../../../layouts/docs.astro -lang: en +lang: vi isMdx: true --- diff --git a/www/src/pages/vi/usage/first-steps.md b/www/src/pages/vi/usage/first-steps.md index a90b52c600..bb17b12995 100644 --- a/www/src/pages/vi/usage/first-steps.md +++ b/www/src/pages/vi/usage/first-steps.md @@ -2,7 +2,7 @@ title: First Steps description: Getting started with your new T3 App layout: ../../../layouts/docs.astro -lang: en +lang: vi --- You just scaffolded a new T3 App and are ready to go. Here is the bare minimum to get your app working. diff --git a/www/src/pages/vi/usage/next-auth.mdx b/www/src/pages/vi/usage/next-auth.mdx index 50f6b9fc82..ed45f346e1 100644 --- a/www/src/pages/vi/usage/next-auth.mdx +++ b/www/src/pages/vi/usage/next-auth.mdx @@ -2,7 +2,7 @@ title: NextAuth.js description: Usage of NextAuth.js layout: ../../../layouts/docs.astro -lang: en +lang: vi isMdx: true --- diff --git a/www/src/pages/vi/usage/next-js.md b/www/src/pages/vi/usage/next-js.md index 77bf718134..6b89d84de1 100644 --- a/www/src/pages/vi/usage/next-js.md +++ b/www/src/pages/vi/usage/next-js.md @@ -2,7 +2,7 @@ title: Next.js description: Usage of Next.js layout: ../../../layouts/docs.astro -lang: en +lang: vi --- Next.js is a backend framework for your React applications. diff --git a/www/src/pages/vi/usage/prisma.md b/www/src/pages/vi/usage/prisma.md index fc82701ca0..cf390353bb 100644 --- a/www/src/pages/vi/usage/prisma.md +++ b/www/src/pages/vi/usage/prisma.md @@ -2,7 +2,7 @@ title: Prisma description: Usage of Prisma layout: ../../../layouts/docs.astro -lang: en +lang: vi --- Prisma is an ORM for TypeScript, that allows you to define your database schema and models in a `schema.prisma` file, and then generate a type-safe client that can be used to interact with your database from your backend. diff --git a/www/src/pages/vi/usage/tailwind.md b/www/src/pages/vi/usage/tailwind.md index bdb355a4b0..df007379d4 100644 --- a/www/src/pages/vi/usage/tailwind.md +++ b/www/src/pages/vi/usage/tailwind.md @@ -2,7 +2,7 @@ title: Tailwind CSS description: Usage of Tailwind CSS layout: ../../../layouts/docs.astro -lang: en +lang: vi --- ## What is Tailwind CSS? diff --git a/www/src/pages/vi/usage/trpc.md b/www/src/pages/vi/usage/trpc.md index 9cd65bdfb0..0572372f9c 100644 --- a/www/src/pages/vi/usage/trpc.md +++ b/www/src/pages/vi/usage/trpc.md @@ -2,7 +2,7 @@ title: tRPC description: Usage of tRPC layout: ../../../layouts/docs.astro -lang: en +lang: vi --- tRPC allows us to write end-to-end typesafe APIs without any code generation or runtime bloat. It uses TypeScript's great inference to infer your API router's type definitions and lets you call your API procedures from your frontend with full typesafety and auto-completion. When using tRPC, your frontend and backend feel closer together than ever before, allowing for an outstanding developer experience. diff --git a/www/src/pages/vi/usage/typescript.md b/www/src/pages/vi/usage/typescript.md index 833fd5b2bc..44aa41875b 100644 --- a/www/src/pages/vi/usage/typescript.md +++ b/www/src/pages/vi/usage/typescript.md @@ -2,7 +2,7 @@ title: TypeScript description: Usage of TypeScript layout: ../../../layouts/docs.astro -lang: en +lang: vi ---
From e650dcf929f2509d8e9891d6644094a718353f53 Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Thu, 24 Apr 2025 16:24:21 +1000 Subject: [PATCH 09/12] docs(vi): Update Vietnamese for First Steps and Next.js pages --- www/src/pages/vi/usage/first-steps.md | 50 +++++++++++++-------------- www/src/pages/vi/usage/next-js.md | 36 +++++++++---------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/www/src/pages/vi/usage/first-steps.md b/www/src/pages/vi/usage/first-steps.md index bb17b12995..67f47ada3d 100644 --- a/www/src/pages/vi/usage/first-steps.md +++ b/www/src/pages/vi/usage/first-steps.md @@ -1,53 +1,53 @@ --- -title: First Steps -description: Getting started with your new T3 App +title: Bước đầu tiên +description: Bắt đầu với T3 App của bạn layout: ../../../layouts/docs.astro lang: vi --- -You just scaffolded a new T3 App and are ready to go. Here is the bare minimum to get your app working. +Vậy là bạn đã khởi tạo thành công chiếc T3 App cho mình rồi đấy. Bây giờ là lúc để bạn có thể bắt đầu làm việc với nó. -## Database +## Cơ sở dữ liệu ### MySQL, PostgreSQL -If you chose MySQL or PostgreSQL as your database, your T3 app will come with a `start-database.sh` bash script that can create a docker container with a database for local development. If you already have a database, feel free to delete this file and put your database credentials in `.env`. On macOS, you can also use [DBngin](https://dbngin.com/) if you don't want to use docker. +Nếu bạn chọn MySQL hoặc PostgreSQL làm cơ sở dữ liệu của mình, T3 App sẽ có một file `start-database.sh` viết bằng bash script mà có thể tạo một container dựa trên cơ sở dữ liệu đã chọn nhằm cho phép bạn phát triển cục bộ. Nếu bạn đã có một cơ sở dữ liệu, hãy cứ thoát khỏi file này và đặt chuỗi kết nối cơ sở dữ liệu của bạn vào `.env`. Trên macOS, bạn cũng có thể sử dụng [DBngin](https://dbngin.com/) nếu bạn không muốn sử dụng docker. ### Prisma -If your app includes Prisma, make sure to run `npx prisma db push` from the root directory of your app. This command will sync your Prisma schema with your database and will generate the TypeScript types for the Prisma Client based on your schema. Note that you need to [restart the TypeScript server](https://tinytip.co/tips/vscode-restart-ts/) after doing this so that it can detect the generated types. +Nếu app của bạn sử dụng Prisma, hãy chắc chắn rằng bạn đã chạy lệnh `npx prisma db push` từ thư mục gốc của app. Lệnh này sẽ đồng bộ hóa schema của Prisma với cơ sở dữ liệu của bạn và sẽ tạo ra các kiểu TypeScript cho Prisma Client dựa trên schema của bạn. Lưu ý rằng bạn cần [khởi động lại server TypeScript](https://tinytip.co/tips/vscode-restart-ts/) sau khi làm điều này để nó có thể phát hiện ra các kiểu đã được tạo. ### Drizzle -If your app includes Drizzle, check the `.env` file for instructions on how to construct your `DATABASE_URL` env variable. Once your env file is ready, run `pnpm db:push` (or the equivalent for other package managers) to push your schema. +Nếu app của bạn sử dụng Drizzle, hãy xem file `.env` để biết hướng dẫn cách tạo biến môi trường `DATABASE_URL`. Khi file env của bạn đã sẵn sàng, chạy lệnh `pnpm db:push` (hoặc lệnh tương đương cho các trình quản lý gói khác) để đẩy schema của bạn. -## Authentication +## Xác thực -If your app includes NextAuth.js, we get you started with the `DiscordProvider`. This is one of the simplest providers that NextAuth.js offers, but it still requires a bit of initial setup on your part. +Nếu app của bạn sử dụng NextAuth.js, chúng tôi cung cấp cho bạn một `DiscordProvider`. Đây là một trong những provider đơn giản nhất mà NextAuth.js cung cấp, tuy nhiên nó vẫn cần một chút cấu hình ban đầu từ phía bạn. -Of course, if you prefer to use a different auth provider, you can also use one of the [many providers](https://next-auth.js.org/providers/) that NextAuth.js offers. +Ngoài ra, nếu bạn muốn sử dụng một provider khác, bạn cũng có thể sử dụng một trong [nhiều provider](https://next-auth.js.org/providers/) mà NextAuth.js cung cấp. -1. You will need a Discord account, so register one if you haven't already. -2. Navigate to https://discord.com/developers/applications and click "New Application" in the top right corner. Give your application a name and agree to the Terms of Service. -3. Once your application has been created, navigate to "Settings → OAuth2 → General". -4. Copy the "Client ID" and add it to your `.env` as `AUTH_DISCORD_ID`. -5. Click "Reset Secret", copy the new secret, and add it to your `.env` as `AUTH_DISCORD_SECRET`. -6. Click "Add Redirect" and type in `http://localhost:3000/api/auth/callback/discord`. - - For production deployment, follow the previous steps to create another Discord Application, but this time replace `http://localhost:3000` with the URL that you are deploying to. -7. Save Changes. +1. Bạn cần một tài khoản Discord, vì vậy hãy tạo cho mình một cái một nếu bạn chưa có. +2. Đi đến https://discord.com/developers/applications và ấn "New Application" ở góc trên bên phải. Đặt tên cho ứng dụng của bạn và đồng ý với Điều khoản dịch vụ. +3. Khi ứng dụng của bạn đã được tạo, đi đến "Settings → OAuth2 → General". +4. Copy "Client ID" và thêm nó vào file `.env` dưới dạng `AUTH_DISCORD_ID`. +5. Click "Reset Secret", copy secret mới, và thêm nó vào file `.env` dưới dạng `AUTH_DISCORD_SECRET`. +6. Click "Add Redirect" và nhập `http://localhost:3000/api/auth/callback/discord`. + - Đối với triển khai sản phẩm, hãy làm theo các bước trước để tạo một ứng dụng Discord khác, nhưng lần này thay thế `http://localhost:3000` với URL mà bạn đang triển khai. +7. Lưu thay đổi. -You should now be able to log in. +Và giờ đây bạn đã có thể đăng nhập bằng Discord. -## Editor Setup +## Cấu hình trình soạn thảo của bạn -The following extensions are recommended for an optimal developer experience. The links below provide editor specific plugin support. +Các extension sau đây được khuyến nghị để mang lại một trải nghiệm phát triển tối ưu. Các liên kết dưới đây cung cấp hỗ trợ plugin cho trình chỉnh sửa cụ thể. - [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup) - [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup) - [Prettier Extension](https://prettier.io/docs/en/editors.html) -## Next Steps +## Bước tiếp theo -- If your app includes tRPC, check out `src/pages/index.tsx` and `src/server/api/routers/post.ts` to see how tRPC queries work. -- Have a look around the Create T3 App docs, as well as the docs of the packages that your app includes. -- Join our [Discord](https://t3.gg/discord) and give us a star on [GitHub](https://github.com/t3-oss/create-t3-app)! :) +- Nếu app của bạn sử dụng tRPC, hãy xem `src/pages/index.tsx` và `src/server/api/routers/post.ts` để hiểu cách tRPC queries hoạt động. +- Hãy xem xét các tài liệu của Create T3 App, cũng như các tài liệu của các thư viện mà app của bạn sử dụng. +- Hãy tham gia [Discord](https://t3.gg/discord) của chúng tôi và cho chúng tôi một ngôi sao tại [GitHub](https://github.com/t3-oss/create-t3-app)! :) diff --git a/www/src/pages/vi/usage/next-js.md b/www/src/pages/vi/usage/next-js.md index 6b89d84de1..78171fc94f 100644 --- a/www/src/pages/vi/usage/next-js.md +++ b/www/src/pages/vi/usage/next-js.md @@ -1,37 +1,37 @@ --- title: Next.js -description: Usage of Next.js +description: Sử dụng Next.js layout: ../../../layouts/docs.astro lang: vi --- -Next.js is a backend framework for your React applications. +Next.js được xem như là một framework backend cho các ứng dụng React của bạn.
-Check out [Theo's Next.js Conf talk](https://www.youtube.com/watch?v=W4UhNo3HAMw) to get a better understanding of what Next.js is and how it works.

+Tham khảo [bài giảng của Theo về Next.js](https://www.youtube.com/watch?v=W4UhNo3HAMw) để hiểu rõ hơn về Next.js và cách nó hoạt động. -## Why should I use it? +## Tại sao tôi nên dùng Next.js? -We love React. It has made UI development accessible in ways we never imagined before. It also can lead developers down some rough paths. Next.js offers a lightly opinionated, heavily optimized approach to creating applications using React. From routing to API definitions to image rendering, we trust Next.js to lead developers towards good decisions. +Chúng ta đều yêu React. Nó đã làm cho việc phát triển UI trở nên dễ dàng hơn bao giờ hết. Nhưng đồng thời nó cũng có thể dẫn chúng ta vào ngõ cụt. Next.js cung cấp một cách nhìn nhận về việc phát triển ứng dụng sử dụng React, mang nặng tính tối ưu hóa để tạo ra các ứng dụng sử dụng React. Từ routing đến định nghĩa API đến việc render hình ảnh, chúng tôi tin rằng Next.js sẽ giúp những nhà phát triển web đưa ra các quyết định tốt hơn. -Pairing Next.js with [Vercel](https://vercel.com/) makes developing and deploying web apps easier than ever before. Their extremely generous free-tier and super intuitive interface provides a point and click solution to deploy your site (We ❤️ Vercel) +Sử dụng Next.js với [Vercel](https://vercel.com/) làm cho việc phát triển và triển khai ứng dụng web trở nên dễ dàng hơn bao giờ hết. Với gói miễn phí tuyệt vời và giao diện dễ sử dụng, Vercel cung cấp một giải pháp "point and click" để triển khai trang web của bạn (Chúng tôi ❤️ Vercel) -## Get Static/Server Props +## Lấy dữ liệu tĩnh/Server Props -A key feature of Next.js is its data fetching capabilities. We highly recommend reading through the [official documentation](https://nextjs.org/docs/basic-features/data-fetching) to understand how to use each method and how they differ. `getServerSideProps` is generally discouraged unless there is a good reason for it, due to the fact that it is a blocking call and will slow down your site. [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) is a great alternative to `getServerSideProps` when the data is dynamic and can be fetched incrementally. +Một tính năng quan trọng của Next.js là khả năng đọc dữ liệu. Chúng tôi khuyến nghị bạn tham khảo [tài liệu chính thức](https://nextjs.org/docs/basic-features/data-fetching) để hiểu sự khác biệt giữa chúng và tìm ra cách sử dụng hiệu quả mỗi phương pháp . `getServerSideProps` thường gây ra nhiều phiền toái và áp dụng được với ít trường, bởi vì nó là một blocking call và có thể dẫn tới làm chậm trang web của bạn. [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) là một lựa chọn tốt hơn cho `getServerSideProps` khi dữ liệu của nó trả về là dữ liệu động và có thể được lấy từng phần. -If you need to use this feature anyway, check these links out: [Advanced tRPC - Callers, functions, and gSSP](https://www.youtube.com/watch?v=G2ZzmgShHgQ) and [SSG-Helpers](https://trpc.io/docs/v9/ssg-helpers) +Nếu bạn cần sử dụng tính năng này, hãy tham khảo các liên kết sau: [Advanced tRPC - Callers, functions, and gSSP](https://www.youtube.com/watch?v=G2ZzmgShHgQ) và [SSG-Helpers](https://trpc.io/docs/v9/ssg-helpers) -## Useful Resources +## Tài liệu hữu ích -| Resource | Link | -| ------------------------------ | ---------------------------------- | -| Next.js Documentation | https://nextjs.org/docs | -| Next.js GitHub | https://github.com/vercel/next.js | -| Next.js Blog | https://nextjs.org/blog | -| Next.js Discord | https://nextjs.org/discord | -| Next.js Twitter | https://twitter.com/nextjs | -| Vercel/Next.js YouTube Channel | https://www.youtube.com/c/VercelHQ | +| Tài liệu | Đường dẫn | +| --------------------------- | ---------------------------------- | +| Tài liệu Next.js | https://nextjs.org/docs | +| GitHub Next.js | https://github.com/vercel/next.js | +| Blog Next.js | https://nextjs.org/blog | +| Discord Next.js | https://nextjs.org/discord | +| Twitter Next.js | https://twitter.com/nextjs | +| Kênh Youtube Vercel/Next.js | https://www.youtube.com/c/VercelHQ | From a71e8cb1d4a38346ec5d757ae423e6841e8fb77d Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Thu, 24 Apr 2025 22:38:35 +1000 Subject: [PATCH 10/12] docs(vi): Update Vietnamese for Drizzle Usage, Prisma Usage and Typescript Usage pages --- www/src/pages/vi/usage/drizzle.mdx | 38 ++++++++++++++-------------- www/src/pages/vi/usage/prisma.md | 38 ++++++++++++++-------------- www/src/pages/vi/usage/typescript.md | 38 ++++++++++++++-------------- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/www/src/pages/vi/usage/drizzle.mdx b/www/src/pages/vi/usage/drizzle.mdx index 69e5c085d8..d7589d3383 100644 --- a/www/src/pages/vi/usage/drizzle.mdx +++ b/www/src/pages/vi/usage/drizzle.mdx @@ -1,16 +1,16 @@ --- title: Drizzle -description: Usage of Drizzle +description: Cách sử dụng Drizzle layout: ../../../layouts/docs.astro lang: vi isMdx: true --- -Drizzle is a headless Typescript ORM with [relational](https://orm.drizzle.team/docs/rqb) and [SQL-like](https://orm.drizzle.team/docs/select) query APIs. It can handle database migrations and schemas, and provides a type safe database client. It also comes with [Drizzle-Kit](https://orm.drizzle.team/drizzle-studio/overview), a set of companion tools that help with querying your database. +Drizzle là một Headless Typescript ORM với [các truy vấn kiểu quan hệ](https://orm.drizzle.team/docs/rqb) và [các truy vấn kiểu SQL](https://orm.drizzle.team/docs/select). Nó có thể xử lý các cập nhật cơ sở dữ liệu và các mô hình, và đồng thời cung cấp một client nơi kiểu dữ liệu có mối liên hệ chặt chẽ với cơ sở dữ liệu. Mặt khác, Drizzle cũng cho ra mắt [Drizzle-Kit](https://orm.drizzle.team/drizzle-studio/overview), một bộ công cụ không thể thiếu nhằm giúp bạn làm việc với cơ sở dữ liệu của bạn. ## Drizzle Client -The Drizzle Client is located at `src/server/db/index.ts`. In this file, you can define your database connection url and connect your schema to the database object. +Drizzle Client được định nghĩa ở `src/server/db/index.ts`. Trong tệp này, bạn có thể định nghĩa URL kết nối cơ sở dữ liệu của bạn và kết nối schema của bạn với cơ sở dữ liệu. ```ts:src/server/db/index.ts import { env } from "~/env"; @@ -23,7 +23,7 @@ const conn = postgres(env.DATABASE_URL) export const db = drizzle(conn, { schema }); ``` -We reccommend including the database client in your tRPC Context: +Chúng tôi khuyên bạn nên bao gồm client của Drizzle trong context của tRPC: ```ts:src/server/api/trpc.ts import { db } from "~/server/db"; @@ -41,13 +41,13 @@ export const createTRPCContext = async (opts: { headers: Headers }) => { ## Schema -The Drizzle schema file can be found at `src/server/db/schema.ts`. This file is where you can define your database schema and models, and connects to the Drizzle Client. +Schema của Drizzle có thể được tìm thấy ở `src/server/db/schema.ts`. Đây là nơi bạn có thể định nghĩa schema của cơ sở dữ liệu và các mô hình của bạn, và kết nối chúng với Drizzle Client. -When you select NextAuth.js in combination with Drizzle, the schema file is generated and set up for you with the recommended values for the `User`, `Session`, `Account`, and `VerificationToken` models, as per the [Auth.js documentation](https://authjs.dev/getting-started/adapters/drizzle). +Khi bạn chọn sử dụng NextAuth.js kết hợp với Drizzle, tệp schema được tạo và thiết lập cho bạn với các giá trị được Auth.js khuyến nghị như là `User`, `Session`, `Account`, và `VerificationToken`, tìm hiểu thêm tại [tài liệu Auth.js](https://authjs.dev/getting-started/adapters/drizzle). ## Drizzle Kit -Drizzle Kit is a collection of command line tools designed to help you manage your database. T3 Stack automatically includes drizzle kit when you select Drizzle as your ORM. +Drizzle Kit là một bộ công cụ dòng lệnh (CLI) được thiết kế giúp bạn quản lý cơ sở dữ liệu của bạn. T3 Stack tự động bao gồm Drizzle Kit khi bạn chọn Drizzle làm ORM của mình. ```json:package.json "scripts": { @@ -60,25 +60,25 @@ Drizzle Kit is a collection of command line tools designed to help you manage yo }, ``` -### Script Explanations +### Giải thích các lệnh `db:generate` -Generates TypeScript types and models from your database schema, ensuring type safety and easy integration with Drizzle ORM. +Tạo ra các kiểu TypeScript và mô hình từ schema của cơ sở dữ liệu của bạn, đảm bảo tính toàn vẹn của kiểu dữ liệu và dễ dàng tích hợp với Drizzle ORM. `db:migrate` -Applies pending migrations to your database, keeping your schema in sync with changes and updates in your project. +Áp dụng các cập nhật chưa được áp dụng cho cơ sở dữ liệu của bạn, giữ cho schema của bạn đồng bộ với các thay đổi và cập nhật trong dự án của bạn. `db:push` -Pushes local schema changes directly to the database without needing explicit migration files. This can be useful for quick syncing in development. +Đẩy các thay đổi schema cục bộ trực tiếp đến cơ sở dữ liệu mà không cần các tệp cập nhật chuyển đổi. Điều này có thể hữu ích cho việc đồng bộ hóa nhanh chóng trong quá trình phát triển. `db:studio` -Opens a visual interface for managing and inspecting your database tables, data, and relationships. +Mở một giao diện trực quan để quản lý và kiểm tra các bảng, dữ liệu và mối quan hệ của cơ sở dữ liệu của bạn. -## Useful Resources +## Tài liệu hữu ích -| Resource | Link | -| --------------------------- | --------------------------------------------------- | -| Drizzle Docs | https://orm.drizzle.team/docs/overview | -| Drizzle GitHub | https://github.com/drizzle-team/drizzle-orm | -| Auth.JS Drizzle Adapter | https://authjs.dev/getting-started/adapters/drizzle | -| Drizzle Kit Migration Guide | https://orm.drizzle.team/docs/kit-overview | +| Tài liệu | Đường dẫn | +| ------------------------------------- | --------------------------------------------------- | +| Tài liệu của Drizzle | https://orm.drizzle.team/docs/overview | +| GitHub của Drizzle | https://github.com/drizzle-team/drizzle-orm | +| Adapter Drizzle của Auth.JS | https://authjs.dev/getting-started/adapters/drizzle | +| Hướng dẫn migrate sử dụng Drizzle Kit | https://orm.drizzle.team/docs/kit-overview | diff --git a/www/src/pages/vi/usage/prisma.md b/www/src/pages/vi/usage/prisma.md index cf390353bb..33fd16af7d 100644 --- a/www/src/pages/vi/usage/prisma.md +++ b/www/src/pages/vi/usage/prisma.md @@ -1,31 +1,31 @@ --- title: Prisma -description: Usage of Prisma +description: Cách sử dụng Prisma layout: ../../../layouts/docs.astro lang: vi --- -Prisma is an ORM for TypeScript, that allows you to define your database schema and models in a `schema.prisma` file, and then generate a type-safe client that can be used to interact with your database from your backend. +Prisma là một ORM cho TypeScript, cho phép bạn định nghĩa schema và mô hình của cơ sở dữ liệu của bạn trong tệp `schema.prisma`, và sau đó tạo ra một client mà kiểu dữ liệu của bạn sẽ được liên kết chặt chẽ với cơ sở dữ liệu của bạn và có thể được sử dụng để tương tác với cơ sở dữ liệu của bạn từ backend. ## Prisma Client -Located at `src/server/db.ts`, the Prisma Client is instantiated as a global variable (as recommended as [best practice](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) by the team at Prisma) and exported to be used in your API routes. We include the Prisma Client in [Context](/en/usage/trpc#-serverapitrpcts) by default and recommend using this instead of importing it separately in each file. +Client của Prisma được đặt ở `src/server/db.ts`, được khởi tạo như là một biến toàn cục (được khuyến nghị là [best practice](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) bởi đội ngũ tại Prisma) và được xuất ra để được sử dụng trong các route API của bạn. Chúng tôi đã bao gồm Prisma Client trong [Context](/en/usage/trpc#-serverapitrpcts) và khuyến nghị bạn sử dụng từ Context thay vì nhập nó riêng lẻ trong từng tệp. ## Schema -You will find the Prisma schema file at `/prisma/schema.prisma`. This file is where you define your database schema and models, and is used when generating the Prisma Client. +Bạn sẽ tìm thấy tệp schema của Prisma ở `/prisma/schema.prisma`. Đây là nơi bạn định nghĩa schema và mô hình của cơ sở dữ liệu của bạn, và được sử dụng khi tạo ra client của Prisma. -### With NextAuth.js +### Với NextAuth.js -When you select NextAuth.js in combination with Prisma, the schema file is generated and set up for you with the recommended values for the `User`, `Session`, `Account`, and `VerificationToken` models, as per the [NextAuth.js documentation](https://next-auth.js.org/adapters/prisma). +Khi bạn chọn NextAuth.js kết hợp với Prisma, tệp schema được tạo và thiết lập cho bạn với các giá trị được Auth.js khuyến nghị như là `User`, `Session`, `Account`, và `VerificationToken`, tìm hiểu thêm tại [tài liệu Auth.js](https://next-auth.js.org/adapters/prisma). -## Default Database +## Cơ sở dữ liệu mặc định -The default database is an SQLite database, which is great for development and quickly spinning up a proof-of-concept but is not recommended for production. You can change the database to use by changing the `provider` in the `datasource` block to either `postgresql` or `mysql`, and then updating the connection string within environment variables to point to your database. +Cơ sở dữ liệu mặc định là cơ sở dữ liệu SQLite, tuy đây là điều tốt để bạn có thể tập trung cho phát triển và tạo ra một proof-of-concept nhanh chóng, nhưng chúng tôi không khuyến nghị bạn làm điều này cho production cảu bạn. Bạn có thể thay đổi cơ sở dữ liệu để sử dụng bằng cách thay đổi `provider` trong khối `datasource` thành `postgresql` hoặc `mysql`, và sau đó cập nhật chuỗi kết nối trong biến môi trường để Prisma có thể kết nối với cơ sở dữ liệu của bạn. -## Seeding your Database +## Tạo dữ liệu cho cơ sở dữ liệu -[Seeding your database](https://www.prisma.io/docs/guides/database/seed-database) is a great way to quickly populate your database with test data to help you get started. In order to setup seeding, you will need to create a `seed.ts` file in the `/prisma` directory, and then add a `seed` script to your `package.json` file. You'll also need a TypeScript runner that can execute the seed-script. We recommend [tsx](https://github.com/esbuild-kit/tsx), which is a very performant TypeScript runner that uses esbuild and doesn't require any ESM configuration, but `ts-node` or other runners will work as well. +[Tạo dữ liệu cho cơ sở dữ liệu](https://www.prisma.io/docs/guides/database/seed-database) là một cách tốt để nhanh chóng điền đầy cơ sở dữ liệu với dữ liệu thử nghiệm để giúp bạn bắt đầu. Để thiết lập seeding, bạn sẽ cần tạo một tệp `seed.ts` trong thư mục `/prisma`, và sau đó thêm một script `seed` vào tệp `package.json` của bạn. Bạn cũng sẽ cần thêm vào một Typescript runner để thực thi script seed, chúng tôi đề xuất [tsx](https://github.com/esbuild-kit/tsx), một Typescript runner rất hiệu quả sử dụng esbuild và không yêu cầu bất kỳ cấu hình ESM, nhưng `ts-node` hoặc các runner khác cũng sẽ hoạt động tốt cho bước này. ```jsonc:package.json { @@ -65,14 +65,14 @@ main() }); ``` -Then, just run `pnpm db-seed` (or `npm`/`yarn`) to seed your database. +Sau đó, chỉ cần chạy `pnpm db-seed` (hoặc `npm`/`yarn`) để tạo dữ liệu cho cơ sở dữ liệu của bạn. -## Useful Resources +## Tài liệu hữu ích -| Resource | Link | -| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| Prisma Docs | https://www.prisma.io/docs/ | -| Prisma GitHub | https://github.com/prisma/prisma | -| Prisma Migrate Playground | https://playground.prisma.io/guides | -| NextAuth.JS Prisma Adapter | https://next-auth.js.org/adapters/prisma | -| PlanetScale Connection Guide | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale | +| Tài liệu | Đường dẫn | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| Tài liệu của Prisma | https://www.prisma.io/docs/ | +| GitHub của Prisma | https://github.com/prisma/prisma | +| Khu thử nghiệm Prisma Migrate | https://playground.prisma.io/guides | +| Prisma Adapter cho NextAuth.JS | https://next-auth.js.org/adapters/prisma | +| Hướng dẫn kết nối cơ sở dữ liệu PlanetScale | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale | diff --git a/www/src/pages/vi/usage/typescript.md b/www/src/pages/vi/usage/typescript.md index 44aa41875b..839e46cac5 100644 --- a/www/src/pages/vi/usage/typescript.md +++ b/www/src/pages/vi/usage/typescript.md @@ -1,6 +1,6 @@ --- title: TypeScript -description: Usage of TypeScript +description: Cách sử dụng TypeScript layout: ../../../layouts/docs.astro lang: vi --- @@ -8,7 +8,7 @@ lang: vi

- Build safety nets, not guard rails + Build safety nets, not guard rails - Dựng lưới an toàn, chớ xây lan can

@@ -18,7 +18,7 @@ lang: vi src="/images/theo_300x300.webp" />
- Theo - creator of the T3 Stack + Theo - người tạo ra T3 Stack
-Whether you're a new or seasoned developer, we think that TypeScript is a must have. It can look intimidating at first, but much like a lot of tools, is something that many never look back from after starting to use it. +Cho dù bạn có là lập trình viên tay mơ hay là lập trình viên có kinh nghiệm, chúng tôi nghĩ rằng TypeScript là một "người bạn" không thể thiếu. Mặc dù nó có thể khiến bạn gặp một chút khó khăn khi bắt đầu, nhưng giống như nhiều công cụ hữu ích khác, Typescript sẽ là công cụ khiến nhiều lập trình viên không bao giờ muốn "đường ai nấy đi" khi đã biết tận dụng sức mạnh của nó. -It provides live feedback as you write your code by defining expected data types, and either provides helpful autocomplete in your code editor, or yells at you with red squiggly lines if you're trying to access a property that doesn't exist or trying to pass a value of the wrong type, which you would otherwise have to debug further down the line. +Typescript phản hồi gần như tức thì khi bạn viết code bằng cách định nghĩa kiểu dữ liệu dự kiến, vì thế điểm mạnh của nó là tự cập nhật autocompletion theo những thay đổi mới nhất trong trình soạn thảo mã của bạn, hoặc có thể cảnh báo bạn với dòng gạch màu đỏ lòm nếu bạn đang cố gắng truy cập vào một thuộc tính không tồn tại hoặc đang cố gắng truyền một giá trị có kiểu sai, thứ khiến bạn sẽ phải tốn hàng giờ đồng hồ để "debug" sau đó. -It is, perhaps, the tool that provides the most productivity to developers; providing documentation of the code you're writing or consuming directly in your editor, and having instant feedback as you inevitably make mistakes is absolutely priceless. +Chính vì thế, Typescript là công cụ giúp cho lập trình viên có nhiều năng suất hơn bao giờ hết; cung cấp tài liệu cho code bạn đang viết hoặc sử dụng trực tiếp trong trình soạn thảo của bạn, và có phản hồi ngay lập tức khi bạn làm sai một cái gì đó, giống như bún đậu thì phải chấm với mắm tôm chứ không phải tương ớt vậy. -## Type Inference +## Suy luận kiểu dữ liệu (Type Inference) -While many new TypeScript developers are concerned with _writing_ TypeScript, many of its benefits don't actually require you to change your code at all, in particular inference. Inference means that if something is typed, that type will follow it throughout the flow of the application without having to be re-declared in other places. This means that for example once you have defined the types of the arguments that a function takes, the remainder of the function will usually be typesafe without requiring any further TypeScript-specific code. Library developers put a ton of work into maintaining the types for their libraries, which means that we as application developers can benefit from both the inference and the built-in documentation in your code editor that these types provide. +Mặc dù nhiều lập trình viên TypeScript mới thường lo lắng về việc _định nghĩa kiểu dữ liệu_ TypeScript một cách chuẩn chỉ, nhưng lợi ích thực sự của Typescript nằm ở chỗ nó không yêu cầu bạn phải thay đổi code của mình để thay đổi kiểu dữ liệu, hay còn gọi là suy luận kiểu dữ liệu (Type Inference). Suy luận kiểu dữ liệu có nghĩa là nếu bạn đã định nghĩa một kiểu dữ liệu, kiểu dữ liệu đó sẽ đi theo trong suốt luồng của ứng dụng mà không cần phải khai báo lại ở những nơi khác. Điều này có nghĩa là, ví dụ, một khi bạn đã định nghĩa kiểu của các tham số mà một hàm nhận vào, phần còn lại của hàm thường sẽ được đảm bảo an toàn về kiểu dữ liệu mà không cần thêm bất kỳ code TypeScript cụ thể nào. Các nhà phát triển thư viện đã phải bỏ ra rất nhiều công sức để duy trì các kiểu dữ liệu cho thư viện của họ, điều này có nghĩa là chúng ta với tư cách là nhà phát triển ứng dụng có thể hưởng lợi từ cả suy luận kiểu dữ liệu và "tài liệu" được tích hợp trong trình soạn thảo code mà các kiểu này cung cấp.
-Check out Theo's video on how [you might be using TypeScript wrong](https://www.youtube.com/watch?v=RmGHnYUqQ4k). +Xem thêm video của Theo về cách [bạn có thể sử dụng TypeScript sai](https://www.youtube.com/watch?v=RmGHnYUqQ4k). -## Powerful uses of type inference +## Các ứng dụng mạnh mẽ của suy luận kiểu dữ liệu ### Zod -[Zod](https://github.com/colinhacks/zod) is a schema validation library that is built on top of TypeScript. Write a schema that represents a single source of truth for your data, and Zod will ensure that your data is valid throughout your application, even across network boundaries and external APIs. +[Zod](https://github.com/colinhacks/zod) là một thư viện kiểm tra dữ liệu được xây dựng trên TypeScript. Viết một schema đại diện cho một nguồn thật sự duy nhất cho dữ liệu của bạn, và Zod sẽ đảm bảo rằng dữ liệu của bạn hợp lệ trong suốt ứng dụng của bạn, thậm chí cả khi đi qua ranh giới mạng và API bên ngoài. ### Tanstack Query -[Tanstack Query](https://tanstack.com/query/v4/) gives you declarative, always-up-to-date auto-managed queries and mutations that directly improve both your developer and user experiences. +[Tanstack Query](https://tanstack.com/query/v4/) cung cấp cho bạn các truy vấn và thao tác sửa đổi theo kiểu khai báo, được quản lý tự động và luôn được cập nhật, từ đó trực tiếp cải thiện trải nghiệm của cả lập trình viên và người dùng. -## Useful Resources +## Tài liệu hữu ích -| Resource | Link | -| --------------------------------------------------------- | ----------------------------------------------------------------- | -| TypeScript Handbook | https://www.typescriptlang.org/docs/handbook/ | -| Beginners TypeScript Tutorial | https://github.com/total-typescript/beginners-typescript-tutorial | -| Type Challenges | https://github.com/type-challenges/type-challenges | -| Rodney Mullen of TypeScript (Matt Pocock) Youtube Channel | https://www.youtube.com/c/MattPocockUk/videos | +| Tài liệu | Đường dẫn | +| ----------------------------------------------------------------------------------- | ----------------------------------------------------------------- | +| Cẩm nang TypeScript | https://www.typescriptlang.org/docs/handbook/ | +| TypeScript dành cho tân thủ | https://github.com/total-typescript/beginners-typescript-tutorial | +| Luyện tập typing chuẩn Typescript  | https://github.com/type-challenges/type-challenges | +| Kênh Youtube của người được mệnh danh là Rodney Mullen của TypeScript (Matt Pocock) | https://www.youtube.com/c/MattPocockUk/videos | From dee5e30a3cc3bdaa2697af4951f009a53b61b97f Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Sat, 26 Apr 2025 12:01:39 +1000 Subject: [PATCH 11/12] docs(vi): Update Vietnamese for Tailwind Usage, tRPC Usage and Environment Variable usages pages --- www/src/pages/vi/usage/env-variables.mdx | 65 +++++----- www/src/pages/vi/usage/tailwind.md | 60 ++++----- www/src/pages/vi/usage/trpc.md | 150 +++++++++++------------ 3 files changed, 137 insertions(+), 138 deletions(-) diff --git a/www/src/pages/vi/usage/env-variables.mdx b/www/src/pages/vi/usage/env-variables.mdx index bb3cb47e51..4e5e8f8f01 100644 --- a/www/src/pages/vi/usage/env-variables.mdx +++ b/www/src/pages/vi/usage/env-variables.mdx @@ -1,6 +1,6 @@ --- -title: Environment Variables -description: Getting started with Create T3 App +title: Biến môi trường +description: Bắt đầu với Create T3 App layout: ../../../layouts/docs.astro lang: vi isMdx: true @@ -8,11 +8,11 @@ isMdx: true import Callout from "../../../components/docs/callout.tsx"; -Create T3 App uses its own package [@t3-oss/env-nextjs](https://env.t3.gg) along with [zod](https://zod.dev) under the hood for validating environment variables at runtime _and_ buildtime by providing a simple logic in `src/env.js`. +Create T3 App sử dụng một thư viện tự tạo tên là [@t3-oss/env-nextjs](https://env.t3.gg) cùng với [zod](https://zod.dev) để xác thực biến môi trường trong thời gian chạy (runtime) _và_ thời gian xây dựng (buildtime) bằng cách cung cấp một logic đơn giản trong `src/env.js`. ## env.js -_TLDR; If you want to add a new environment variable, you must add a validator for it in `src/env.js`, and then add the KV-pair in `.env`_ +_TLDR; Nếu bạn muốn thêm một biến môi trường mới, bạn phải thêm một validator trong `src/env.js`, và sau đó thêm chúng vào trong `.env`_ ```ts:env.js import { createEnv } from "@t3-oss/env-nextjs"; @@ -31,70 +31,69 @@ export const env = createEnv({ }); ``` -T3 Env uses the `createEnv` function to create the schema validate both client and server-side environment variables. +T3 Env sử dụng hàm `createEnv` để tạo schema và xác thực cả biến môi trường cho cả client-side và server-side. - For more information about how `createEnv` works internally, check out the [T3 - Env](https://env.t3.gg/docs/introduction) docs + Để biết thêm thông tin về cách `createEnv` hoạt động bên trong, hãy tham khảo + tài liệu của [T3 Env](https://env.t3.gg/docs/introduction) -## Using Environment Variables +## Sử dụng biến môi trường -When you want to use your environment variables, you can import them from the created `env.js` and use them as you would normally do. If you import this on the client and try accessing a server-side environment variable, you will get a runtime error. +Khi bạn muốn sử dụng biến môi trường của bạn, bạn có thể nhập chúng từ tập tin đã tạo `env.js` và sử dụng chúng như bạn thường làm. Nếu bạn nhập chúng trên client và cố gắng truy cập vào một biến môi trường server-side, bạn sẽ nhận được một lỗi thời gian chạy. ```ts:pages/api/hello.ts import { env } from "../../env.js"; -// `env` is fully typesafe and provides autocompletion +// `env` đảm bảo typesafe và cung cấp tự động hoàn tất const dbUrl = env.DATABASE_URL; ``` ```ts:pages/index.tsx import { env } from "../env.js"; -// ❌ This will throw a runtime error +// ❌ Sẽ tạo ra một lỗi thời gian chạy const dbUrl = env.DATABASE_URL; -// ✅ This is fine +// ✅ Đủ wow rồi đó const wsKey = env.NEXT_PUBLIC_WS_KEY; ``` ## .env.example -Since the default `.env` file is not committed to version control, we have also included a `.env.example` file, in which you can optionally keep a copy of your `.env` file with any secrets removed. This is not required, but we recommend keeping the example up to date to make it as easy as possible for contributors to get started with their environment. +Vì tập tin `.env` mặc định không được commit vào version control, chúng tôi cũng đã bao gồm một tập tin `.env.example`, trong đó bạn có thể tùy chọn giữ một bản sao của tập tin `.env` của bạn mà không để lộ bất kì thông tin nào bí mật. Điều này không bắt buộc, nhưng chúng tôi khuyên bạn nên giữ file này để dễ dàng hơn cho người đóng góp bắt đầu với môi trường của họ. -Some frameworks and build tools, like Next.js, suggest that you store secrets in a `.env.local` file and commit `.env` files to your project. This is not recommended, as it could make it easy to accidentally commit secrets to your project. Instead, we recommend that you store secrets in `.env`, keep your `.env` file in your `.gitignore` and only commit `.env.example` files to your project. +Một số framework và công cụ build, như Next.js, khuyên bạn nên lưu trữ bí mật trong tập tin `.env.local` và commit tập tin `.env` vào project. Chúng tôi không khuyến khích điều này, vì nó có thể làm cho việc commit bí mật vào project trở nên dễ dàng hơn. Thay vào đó, chúng tôi khuyên bạn nên lưu trữ bí mật trong `.env`, giữ tập tin `.env` của bạn trong `.gitignore` và chỉ commit tập tin `.env.example` vào project. -## Adding Environment Variables +## Thêm biến môi trường -To ensure your build never completes without the environment variables the project needs, you will need to add new environment variables in **two** locations: +Để đảm bảo rằng quá trình build của bạn không thể hoành thành nếu không có các biến môi trường mà project cần, bạn sẽ cần thêm biến môi trường mới vào **hai** vị trí: -📄 `.env`: Enter your environment variable like you would normally do in a `.env` file, i.e. `KEY=VALUE` +📄 `.env`: Nhập biến môi trường của bạn như bạn dưới dạng `KEY=VALUE` trong tập tin `.env` -📄 `env.js`: Add the appropriate validation logic for the environment variables by defining a Zod schema inside `createEnv` for each one, e.g. `KEY: z.string()`. Besides that, make sure to destruct them in the `runtimeEnv` option, e.g.: `KEY: process.env.KEY` +📄 `env.js`: Thêm logic xác thực thích hợp cho các biến môi trường bằng cách định nghĩa một schema Zod bên trong `createEnv` cho mỗi biến, ví dụ: `KEY: z.string()`. Ngoài ra, hãy đảm bảo rằng bạn thêm chúng trong tùy chọn `runtimeEnv`, ví dụ: `KEY: process.env.KEY` - Why do I need to destructure the environment variable in the `runtimeEnv`? - This is due to how Next.js bundles environment variables in certain runtimes. - By destructuring it manually, you ensure that the variable will never be - stripped out from the bundle. + Tại sao tôi cần phân thêm biến môi trường trong `runtimeEnv`? Điều này là do + cách Next.js đóng gói biến môi trường trong các runtime nhất định. Bằng cách + này, bạn đảm bảo rằng biến sẽ không bao giờ bị loại bỏ khỏi bundle. -Optionally, you can also keep `.env.example` updated: +Tùy chọn, bạn cũng có thể giữ tập tin `.env.example` cập nhật: -📄 `.env.example`: Enter your environment variable, but be sure to not include the value if it is secret, i.e. `KEY=VALUE` or `KEY=` +📄 `.env.example`: Nhập biến môi trường của bạn, nhưng hãy đảm bảo rằng bạn không bao gồm giá trị nếu nó là bí mật, tức là `KEY=VALUE` hoặc `KEY=` -### Example +### Ví dụ -_I want to add my Twitter API Token as a server-side environment variable_ +_Tôi muốn thêm biến môi trường của Twitter API vào biến môi trường server-side_ -1. Add the environment variable to `.env`: +1. Thêm biến môi trường vào `.env`: ``` TWITTER_API_TOKEN=1234567890 ``` -2. Add the environment variable to `env.js`: +2. Thêm biến môi trường vào `env.js`: ```ts import { createEnv } from "@t3-oss/env-nextjs"; @@ -112,24 +111,24 @@ export const env = createEnv({ }); ``` -3. _Optional:_ Add the environment variable to `.env.example` and make sure not to include the secret in the `runtimeEnv` option +3. _Tùy chọn:_ Thêm biến môi trường vào `.env.example` và đảm bảo rằng bạn không bao gồm giá trị bí mật trong tùy chọn `runtimeEnv` ```bash TWITTER_API_TOKEN= ``` -## Type Coercion +## Ép kiểu biến -All variables you add to `.env` will be imported as strings, even if their value is intended to represent a different type. If you want to use your environment variables as a different type at runtime, you can use Zod's `coerce` to convert the string to the type you want. It will throw if the coercion fails. +Tất cả các biến môi trường bạn thêm vào `.env` sẽ được nhập dưới dạng chuỗi, ngay cả khi giá trị của chúng được dự định đại diện cho một kiểu khác. Nếu bạn muốn sử dụng biến môi trường của bạn dưới dạng kiểu khác tại thời gian chạy, bạn có thể sử dụng `zod.coerce` để chuyển đổi chuỗi thành kiểu bạn muốn. Nó sẽ báo lỗi nếu ép kiểu không thành công. -Add the variables to your `.env`: +Thêm biến môi trường vào `.env`: ``` SOME_NUMBER=123 SOME_BOOLEAN=true ``` -Then, validate them in `env.js`: +Sau đó, xác thực chúng trong `env.js`: ```ts import { createEnv } from "@t3-oss/env-nextjs"; diff --git a/www/src/pages/vi/usage/tailwind.md b/www/src/pages/vi/usage/tailwind.md index df007379d4..779fd37720 100644 --- a/www/src/pages/vi/usage/tailwind.md +++ b/www/src/pages/vi/usage/tailwind.md @@ -1,19 +1,19 @@ --- title: Tailwind CSS -description: Usage of Tailwind CSS +description: Sử dụng Tailwind CSS layout: ../../../layouts/docs.astro lang: vi --- -## What is Tailwind CSS? +## Tailwind CSS là gì? -Tailwind CSS is a tiny, [utility first](https://tailwindcss.com/docs/utility-first) CSS framework for building custom designs, without the context switching that regular CSS requires. It is purely a CSS framework and does not provide any pre-built components or logic, and provides [a very different set of benefits](https://www.youtube.com/watch?v=CQuTF-bkOgc) compared to a component library like Material UI. +Tailwind CSS là một framework CSS nhỏ gọn, [tập trung vào utility](https://tailwindcss.com/docs/utility-first) nhằm cho phép bạn xây dựng thiết kế tùy chỉnh mà không cần chuyển đổi context giữa CSS thông thường. Nó là một framework CSS và không cung cấp bất kỳ thành phần tiền xây dựng hoặc logic nào, và cung cấp [một tập hợp khác biệt](https://www.youtube.com/watch?v=CQuTF-bkOgc) so với một các thư viện khác như Material UI. -It makes CSS incredibly easy and quick to write, as shown by the following example: +Nó làm cho CSS trở nên vô cùng dễ dàng và nhanh chóng để viết, như được chứng minh bởi ví dụ sau: -Old CSS: +CSS thông thường: -1. Write CSS, often in a separate file +1. Viết CSS, thường trong một file riêng ```css .my-class { @@ -28,21 +28,21 @@ Old CSS: } ``` -2. Import CSS into your component +2. Import CSS vào component của bạn ```jsx import "./my-class.css"; ``` -3. Add the class to your HTML +3. Thêm class vào HTML ```html
...
``` -Equivalent in Tailwind: +Tương đương trong Tailwind: -1. Just write classes in your HTML +1. Chỉ viết classes trong HTML của bạn ```html
``` -When used together with React Components, it is extremely powerful for quickly building UIs. +Khi sử dụng cùng với React Components, nó mang đến sức mạnh để xây dựng UI một cách nhanh chóng. -Tailwind CSS has a beautiful built-in design system, that comes out of the box with a carefully chosen color palette, sizing patterns for styles such as width/height and padding/margin for a uniform design, as well as media breakpoints for creating responsive layouts. This design system can be customized and extended to create the exact toolbox of styles that your project needs. +Tailwind CSS có một hệ thống thiết kế tích hợp sẵn, được tạo ra từ box với một palette màu sắc được chọn cẩn thận, các kích thước cho các kiểu như width/height và padding/margin cho một thiết kế đồng nhất, cũng như các điểm cắt cho tạo ra các bố cục hài hòa. Hệ thống này được thiết kế này để có thể dễ dàng tùy chỉnh và mở rộng để tạo ra các công cụ mà bạn cần.
-Tru Narla better known as [mewtru](https://twitter.com/trunarla) gave an amazing talk on [building a design system using Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI). +Tru Narla, hay được biết đến dưới tên một người dùng Twitter là [mewtru](https://twitter.com/trunarla), đã cho chúng ta một bài nói chuyện tuyệt vời về [cách xây dựng một hệ thống thiết kế sử dụng Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI). -## Usage +## Sử dụng -Make sure you have editor plugins for Tailwind installed to improve your experience writing Tailwind. +Hãy đảm bảo rằng bạn đã cài đặt các plugin editor cho Tailwind CSS để cải thiện trải nghiệm viết Tailwind CSS. ### Extensions and Plugins @@ -72,25 +72,25 @@ Make sure you have editor plugins for Tailwind installed to improve your experie - [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install) - [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss) -### Formatting +### Định dạng -Tailwind CSS classes can easily get a bit messy, so a formatter for the classes is a must have. [Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) sorts the classes in the [recommended order](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) so that the classes match the outputted css bundle. When selecting Tailwind in the CLI, we will install and configure this for you. +Tailwind CSS classes có thể dễ dàng trở nên lộn xộn, vì vậy việc cần có một định dạng cho các classes là điều cần thiết. [Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) sắp xếp các classes trong [thứ tự được đề xuất](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) để các classes phù hợp với bundle CSS được xuất ra. Khi chọn Tailwind trong CLI, chúng tôi sẽ cài đặt và cấu hình nó cho bạn. -### Conditionally Applying Classes +### Áp dụng điều kiện -Conditionally adding classes using ternaries can get very messy and hard to read. These packages help in organizing your classes when using some conditional logic. +Thêm classes bằng cách sử dụng ternaries có thể trở nên rất lộn xộn và khó đọc. Các package này giúp sắp xếp các classes của bạn khi sử dụng một số logic điều kiện. - [clsx](https://github.com/lukeed/clsx) - [classnames](https://github.com/JedWatson/classnames) -## Useful Resources - -| Resource | Link | -| ---------------------------- | -------------------------------------------------------- | -| Tailwind Docs | https://tailwindcss.com/docs/editor-setup/ | -| Tailwind Cheat Sheet | https://nerdcave.com/tailwind-cheat-sheet/ | -| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ | -| Tailwind Community | https://github.com/tailwindlabs/tailwindcss/discussions/ | -| Tailwind Discord Server | https://tailwindcss.com/discord/ | -| TailwindLabs Youtube Channel | https://www.youtube.com/tailwindlabs/ | -| Tailwind Playground | https://play.tailwindcss.com/ | +## Tài liệu hữu ích + +| Tài liệu | Đường dẫn | +| --------------------------- | -------------------------------------------------------- | +| Tài liệu củaTailwind | https://tailwindcss.com/docs/editor-setup/ | +| Tailwind Cheat Sheet | https://nerdcave.com/tailwind-cheat-sheet/ | +| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ | +| Cộng đồng Tailwind | https://github.com/tailwindlabs/tailwindcss/discussions/ | +| Server Discord của Tailwind | https://tailwindcss.com/discord/ | +| Kênh Youtube của Tailwind | https://www.youtube.com/tailwindlabs/ | +| Playground của Tailwind | https://play.tailwindcss.com/ | diff --git a/www/src/pages/vi/usage/trpc.md b/www/src/pages/vi/usage/trpc.md index 0572372f9c..d9f2d52829 100644 --- a/www/src/pages/vi/usage/trpc.md +++ b/www/src/pages/vi/usage/trpc.md @@ -1,16 +1,16 @@ --- title: tRPC -description: Usage of tRPC +description: Cách sử dụng tRPC layout: ../../../layouts/docs.astro lang: vi --- -tRPC allows us to write end-to-end typesafe APIs without any code generation or runtime bloat. It uses TypeScript's great inference to infer your API router's type definitions and lets you call your API procedures from your frontend with full typesafety and auto-completion. When using tRPC, your frontend and backend feel closer together than ever before, allowing for an outstanding developer experience. +tRPC cho phép chúng ta viết API có tính toàn vẹn của kiểu dữ liệu (typesafe) mà không cần qua các bước tạo code (code generation) hoặc runtime bloat. Nó sử dụng inference của TypeScript để suy ra định nghĩa kiểu của router API của bạn và cho phép bạn gọi các thủ tục API của bạn từ frontend mà vẫn đảm bảo tính toàn vẹn của kiểu dữ liệu và auto-completion. Khi sử dụng tRPC, frontend và backend của bạn gần nhau hơn bao giờ hết, cho phép bạn có trải nghiệm lập trình (developer experience) tuyệt vời.

- I built tRPC to allow people to move faster by removing the need for a traditional API-layer, while still having confidence that our apps won't break as we rapidly iterate. + Tôi tạo tRPC để cho phép mọi người lập trình nhanh hơn bằng cách loại bỏ API layer truyền thống, trong khi vẫn đảm bảo rằng ứng dụng của chúng ta sẽ không bị phá vỡ khi chúng ta lập trình ứng dụng một cách nhanh chóng.

@@ -20,7 +20,7 @@ tRPC allows us to write end-to-end typesafe APIs without any code generation or src="https://avatars.githubusercontent.com/u/459267?v=4" />
-## How do I use tRPC? +## Làm sao để tôi sử dụng tRPC?
-tRPC contributor [trashh_dev](https://twitter.com/trashh_dev) made [a killer talk at Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) about tRPC. We highly recommend you watch it if you haven't already. +Contributor của tRPC, [trashh_dev](https://twitter.com/trashh_dev), đã có [một bài giảng tuyệt vời tại Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) về tRPC. Chúng tôi khuyên bạn nên tham khảo qua video trước nếu bạn chưa từng sử dụng tRPC. -With tRPC, you write TypeScript functions on your backend, and then call them from your frontend. A simple tRPC procedure could look like this: +Với tRPC, bạn viết các hàm TypeScript trên backend, và sau đó gọi chúng từ frontend. Một tRPC procedure đơn giản có thể được định nghĩa như sau: ```ts:server/api/routers/user.ts const userRouter = createTRPCRouter({ @@ -55,11 +55,11 @@ const userRouter = createTRPCRouter({ }); ``` -This is a tRPC procedure (equivalent to a route handler in a traditional backend) that first validates the input using Zod (which is the same validation library that we use for [environment variables](./env-variables)) - in this case, it's making sure that the input is a string. If the input is not a string it will send an informative error instead. +Đây là một tRPC procedure (tương đương với một route handler trong backend truyền thống), nó bắt đầu bằng cách kiểm tra đầu vào bằng thư viện Zod (đồng thời cũng là thư viện validation mà chúng tôi sử dụng cho [biến môi trường](./env-variables)) - trong trường hợp này, nó đảm bảo rằng đầu vào là một chuỗi. Nếu đầu vào không phải là một chuỗi, nó sẽ báo lỗi ngay. -After the input, we chain a resolver function which can be either a [query](https://trpc.io/docs/client/react/useQuery), [mutation](https://trpc.io/docs/v11/client/react/useMutation), or a [subscription](https://trpc.io/docs/v11/subscriptions). In our example, the resolver calls our database using our [prisma](./prisma) client and returns the user whose `id` matches the one we passed in. +Sau đó, chúng ta có một hàm resolver, có thể là [query](https://trpc.io/docs/client/react/useQuery), [mutation](https://trpc.io/docs/v11/client/react/useMutation), hoặc một [subscription](https://trpc.io/docs/v11/subscriptions). Trong ví dụ của chúng tôi, hàm resolver này gọi tới cơ sở dữ liệu bằng cách sử dụng [prisma](./prisma) client và trả về người dùng có `id` khớp với id mà chúng tôi đã truyền vào. -You define your procedures in `routers` which represent a collection of related procedures with a shared namespace. You may have one router for `users`, one for `posts`, and another one for `messages`. These routers can then be merged into a single, centralized `appRouter`: +Bạn định nghĩa các procedures trong `routers` mà đại diện cho một tập hợp các procedures liên quan với nhau và có cùng namespace. Bạn có thể có một router cho `users`, một cho `posts`, và một router khác cho `messages`. Sau đó, các router này có thể được gộp lại thành một `appRouter` duy nhất: ```ts:server/api/root.ts const appRouter = createTRPCRouter({ @@ -71,9 +71,9 @@ const appRouter = createTRPCRouter({ export type AppRouter = typeof appRouter; ``` -Notice that we only need to export our router's type definitions, which means we are never importing any server code on our client. +Chú ý rằng chúng ta chỉ cần xuất (export) kiểu dữ liệu của router của chúng ta, điều này có nghĩa là chúng ta chẳng cần phải import bất kỳ một đoạn code server nào ở phía client. -Now let's call the procedure on our frontend. tRPC provides a wrapper for `@tanstack/react-query` which lets you utilize the full power of the hooks they provide, but with the added benefit of having your API calls typed and inferred. We can call our procedures from our frontend like this: +Bây giờ, chúng ta sẽ thử gọi một procedure của chúng ta trên frontend. tRPC có cung cấp một wrapper cho `@tanstack/react-query` cho phép bạn sử dụng toàn bộ sức mạnh của các hooks mà nó cung cấp, nhưng với lợi ích thêm là các cuộc gọi API của bạn sẽ được tự động định kiểu và suy ra. Chúng ta có thể gọi các procedures của chúng ta từ frontend như sau: ```tsx:pages/users/[id].tsx import { useRouter } from "next/router"; @@ -91,13 +91,13 @@ const UserPage = () => { }; ``` -You'll immediately notice how good the autocompletion and typesafety is. As soon as you write `api.`, your routers will show up in autocomplete, and when you select a router, its procedures will show up as well. You'll also get a TypeScript error if your input doesn't match the validator that you defined on the backend. +Bạn sẽ nhận thấy ngay lập tức việc autocompletion và tính toàn vẹn kiểu dữ liệu làm cho việc lập trình trở nên tuyệt vời hơn bao giờ hết. Ngay khi bạn viết `api.`, các routers của bạn sẽ xuất hiện trong autocomplete, và khi bạn chọn một router, các procedures của nó cũng sẽ xuất hiện. Bạn cũng sẽ nhận được một lỗi TypeScript nếu đầu vào của bạn không khớp với validator mà bạn đã định nghĩa ở phía backend. -## Inferring errors +## Xử lý lỗi -By default, `create-t3-app` sets up an [error formatter](https://trpc.io/docs/v11/server/error-formatting) that lets you infer your Zod Errors if you get validation errors on the backend. +Mặc định, `create-t3-app` đã thiết lập một [error formatter](https://trpc.io/docs/v11/server/error-formatting) cho phép bạn suy ra các lỗi Zod nếu bạn nhận được lỗi validation ở phía backend. -Example usage: +Ví dụ: ```tsx function MyComponent() { @@ -111,7 +111,7 @@ function MyComponent() { }}> {error?.data?.zodError?.fieldErrors.title && ( - {/** `mutate` returned with an error on the `title` */} + {/** `mutate` trả về lỗi trên `title` */} {error.data.zodError.fieldErrors.title} @@ -123,57 +123,57 @@ function MyComponent() { } ``` -## Files +## Các file -tRPC requires quite a lot of boilerplate that `create-t3-app` sets up for you. Let's go over the files that are generated: +tRPC yêu cầu rất nhiều boilerplate mà `create-t3-app` đã thiết lập cho bạn. Hãy cùng chúng tôi đi qua các file đã được tạo: ### 📄 `pages/api/trpc/[trpc].ts` -This is the entry point for your API and exposes the tRPC router. Normally, you won't touch this file very much, but if you need to, for example, enable CORS middleware or similar, it's useful to know that the exported `createNextApiHandler` is a [Next.js API handler](https://nextjs.org/docs/api-routes/introduction) which takes a [request](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [response](https://developer.mozilla.org/en-US/docs/Web/API/Response) object. This means that you can wrap the `createNextApiHandler` in any middleware you want. See below for an [example snippet](#enabling-cors) of adding CORS. +Đây được gọi là điểm xuất phát cho API của bạn và để thêm vào các router của tRPC. Thông thường, bạn sẽ không phải lo lắng với file này nhiều, nhưng nếu cần thiết, ví dụ như khi bạn muốn sử dụng các middleware như CORS hoặc tương tự, hãy biết rằng hàm `createNextApiHandler` là một [Next.js API handler](https://nextjs.org/docs/api-routes/introduction) nhận vào một đối tượng [request](https://developer.mozilla.org/en-US/docs/Web/API/Request) và [response](https://developer.mozilla.org/en-US/docs/Web/API/Response). Điều này có nghĩa là bạn có thể bọc `createNextApiHandler` trong bất kỳ middleware nào bạn muốn. Xem [ví dụ](#sử-dụng-cors) dưới đây để biết cách thêm CORS. ### 📄 `server/api/trpc.ts` -This file is split up in two parts, context creation and tRPC initialization: +File này được chia thành hai phần: khởi tạo context và khởi tạo tRPC: -1. We define the context that is passed to your tRPC procedures. Context is data that all of your tRPC procedures will have access to, and is a great place to put things like database connections, authentication information, etc. In create-t3-app we use two functions, to enable using a subset of the context when we do not have access to the request object. +1. Đây là nơi chúng ta định nghĩa context mà tRPC procedures sẽ có thể truy cập. Context là nơi mà tất cả các procedures của tRPC sẽ có thể truy cập để sử dụng những dữ liệu được "đựng" trong đó. Chính vì thế, đây là nơi tuyệt vời để đặt các thứ như kết nối cơ sở dữ liệu, thông tin xác thực, v.v. Trong `create-t3-app`, chúng tôi sử dụng hai hàm, để cho phép sử dụng một tập con của context khi chúng ta không có đối tượng request. -- `createInnerTRPCContext`: This is where you define context which doesn't depend on the request, e.g. your database connection. You can use this function for [integration testing](#sample-integration-test) or [ssg-helpers](https://trpc.io/docs/v10/client/nextjs/server-side-helpers) where you don't have a request object. +- `createInnerTRPCContext`: Đây là nơi bạn định nghĩa context mà không phụ thuộc vào request, ví dụ như kết nối cơ sở dữ liệu. Bạn có thể sử dụng hàm này cho [integration testing](#sample-integration-test) hoặc [ssg-helpers](https://trpc.io/docs/v10/client/nextjs/server-side-helpers) khi bạn không có đối tượng request. -- `createTRPCContext`: This is where you define context which depends on the request, e.g. the user's session. You request the session using the `opts.req` object, and then pass the session down to the `createInnerTRPCContext` function to create the final context. +- `createTRPCContext`: Đây là nơi bạn định nghĩa context mà phụ thuộc vào request, ví dụ như thông tin phiên người dùng. Bạn yêu cầu phiên người dùng bằng cách sử dụng đối tượng `opts.req`, và sau đó chuyển phiên người dùng xuống hàm `createInnerTRPCContext` để tạo context cuối cùng. -2. We initialize tRPC and define reusable [procedures](https://trpc.io/docs/v11/server/procedures) and [middlewares](https://trpc.io/docs/v11/server/middlewares). By convention, you shouldn't export the entire `t`-object but instead, create reusable procedures and middlewares and export those. +2. Chúng ta khởi tạo tRPC và định nghĩa các procedures có thể tái sử dụng và [middlewares](https://trpc.io/docs/v11/server/middlewares). Theo quy ước, bạn không nên xuất toàn bộ đối tượng `t` mà thay vào đó, tạo các procedures và middlewares để có thể tái sử dụng chúng. -You'll notice we use `superjson` as [data transformer](https://trpc.io/docs/v10/server/data-transformers). This makes it so that your data types are preserved when they reach the client, so if you for example send a `Date` object, the client will return a `Date` and not a string which is the case for most APIs. +Chúng tôi sử dụng `superjson` để làm [data transformer](https://trpc.io/docs/v10/server/data-transformers). Điều này có nghĩa là dữ liệu của bạn sẽ được bảo toàn khi chúng đến client, vì vậy nếu bạn gửi một đối tượng `Date`, client sẽ trả về một đối tượng `Date` và không phải là một chuỗi, như là trường hợp với hầu hết các APIs. ### 📄 `server/api/routers/*.ts` -This is where you define the routes and procedures of your API. By convention, you [create separate routers](https://trpc.io/docs/v11/server/routers) for related procedures. +Đây là nơi bạn định nghĩa các routes và procedures của API của bạn. Theo quy ước, bạn nên [tạo các routers riêng biệt](https://trpc.io/docs/v11/server/routers) cho các procedures liên quan. ### 📄 `server/api/root.ts` -Here we [merge](https://trpc.io/docs/v11/server/merging-routers) all the sub-routers defined in `routers/**` into a single app router. +Ở đây chúng ta thực hiện [gộp](https://trpc.io/docs/v11/server/merging-routers) tất cả các routers con được định nghĩa trong `routers/**` thành một router duy nhất. ### 📄 `utils/api.ts` -This is the frontend entry point for tRPC. This is where you'll import the router's **type definition** and create your tRPC client along with the react-query hooks. Since we enabled `superjson` as our data transformer on the backend, we need to enable it on the frontend as well. This is because the serialized data from the backend is deserialized on the frontend. +Đây là điểm xuất phát cho tRPC ở phía frontend. Đây là nơi bạn sẽ import **type definition** của router và tạo client tRPC của bạn cùng với các hooks react-query. Vì chúng tôi đã sử dụng `superjson` làm data transformer ở phía backend, chúng tôi cần sử dụng nó ở phía frontend. Điều này sẽ giúp cho việc dữ liệu được chuyển đổi từ backend sẽ được giải mã ở phía frontend. -You'll define your tRPC [links](https://trpc.io/docs/v11/client/links) here, which determines the request flow from the client to the server. We use the "default" [`httpBatchLink`](https://trpc.io/docs/v11/client/links/httpBatchLink) which enables [request batching](https://cloud.google.com/compute/docs/api/how-tos/batch), as well as a [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink) which outputs useful request logs during development. +Bạn sẽ định nghĩa các [links](https://trpc.io/docs/v11/client/links) ở đây, điều này xác định luồng request từ client đến server. Chúng tôi sử dụng [`httpBatchLink`](https://trpc.io/docs/v11/client/links/httpBatchLink) mà cho phép [request batching](https://cloud.google.com/compute/docs/api/how-tos/batch), cũng như một [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink) mà xuất ra các log request hữu ích trong quá trình phát triển. -Lastly, we export a [helper type](https://trpc.io/docs/client/vanilla/infer-types) which you can use to infer your types on the frontend. +Cuối cùng, chúng tôi xuất ra một [helper type](https://trpc.io/docs/client/vanilla/infer-types) mà bạn có thể sử dụng để suy ra kiểu dữ liệu của bạn ở phía frontend.
-Create T3 App contributor [Christopher Ehrlich](https://twitter.com/ccccjjjjeeee) made [a video about data flows in tRPC](https://www.youtube.com/watch?v=x4mu-jOiA0Q). This video is recommended if you have used tRPC but still feel a bit unclear about how it works. +Một contributor khác của Create T3 App, [Christopher Ehrlich](https://twitter.com/ccccjjjjeeee), đã làm một video về [luồng dữ liệu trong tRPC](https://www.youtube.com/watch?v=x4mu-jOiA0Q). Video này được khuyến khích nếu bạn đã sử dụng tRPC nhưng vẫn còn mơ hồ về cách nó hoạt động. -## How do I call my API externally? +## Làm sao để gọi API từ bên ngoài? -With regular APIs, you can call your endpoints using any HTTP client such as `curl`, `Postman`, `fetch` or straight from your browser. With tRPC, it's a bit different. If you want to call your procedures without the tRPC client, there are two recommended ways to do it: +Với các API thông thường, bạn có thể gọi các endpoint của mình bằng bất kỳ HTTP client nào như `curl`, `Postman`, `fetch` hoặc trực tiếp từ trình duyệt của bạn. Với tRPC, điều này hơi khác. Nếu bạn muốn gọi các procedures mà không cần sử dụng client tRPC, có hai cách được khuyến nghị: -### Expose a single procedure externally +### Khởi tạo một external procedure -If you want to expose a single procedure externally, you're looking for [server side calls](https://trpc.io/docs/server/server-side-calls). That would allow you to create a normal Next.js API endpoint, but reuse the resolver part of your tRPC procedure. +Nếu bạn muốn khởi tạo một procedure mà bạn có thể gọi từ bên ngoài, bạn có thể đang tìm kiếm [server side calls](https://trpc.io/docs/server/server-side-calls). Điều này sẽ cho phép bạn tạo một endpoint Next.js thông thường, nhưng sử dụng phần resolver của procedure tRPC của bạn. ```ts:pages/api/users/[id].ts import { type NextApiRequest, type NextApiResponse } from "next"; @@ -181,7 +181,7 @@ import { appRouter, createCaller } from "../../../server/api/root"; import { createTRPCContext } from "../../../server/api/trpc"; const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => { - // Create context and caller + // Tạo context và caller const ctx = await createTRPCContext({ req, res }); const caller = createCaller(ctx); try { @@ -190,30 +190,30 @@ const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => { res.status(200).json(user); } catch (cause) { if (cause instanceof TRPCError) { - // An error from tRPC occurred + // Một lỗi tRPC đã xảy ra const httpCode = getHTTPStatusCodeFromError(cause); return res.status(httpCode).json(cause); } - // Another error occurred + // Một lỗi khác đã xảy ra console.error(cause); - res.status(500).json({ message: "Internal server error" }); + res.status(500).json({ message: "Lỗi máy chủ nội bộ" }); } }; export default userByIdHandler; ``` -### Exposing every procedure as a REST endpoint +### Khởi tạo tất cả các procedures như các REST endpoints -If you want to expose every single procedure externally, checkout the community built plugin [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). By providing some extra meta-data to your procedures, you can generate an OpenAPI compliant REST API from your tRPC router. +Nếu bạn muốn khởi tạo tất cả các procedures mà bạn có thể gọi từ bên ngoài, bạn có thê tham khảo các plugins xây dựng bởi cộng đồng [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). Bằng cách cung cấp một số thông tin meta-data cho các procedures của bạn, bạn có thể tạo ra một API REST tương thích với OpenAPI từ router tRPC của bạn. -### It's just HTTP Requests +### Đây chỉ là các HTTP Requests -tRPC communicates over HTTP, so it is also possible to call your tRPC procedures using "regular" HTTP requests. However, the syntax can be cumbersome due to the [RPC protocol](https://trpc.io/docs/rpc) that tRPC uses. If you're curious, you can check what tRPC requests and responses look like in your browser's network tab, but we suggest doing this only as an educational exercise and sticking to one of the solutions outlined above. +tRPC sử dụng giao thức HTTP, vì vậy bạn đều có thể gọi các procedures của tRPC bằng các HTTP requests thông thường. Tuy nhiên, cú pháp có thể khá phức tạp do tRPC sử dụng [kiểu định nghĩa giao thức RPC](https://trpc.io/docs/rpc) riêng biệt. Nếu bạn muốn tìm hiểu, bạn có thể kiểm tra các request và responses của tRPC trong tab mạng của trình duyệt của bạn, nhưng chúng tôi khuyến khích bạn nên làm điều này với mục đích học hỏi và sử dụng một trong các giải pháp được đề cập ở trên. -## Comparison to a Next.js API endpoint +## So sánh với Next.js API endpoint -Let's compare a Next.js API endpoint to a tRPC procedure. Let's say we want to fetch a user object from our database and return it to the frontend. We could write a Next.js API endpoint like this: +Hãy so sánh một endpoint Next.js API với một procedure tRPC. Ví dụ chúng ta muốn lấy một đối tượng user từ cơ sở dữ liệu và trả nó cho frontend. Chúng ta có thể viết một endpoint Next.js API như sau: ```ts:pages/api/users/[id].ts import { type NextApiRequest, type NextApiResponse } from "next"; @@ -259,21 +259,21 @@ const UserPage = () => { }; ``` -Compare this to the tRPC example above and you can see some of the advantages of tRPC: +So sánh với ví dụ tRPC ở trên và bạn có thể thấy một số lợi ích của tRPC: -- Instead of specifying a url for each route, which can become annoying to debug if you move something, your entire router is an object with autocomplete. -- You don’t need to validate which HTTP method was used. -- You don’t need to validate that the request query or body contains the correct data in the procedure, because Zod takes care of this. -- Instead of creating a response, you can throw errors and return a value or object as you would in any other TypeScript function. -- Calling the procedure on the frontend provides autocompletion and type safety. +- Thay vì phải tạo ra một URL cho mỗi route, điều này có thể trở nên khó khăn khi gỡ lỗi nếu bạn chuyển đổi điều gì đó, với tRPC, router của bạn là một đối tượng với autocomplete. +- Bạn không cần phải xác định phương thức HTTP nào đã được sử dụng. +- Bạn không cần phải xác định rằng request query hoặc body chứa dữ liệu đúng, vì Zod sẽ xử lý điều này. +- Thay vì tạo ra một response, bạn có thể throws lỗi và trả về một giá trị hoặc đối tượng như bạn làm trong bất kỳ hàm TypeScript nào khác. +- Gọi procedure ở phía frontend sẽ cung cấp đầy đủ autocompletion và tính toàn vẹn kiểu dữ liệu. -## Useful snippets +## Các snippet hữu ích -Here are some snippets that might come in handy. +Dưới đây là một số snippet mà có thể hữu ích cho bạn. -### Enabling CORS +### Sử dụng CORS -If you need to consume your API from a different domain, for example in a monorepo that includes a React Native app, you might need to enable CORS: +Nếu bạn cần sử dụng API của bạn từ một domain khác, ví dụ như trong một monorepo bao gồm một app React Native, bạn có thể cần phải sử dụng CORS: ```ts:pages/api/trpc/[trpc].ts import { type NextApiRequest, type NextApiResponse } from "next"; @@ -283,10 +283,10 @@ import { createTRPCContext } from "~/server/api/trpc"; import cors from "nextjs-cors"; const handler = async (req: NextApiRequest, res: NextApiResponse) => { - // Enable cors + // Sử dụng CORS await cors(req, res); - // Create and call the tRPC handler + // Tạo và gọi handler tRPC return createNextApiHandler({ router: appRouter, createContext: createTRPCContext, @@ -296,9 +296,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { export default handler; ``` -### Optimistic updates +### Cập nhật tối ưu (Optimistic updates) -Optimistic updates are when we update the UI before the API call has finished. This gives the user a better experience because they don't have to wait for the API call to finish before the UI reflects the result of their action. However, apps that value data correctness highly should avoid optimistic updates as they are not a "true" representation of backend state. You can read more on the [React Query docs](https://tanstack.com/query/latest/docs/framework/react/guides/optimistic-updates). +Cập nhật tối ưu (optimistic updates) là khi chúng ta cập nhật UI trước khi cuộc gọi API hoàn tất. Điều này cho phép người dùng có trải nghiệm tốt hơn vì họ không phải chờ cuộc gọi API hoàn tất trước khi UI phản ánh kết quả hành động của họ. Tuy nhiên, các ứng dụng có giá trị dữ liệu chính xác cao nên tránh sử dụng cập nhật tối ưu vì chúng không biểu hiện của trạng thái backend. Bạn có thể đọc thêm trên [tài liệu của React Query](https://tanstack.com/query/latest/docs/framework/react/guides/optimistic-updates). ```tsx const MyComponent = () => { @@ -307,33 +307,33 @@ const MyComponent = () => { const utils = api.useUtils(); const postCreate = api.post.create.useMutation({ async onMutate(newPost) { - // Cancel outgoing fetches (so they don't overwrite our optimistic update) + // Hủy bỏ cuộc gọi API (để chúng không ghi đè lên cập nhật tối ưu của chúng ta) await utils.post.list.cancel(); - // Get the data from the queryCache + // Lấy dữ liệu từ cache const prevData = utils.post.list.getData(); - // Optimistically update the data with our new post + // Cập nhật dữ liệu tối ưu với bài viết mới utils.post.list.setData(undefined, (old) => [...old, newPost]); - // Return the previous data so we can revert if something goes wrong + // Trả về dữ liệu trước đó để chúng ta có thể quay lại nó nếu điều gì đó sai return { prevData }; }, onError(err, newPost, ctx) { - // If the mutation fails, use the context-value from onMutate + // Nếu cuộc gọi mutation thất bại, sử dụng giá trị từ onMutate utils.post.list.setData(undefined, ctx.prevData); }, onSettled() { - // Sync with server once mutation has settled + // Đồng bộ với server một lần mutation đã hoàn tất utils.post.list.invalidate(); }, }); }; ``` -### Sample Integration Test +### Ví dụ về tích hợp kiểm thử -Here is a sample integration test that uses [Vitest](https://vitest.dev) to check that your tRPC router is working as expected, the input parser infers the correct type, and that the returned data matches the expected output. +Dưới đây là một ví dụ về kiểm thử sử dụng [Vitest](https://vitest.dev) để kiểm tra xem router tRPC của bạn đang hoạt động như mong đợi, phân tích kiểu đầu vào đúng, và dữ liệu trả về phù hợp với kỳ vọng. ```ts import { type inferProcedureInput } from "@trpc/server"; @@ -357,7 +357,7 @@ test("example router", async () => { }); ``` -If your procedure is protected, you can pass in a mocked `session` object when you create the context: +Nếu procedure của bạn được bảo vệ, bạn có thể truyền vào một đối tượng `session` giả khi bạn tạo context: ```ts test("protected example router", async () => { @@ -373,10 +373,10 @@ test("protected example router", async () => { }); ``` -## Useful Resources +## Tài liệu hữu ích -| Resource | Link | -| ---------------------- | ----------------------------------------------- | -| tRPC Docs | https://www.trpc.io | -| Bunch of tRPC Examples | https://github.com/trpc/trpc/tree/next/examples | -| React Query Docs | https://tanstack.com/query/latest/docs | +| Tài liệu | Đường dẫn | +| -------------------- | ----------------------------------------------- | +| Tài liệu tRPC | https://www.trpc.io | +| Ví dụ về tRPC | https://github.com/trpc/trpc/tree/next/examples | +| Tài liệu React Query | https://tanstack.com/query/latest/docs | From a9cd4eb91b77fb0e757a82704376dd3445fae20f Mon Sep 17 00:00:00 2001 From: Simon Nguyen <80842534+cobeo2004@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:46:06 +1000 Subject: [PATCH 12/12] docs(vi): Update Vietnamese for Next Auth usage (both page and app router) pages and fix tailwind pages. Ready to be review >.< --- .../pages/vi/usage/_next-auth-app-router.mdx | 126 +++++++++--------- www/src/pages/vi/usage/_next-auth-pages.mdx | 88 ++++++------ www/src/pages/vi/usage/next-auth.mdx | 4 +- www/src/pages/vi/usage/tailwind.md | 2 +- 4 files changed, 111 insertions(+), 109 deletions(-) diff --git a/www/src/pages/vi/usage/_next-auth-app-router.mdx b/www/src/pages/vi/usage/_next-auth-app-router.mdx index b610105d13..4b51fe17a3 100644 --- a/www/src/pages/vi/usage/_next-auth-app-router.mdx +++ b/www/src/pages/vi/usage/_next-auth-app-router.mdx @@ -2,12 +2,12 @@ import Callout from "../../../components/docs/callout.tsx"; import Tabs from "../../../components/docs/tabs.astro"; - The newest version of NextAuth has migrated to [Auth.js](https://authjs.dev/) + Phiên bản mới nhất của NextAuth đã chuyển sang [Auth.js](https://authjs.dev/) -## Retrieving session server side +## Lấy dữ liệu phiên từ phía server -Sometimes you might want to request the session on the server. To do so, use the `auth` helper function that `create-t3-app` provides. +Đôi khi bạn có thể muốn lấy dữ liệu phiên trên server. Để làm điều đó, sử dụng hàm trợ giúp `auth` mà `create-t3-app` cung cấp. ```tsx:app/page.tsx import { auth } from "~/server/auth"; @@ -18,9 +18,9 @@ export default async function Home() { } ``` -## Inclusion of `user.id` on the Session +## Thêm `user.id` vào phiên -Create T3 App is configured to utilise the [session callback](https://authjs.dev/guides/extending-the-session) in the NextAuth.js config to include the user's ID within the `session` object. +Create T3 App đã thiết lập sẵn [session callback](https://authjs.dev/guides/extending-the-session) trong cấu hình NextAuth.js để bao gồm ID của người dùng trong đối tượng `session`. ```ts:server/auth/config.ts callbacks: { @@ -34,7 +34,7 @@ callbacks: { }, ``` -This is coupled with a type declaration file to make sure the `user.id` is typed when accessed on the `session` object. Read more about [`Module Augmentation`](https://authjs.dev/getting-started/typescript#resources*module-augmentation) on NextAuth.js's docs. +Và đông thời `user.id` cũng đã được khai báo thông qua một file định kiểu để đảm bảo rằng `user.id` được định kiểu rõ ràng khi truy cập vào đối tượng `session`. Đọc thêm về [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) trên tài liệu của NextAuth.js. ```ts:server/auth/config.ts import { DefaultSession } from "next-auth"; @@ -47,15 +47,15 @@ declare module "next-auth" { } ``` -The same pattern can be used to add any other data to the `session` object, such as a `role` field, but **should not be misused to store sensitive data** on the client. +Bước này có thể áp dụng để thêm bất kỳ dữ liệu nào khác vào đối tượng `session`, chẳng hạn như trường `role`, nhưng **không nên được sử dụng để lưu trữ dữ liệu nhạy cảm trên client**. ## Usage with tRPC -When using NextAuth.js with tRPC, you can create reusable, protected procedures using [middleware](https://trpc.io/docs/v10/middlewares). This allows you to create procedures that can only be accessed by authenticated users. `create-t3-app` sets all of this up for you, allowing you to easily access the session object within authenticated procedures. +Khi sử dụng NextAuth.js với tRPC, bạn có thể tạo và tái sử dụng các procedures được bảo vệ kỹ càng bằng cách sử dụng [middleware](https://trpc.io/docs/v10/middlewares). Điều này cho phép bạn tạo ra các procedure mà chỉ có thể được dùng bởi người dùng đã đăng nhập. `create-t3-app` đã thiết lập tất cả điều này cho bạn, cho phép bạn dễ dàng truy cập vào đối tượng phiên (session object) trong các procedures được bảo vệ. -This is done in a two step process: +Điều này có thể được thực hiện qua hai bước: -1. Pass the authentication session into the tRPC context: +1. Thêm phiên xác thực vào context của tRPC: ```ts:server/api/trpc.ts import { auth } from "~/server/auth"; @@ -72,7 +72,7 @@ export const createTRPCContext = async (opts: { headers: Headers }) => { }; ``` -2. Create a tRPC middleware that checks if the user is authenticated. We then use the middleware in a `protectedProcedure`. Any caller to these procedures must be authenticated, or else an error will be thrown which can be appropriately handled by the client. +2. Tạo một tRPC middleware kiểm tra xem người dùng có được xác thực hay không. Sau đó, sử dụng middleware này trong `protectedProcedure`. Bất kỳ caller nào gọi đến các procedure này phải được xác thực, nếu không caller đó sẽ bị báo lỗi mà client có thể dùng để xử lý (ví dụ: hiển thị một trang đăng nhập). ```ts:server/api/trpc.ts export const protectedProcedure = t.procedure @@ -88,7 +88,7 @@ export const protectedProcedure = t.procedure }); ``` -The session object is a light, minimal representation of the user and only contains a few fields. When using the `protectedProcedures`, you have access to the user's id which can be used to fetch more data from the database. +Dữ liệu phiên ở đây là một sự biểu diễn tối giản và gọn nhẹ của người dùng và chỉ chứa một số trường. Khi sử dụng `protectedProcedures`, bạn có thể truy cập để lấy ID của người dùng để đạt được nhiều mục đích khác nhau, ví dụ như sử dụng ID để lấy thêm dữ liệu từ cơ sở dữ liệu. ```ts:server/api/routers/user.ts const userRouter = router({ @@ -103,44 +103,47 @@ const userRouter = router({ }); ``` -## Usage with a database provider +## Sử dụng với các Database Providers
- Getting NextAuth.js to work with Prisma requires a lot of [initial - setup](https://authjs.dev/reference/adapter/prisma/). `create-t3-app` - handles all of this for you, and if you select both Prisma and NextAuth.js, - you'll get a fully working authentication system with all the required - models preconfigured. We ship your scaffolded app with a preconfigured - Discord OAuth provider, which we chose because it is one of the easiest to - get started with - just provide your tokens in the `.env` and you're good to - go. However, you can easily add more providers by following the [Auth.js - docs](https://authjs.dev/getting-started/authentication/oauth). Note that - certain providers require extra fields to be added to certain models. We - recommend you read the documentation for the provider you would like to use - to make sure you have all the required fields. + Để NextAuth.js có thể hoạt động với Prisma, bạn cần phải chuẩn bị khá nhiều + thủ tục [thiết lập ban đầu](https://authjs.dev/reference/adapter/prisma/). + Tuy nhiên, `create-t3-app` đã làm tất cả những điều này cho bạn. Nếu bạn + chọn cả Prisma và NextAuth.js khi khởi tạo dự án, bạn sẽ có ngay một hệ + thống xác thực hoàn chỉnh với tất cả các model cần thiết đã được cấu hình + sẵn. Ứng dụng mẫu mà chúng tôi cung cấp sẽ được cấu hình sẵn với nhà cung + cấp Discord OAuth, vì đây là một trong những provider dễ bắt đầu nhất – bạn + chỉ cần thêm các token vào file `.env` là có thể sử dụng ngay. Tuy nhiên, + bạn cũng có thể dễ dàng thêm các provider khác bằng cách làm theo [tài liệu + của NextAuth.js](https://next-auth.js.org/providers/). Lưu ý rằng một số + provider sẽ yêu cầu bạn thêm các trường bổ sung vào một số model nhất định. + Chúng tôi khuyến nghị bạn nên đọc kỹ tài liệu của provider mà bạn muốn sử + dụng để đảm bảo rằng bạn đã thêm đầy đủ các trường cần thiết.
- Getting NextAuth.js to work with Drizzle requires a lot of [initial - setup](https://authjs.dev/getting-started/adapters/drizzle). `create-t3-app` - handles all of this for you, and if you select both Drizzle and NextAuth.js, - you'll get a fully working authentication system with all the required - models preconfigured. We ship your scaffolded app with a preconfigured - Discord OAuth provider, which we chose because it is one of the easiest to - get started with - just provide your tokens in the `.env` and you're good to - go. However, you can easily add more providers by following the [Auth.js - docs](https://authjs.dev/getting-started/authentication/oauth). Note that - certain providers require extra fields to be added to certain models. We - recommend you read the documentation for the provider you would like to use - to make sure you have all the required fields. + Để NextAuth.js có thể hoạt động với Drizzle, bạn cần phải chuẩn bị khá nhiều + thủ tục [thiết lập ban + đầu](https://authjs.dev/getting-started/adapters/drizzle). Tuy nhiên, + `create-t3-app` đã làm tất cả những điều này cho bạn. Nếu bạn chọn cả + Drizzle và NextAuth.js khi khởi tạo dự án, bạn sẽ có ngay một hệ thống xác + thực hoàn chỉnh với tất cả các model cần thiết đã được cấu hình sẵn. Ứng + dụng mẫu mà chúng tôi cung cấp sẽ được cấu hình sẵn với nhà cung cấp Discord + OAuth, vì đây là một trong những provider dễ bắt đầu nhất – bạn chỉ cần thêm + các token vào file `.env` là có thể sử dụng ngay. Tuy nhiên, bạn cũng có thể + dễ dàng thêm các provider khác bằng cách làm theo [tài liệu của + Auth.js](https://authjs.dev/getting-started/authentication/oauth). Lưu ý + rằng một số provider sẽ yêu cầu bạn thêm các trường bổ sung vào một số model + nhất định. Chúng tôi khuyến nghị bạn nên đọc kỹ tài liệu của provider mà bạn + muốn sử dụng để đảm bảo rằng bạn đã thêm đầy đủ các trường cần thiết.
-### Adding new fields to your models +### Thêm các trường mới vào model của bạn -When adding new fields to any of the `User`, `Account`, `Session`, or `VerificationToken` models (most likely you'd only need to modify the `User` model), you need to keep in mind that the [Prisma adapter](https://authjs.dev/reference/adapter/prisma/) automatically creates fields on these models when new users sign up and log in. Therefore, when adding new fields to these models, you must provide default values for them, since the adapter is not aware of these fields. +Khi thêm các trường mới vào bất kỳ model nào trong số `User`, `Account`, `Session`, or `VerificationToken` (đa số bạn chỉ cần sửa đổi model `User`), bạn cần lưu ý rằng [Prisma adapter](https://next-auth.js.org/adapters/prisma) tự động tạo các trường trên các model này khi người dùng mới đăng ký và đăng nhập. Do đó, khi thêm các trường mới vào các model này, bạn phải cung cấp giá trị mặc định cho chúng, vì adapter sẽ không thể nhận ra các trường này. -If for example, you'd like to add a `role` to the `User` model, you would need to provide a default value to the `role` field. This is done by adding a `@default` value to the `role` field in the `User` model: +Nếu bạn muốn thêm một trường `role` vào model `User`, bạn cần cung cấp một giá trị mặc định cho trường `role`. Điều này được thực hiện bằng cách thêm `@default` vào trường `role` trong model `User`: ```diff:prisma/schema.prisma + enum Role { @@ -154,15 +157,15 @@ If for example, you'd like to add a `role` to the `User` model, you would need t } ``` -## Usage with Next.js middleware +## Sử dụng với Next.js middleware -With Next.js 12+, the easiest way to protect a set of pages is using the [middleware file](https://authjs.dev/getting-started/session-management/protecting?framework=express#nextjs-middleware). You can create a middleware.ts file in your root pages directory with the following contents. +Với Next.js 12+, cách dễ nhất để bảo vệ các trang trong ứng dụng của bạn là sử dụng [middleware file](https://authjs.dev/getting-started/session-management/protecting?framework=express#nextjs-middleware). Bạn có thể tạo một file middleware.ts trong thư mục root của pages (hoặc app nếu bạn dùng App Router) với nội dung sau: ```middleware.ts export { auth as middleware } from "@/auth" ``` -Then define authorized callback in your auth.ts file. For more details check out the [reference docs.](https://authjs.dev/reference/nextjs#authorized) +Sau đó, định nghĩa các callback bảo vệ trong file auth.ts của bạn. Để biết thêm chi tiết, hãy xem [tài liệu tham khảo](https://authjs.dev/reference/nextjs#authorized). ```app/auth.ts async authorized({ request, auth }) { @@ -170,37 +173,38 @@ async authorized({ request, auth }) { if(request.method === "POST") { const { authToken } = (await request.json()) ?? {} - // If the request has a valid auth token, it is authorized + // Nếu yêu cầu có một token xác thực hợp lệ, nó được xác thực const valid = await validateAuthToken(authToken) if(valid) return true return NextResponse.json("Invalid auth token", { status: 401 }) } - // Logged in users are authenticated, otherwise redirect to login page + // Chỉ các người dùng đã đăng nhập mới được quyền vào, nếu không hãy chuyển hướng đến trang đăng nhập return !!auth.user } ``` - You should not rely on middleware exclusively for authorization. Always ensure - that the session is verified as close to your data fetching as possible. + Bạn không nên chỉ dựa vào middleware để kiểm soát quyền truy cập. Hãy luôn đảm + bảo rằng phiên đăng nhập (session) được xác thực càng gần với nơi lấy dữ liệu + càng tốt. -## Setting up the default DiscordProvider +## Thiết lập Discord Provider mặc định -1. Head to [the Applications section in the Discord Developer Portal](https://discord.com/developers/applications), and click on "New Application" -2. In the settings menu, go to "OAuth2 => General" +1. Đi đến [phần Applications trong Discord Developer Portal](https://discord.com/developers/applications), và click vào "New Application" +2. Trong menu settings, đi đến "OAuth2 => General" -- Copy the Client ID and paste it in `DISCORD_CLIENT_ID` in `.env`. -- Under Client Secret, click "Reset Secret" and copy that string to `DISCORD_CLIENT_SECRET` in `.env`. Be careful as you won't be able to see this secret again, and resetting it will cause the existing one to expire. -- Click "Add Redirect" and paste in `/api/auth/callback/discord` (example for local development: http://localhost:3000/api/auth/callback/discord) -- Save your changes -- It is possible, but not recommended, to use the same Discord Application for both development and production. You could also consider [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) during development. +- Copy Client ID và dán nó vào `DISCORD_CLIENT_ID` trong `.env`. +- Dưới Client Secret, click "Reset Secret" và copy chuỗi đó vào `DISCORD_CLIENT_SECRET` trong `.env`. Cẩn thận vì bạn sẽ không thể nhìn thấy chuỗi này lại nữa, và đặt lại nó sẽ làm cho chuỗi hiện tại hết hạn. +- Click "Add Redirect" và dán vào `/api/auth/callback/discord` (ví dụ cho phát triển local: http://localhost:3000/api/auth/callback/discord) +- Lưu thay đổi của bạn +- Có thể, nhưng không được khuyến nghị, là sử dụng cùng một ứng dụng Discord cho cả phát triển và sản phẩm. Bạn cũng có thể xem xét [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) trong quá trình phát triển. -## Useful Resources +## Tài liệu hữu ích -| Resource | Link | -| --------------------------------- | --------------------------------------- | -| NextAuth.js Docs | https://authjs.dev/ | -| NextAuth.js GitHub | https://github.com/nextauthjs/next-auth | -| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth | +| Tài liệu | Đường dẫn | +| ------------------------------------ | --------------------------------------- | +| Tài liệu NextAuth.js | https://authjs.dev/ | +| GitHub của NextAuth.js | https://github.com/nextauthjs/next-auth | +| tRPC Kitchen Sink - sử dụng NextAuth | https://kitchen-sink.trpc.io/next-auth | diff --git a/www/src/pages/vi/usage/_next-auth-pages.mdx b/www/src/pages/vi/usage/_next-auth-pages.mdx index 7d21099805..f804750822 100644 --- a/www/src/pages/vi/usage/_next-auth-pages.mdx +++ b/www/src/pages/vi/usage/_next-auth-pages.mdx @@ -2,7 +2,7 @@ import Callout from "../../../components/docs/callout.tsx"; ## Context Provider -In your app's entrypoint, you'll see that your application is wrapped in a [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider): +Trong điểm bắt đầu (entrypoint) của ứng dụng của bạn, bạn sẽ thấy rằng toàn bộ ứng dụng của bạn được bọc bởi một lớp [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider): ```tsx:pages/_app.tsx @@ -10,7 +10,7 @@ In your app's entrypoint, you'll see that your application is wrapped in a [Sess ``` -This context provider allows your application to access the session data from anywhere in your application, without having to pass it down as props: +Lớp context provider này cho phép ứng dụng của bạn truy cập dữ liệu phiên (session) từ bất cứ đâu trong ứng dụng của bạn, mà không cần phải truyền nó xuống như là props: ```tsx:pages/users/[id].tsx import { useSession } from "next-auth/react"; @@ -19,7 +19,7 @@ const User = () => { const { data: session } = useSession(); if (!session) { - // Handle unauthenticated state, e.g. render a SignIn component + // Xử lý khi không có phiên hợp lí, ví dụ: hiển thị một component SignIn return ; } @@ -27,9 +27,9 @@ const User = () => { }; ``` -## Retrieving session server-side +## Lấy dữ liệu phiên ở phía server -Sometimes you might want to request the session on the server. To do so, prefetch the session using the `getServerAuthSession` helper function that `create-t3-app` provides, and pass it down to the client using `getServerSideProps`: +Đôi khi bạn có thể muốn lấy dữ liệu phiên đăng nhập ở phía server. Để làm điều đó, hãy sử dụng hàm `getServerAuthSession` mà `create-t3-app` cung cấp, và truyền nó xuống cho client sử dụng thông qua `getServerSideProps`: ```tsx:pages/users/[id].tsx import { getServerAuthSession } from "../server/auth"; @@ -44,15 +44,15 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { const User = () => { const { data: session } = useSession(); - // NOTE: `session` wont have a loading state since it's already prefetched on the server + // NOTE: `session` sẽ không có trạng thái loading vì nó đã được lấy trước ở phía server ... } ``` -## Inclusion of `user.id` on the Session +## Thêm `user.id` vào trong phiên -Create T3 App is configured to utilise the [session callback](https://next-auth.js.org/configuration/callbacks#session-callback) in the NextAuth.js config to include the user's ID within the `session` object. +Create T3 App đã thiết lập sẵn [session callback](https://next-auth.js.org/configuration/callbacks#session-callback) trong cấu hình NextAuth.js để bao gồm luôn ID của người dùng trong đối tượng `session`. ```ts:server/auth.ts callbacks: { @@ -65,7 +65,7 @@ callbacks: { }, ``` -This is coupled with a type declaration file to make sure the `user.id` is typed when accessed on the `session` object. Read more about [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) on NextAuth.js's docs. +Và đông thời `user.id` cũng đã được khai báo thông qua một file định kiểu để đảm bảo rằng `user.id` được định kiểu rõ ràng khi truy cập vào đối tượng `session`. Đọc thêm về [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) trên tài liệu của NextAuth.js. ```ts:server/auth.ts import { DefaultSession } from "next-auth"; @@ -79,15 +79,15 @@ declare module "next-auth" { } ``` -The same pattern can be used to add any other data to the `session` object, such as a `role` field, but **should not be misused to store sensitive data** on the client. +Bước này có thể áp dụng để thêm bất kỳ dữ liệu nào khác vào đối tượng `session`, chẳng hạn như trường `role`, nhưng **không nên được sử dụng để lưu trữ dữ liệu nhạy cảm trên client**. -## Usage with tRPC +## Sử dụng với tRPC -When using NextAuth.js with tRPC, you can create reusable, protected procedures using [middleware](https://trpc.io/docs/v10/middlewares). This allows you to create procedures that can only be accessed by authenticated users. `create-t3-app` sets all of this up for you, allowing you to easily access the session object within authenticated procedures. +Khi sử dụng NextAuth.js với tRPC, bạn có thể tạo và tái sử dụng các procedures được bảo vệ kỹ càng bằng cách sử dụng [middleware](https://trpc.io/docs/v10/middlewares). Điều này cho phép bạn tạo ra các procedure mà chỉ có thể được dùng bởi người dùng đã đăng nhập. `create-t3-app` đã thiết lập tất cả điều này cho bạn, cho phép bạn dễ dàng truy cập vào đối tượng phiên (session object) trong các procedures được bảo vệ. -This is done in a two step process: +Điều này có thể được thực hiện qua hai bước: -1. Grab the session from the request headers using the [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession) function. The advantage of using `getServerSession` instead of the regular `getSession` is that it's a server-side only function and doesn't trigger unnecessary fetch calls. `create-t3-app` creates a helper function that abstracts this peculiar API away so that you don't need to import both your NextAuth.js options as well as the `getServerSession` function every time you need to access the session. +1. Lấy session từ request headers thông qua hàm [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession). Lợi thế của việc sử dụng `getServerSession` thay vì `getSession` là nó là một hàm chỉ thực thi ở phía server và không gây ra các cuộc gọi fetch không cần thiết. `create-t3-app` tạo ra một hàm trợ giúp để tóm tắt API này, để bạn không cần phải nhập cả hai tùy chọn NextAuth.js cũng như hàm `getServerSession` mỗi khi cần truy cập vào phiên. ```ts:server/auth.ts export const getServerAuthSession = (ctx: { @@ -98,7 +98,7 @@ export const getServerAuthSession = (ctx: { }; ``` -Using this helper function, we can grab the session and pass it through to the tRPC context: +Bằng cách sử dụng hàm trợ giúp này, chúng ta có thể lấy phiên và truyền nó vào context của tRPC: ```ts:server/api/trpc.ts import { getServerAuthSession } from "../auth"; @@ -112,7 +112,7 @@ export const createContext = async (opts: CreateNextContextOptions) => { }; ``` -2. Create a tRPC middleware that checks if the user is authenticated. We then use the middleware in a `protectedProcedure`. Any caller to these procedures must be authenticated, or else an error will be thrown which can be appropriately handled by the client. +2. Tạo một tRPC middleware để kiểm tra xem người dùng có được xác thực hay không. Sau đó, chúng ta sử dụng middleware này trong một `protectedProcedure`. Bất kỳ caller nào gọi đến các procedure này phải được xác thực, nếu không caller đó sẽ bị báo lỗi mà client có thể dùng để xử lý (ví dụ: hiển thị một trang đăng nhập). ```ts:server/api/trpc.ts export const protectedProcedure = t.procedure.use(({ ctx, next }) => { @@ -121,14 +121,14 @@ export const protectedProcedure = t.procedure.use(({ ctx, next }) => { } return next({ ctx: { - // infers the `session` as non-nullable + // Session phải được đảm bảo là không null session: { ...ctx.session, user: ctx.session.user }, }, }); }) ``` -The session object is a light, minimal representation of the user and only contains a few fields. When using the `protectedProcedures`, you have access to the user's id which can be used to fetch more data from the database. +Dữ liệu phiên ở đây là một sự biểu diễn tối giản và gọn nhẹ của người dùng và chỉ chứa một số trường. Khi sử dụng `protectedProcedures`, bạn có thể truy cập để lấy ID của người dùng để đạt được nhiều mục đích khác nhau, ví dụ như sử dụng ID để lấy thêm dữ liệu từ cơ sở dữ liệu. ```ts:server/api/routers/user.ts const userRouter = router({ @@ -143,15 +143,15 @@ const userRouter = router({ }); ``` -## Usage with Prisma +## Sử dụng với Prisma -Getting NextAuth.js to work with Prisma requires a lot of [initial setup](https://authjs.dev/reference/adapter/prisma/). `create-t3-app` handles all of this for you, and if you select both Prisma and NextAuth.js, you'll get a fully working authentication system with all the required models preconfigured. We ship your scaffolded app with a preconfigured Discord OAuth provider, which we chose because it is one of the easiest to get started with - just provide your tokens in the `.env` and you're good to go. However, you can easily add more providers by following the [NextAuth.js docs](https://next-auth.js.org/providers/). Note that certain providers require extra fields to be added to certain models. We recommend you read the documentation for the provider you would like to use to make sure you have all the required fields. +Để NextAuth.js có thể hoạt động với Prisma, bạn cần phải chuẩn bị khá nhiều thủ tục [thiết lập ban đầu](https://authjs.dev/reference/adapter/prisma/). Tuy nhiên, `create-t3-app` đã làm tất cả những điều này cho bạn. Nếu bạn chọn cả Prisma và NextAuth.js khi khởi tạo dự án, bạn sẽ có ngay một hệ thống xác thực hoàn chỉnh với tất cả các model cần thiết đã được cấu hình sẵn. Ứng dụng mẫu mà chúng tôi cung cấp sẽ được cấu hình sẵn với nhà cung cấp Discord OAuth, vì đây là một trong những provider dễ bắt đầu nhất – bạn chỉ cần thêm các token vào file `.env` là có thể sử dụng ngay. Tuy nhiên, bạn cũng có thể dễ dàng thêm các provider khác bằng cách làm theo [tài liệu của NextAuth.js](https://next-auth.js.org/providers/). Lưu ý rằng một số provider sẽ yêu cầu bạn thêm các trường bổ sung vào một số model nhất định. Chúng tôi khuyến nghị bạn nên đọc kỹ tài liệu của provider mà bạn muốn sử dụng để đảm bảo rằng bạn đã thêm đầy đủ các trường cần thiết. -### Adding new fields to your models +### Thêm các trường mới vào model của bạn -When adding new fields to any of the `User`, `Account`, `Session`, or `VerificationToken` models (most likely you'd only need to modify the `User` model), you need to keep in mind that the [Prisma adapter](https://next-auth.js.org/adapters/prisma) automatically creates fields on these models when new users sign up and log in. Therefore, when adding new fields to these models, you must provide default values for them, since the adapter is not aware of these fields. +Khi thêm các trường mới vào bất kỳ model nào trong số `User`, `Account`, `Session`, or `VerificationToken` (đa số bạn chỉ cần sửa đổi model `User`), bạn cần lưu ý rằng [Prisma adapter](https://next-auth.js.org/adapters/prisma) tự động tạo các trường trên các model này khi người dùng mới đăng ký và đăng nhập. Do đó, khi thêm các trường mới vào các model này, bạn phải cung cấp giá trị mặc định cho chúng, vì adapter sẽ không thể nhận ra các trường này. -If for example, you'd like to add a `role` to the `User` model, you would need to provide a default value to the `role` field. This is done by adding a `@default` value to the `role` field in the `User` model: +Nếu bạn muốn thêm một trường `role` vào model `User`, bạn cần cung cấp một giá trị mặc định cho trường `role`. Điều này được thực hiện bằng cách thêm `@default` vào trường `role` trong model `User`: ```diff:prisma/schema.prisma + enum Role { @@ -165,19 +165,17 @@ If for example, you'd like to add a `role` to the `User` model, you would need t } ``` -## Usage with Next.js middleware +## Sử dụng với Next.js middleware -Usage of NextAuth.js with Next.js middleware [requires the use of the JWT session strategy](https://next-auth.js.org/configuration/nextjs#caveats) for authentication. This is because the middleware is only able to access the session cookie if it is a JWT. By default, Create T3 App is configured to use the **default** database strategy, in combination with Prisma as the database adapter. +Để sử dụng NextAuth.js với Next.js middleware, bạn cần sử dụng [xác thực phiên bằng JWT](https://next-auth.js.org/configuration/nextjs#caveats) cho xác thực. Điều này là do middleware chỉ có thể truy cập cookie phiên nếu nó là JWT. Theo mặc định, Create T3 App được cấu hình để sử dụng chiến lược **default**, kết hợp với Prisma làm adapter lưu trữ phiên trong cơ sở dữ liệu. - Using database sessions is the recommended approach and you should read up on - JWTs before switching to the JWT session strategy to avoid any security - issues. + Lưu trữ phiên bằng cơ sở dữ liệu là cách tiếp cận được khuyến nghị và bạn nên + đọc thêm về JWTs trước khi chuyển sang xác thực phiên bằng JWT để tránh bất kỳ + vấn đề bảo mật nào. -After switching to the JWT session strategy. Make sure to update the `session` callback in `src/server/auth.ts`. -The `user` object will be `undefined`. Instead, retrieve the user's ID from the `token` object. -I.e.: +Sau khi chuyển sang chiến lược phiên bằng JWT, hãy đảm bảo cập nhật callback `session` trong `src/server/auth.ts`. Đối tượng `user` sẽ là `undefined`. Thay vào đó, hãy lấy ID của người dùng thông qua đối tượng `token`. Ví dụ: ```diff:server/auth.ts export const authOptions: NextAuthOptions = { @@ -198,21 +196,21 @@ I.e.: } ``` -## Setting up the default DiscordProvider +## Thiết lập Discord Provider mặc định -1. Head to [the Applications section in the Discord Developer Portal](https://discord.com/developers/applications), and click on "New Application" -2. In the settings menu, go to "OAuth2 => General" +1. Đi đến [phần Applications trong Discord Developer Portal](https://discord.com/developers/applications), và click vào "New Application" +2. Trong menu settings, đi đến "OAuth2 => General" -- Copy the Client ID and paste it in `DISCORD_CLIENT_ID` in `.env`. -- Under Client Secret, click "Reset Secret" and copy that string to `DISCORD_CLIENT_SECRET` in `.env`. Be careful as you won't be able to see this secret again, and resetting it will cause the existing one to expire. -- Click "Add Redirect" and paste in `/api/auth/callback/discord` (example for local development: http://localhost:3000/api/auth/callback/discord) -- Save your changes -- It is possible, but not recommended, to use the same Discord Application for both development and production. You could also consider [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) during development. +- Copy Client ID và dán nó vào `DISCORD_CLIENT_ID` trong `.env`. +- Dưới Client Secret, click "Reset Secret" và copy chuỗi đó vào `DISCORD_CLIENT_SECRET` trong `.env`. Cẩn thận vì bạn sẽ không thể nhìn thấy chuỗi này lại nữa, và đặt lại nó sẽ làm cho chuỗi hiện tại hết hạn. +- Click "Add Redirect" và dán vào `/api/auth/callback/discord` (ví dụ cho phát triển local: http://localhost:3000/api/auth/callback/discord) +- Lưu thay đổi của bạn +- Có thể, nhưng không được khuyến nghị, là sử dụng cùng một ứng dụng Discord cho cả phát triển và sản phẩm. Bạn cũng có thể xem xét [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) trong quá trình phát triển. -## Useful Resources +## Tài liệu hữu ích -| Resource | Link | -| --------------------------------- | --------------------------------------- | -| NextAuth.js Docs | https://next-auth.js.org/ | -| NextAuth.js GitHub | https://github.com/nextauthjs/next-auth | -| tRPC Kitchen Sink - with NextAuth | https://kitchen-sink.trpc.io/next-auth | +| Tài liệu | Đường dẫn | +| ------------------------------------ | --------------------------------------- | +| Tài liệu NextAuth.js | https://next-auth.js.org/ | +| GitHub của NextAuth.js | https://github.com/nextauthjs/next-auth | +| tRPC Kitchen Sink - sử dụng NextAuth | https://kitchen-sink.trpc.io/next-auth | diff --git a/www/src/pages/vi/usage/next-auth.mdx b/www/src/pages/vi/usage/next-auth.mdx index ed45f346e1..70702398c3 100644 --- a/www/src/pages/vi/usage/next-auth.mdx +++ b/www/src/pages/vi/usage/next-auth.mdx @@ -1,6 +1,6 @@ --- title: NextAuth.js -description: Usage of NextAuth.js +description: Sử dụng NextAuth.js layout: ../../../layouts/docs.astro lang: vi isMdx: true @@ -10,7 +10,7 @@ import Tabs from "../../../components/docs/tabs.astro"; import AppRouter from "./_next-auth-app-router.mdx"; import Pages from "./_next-auth-pages.mdx"; -When you want an authentication system in your Next.js application, NextAuth.js is an excellent solution to bring in the complexity of security without the hassle of having to build it yourself. It comes with an extensive list of providers to quickly add OAuth authentication and provides adapters for many databases and ORMs. +Khi bạn muốn có cho mình một hệ thống xác thực hoàn thiện trong ứng dụng Next.js của bạn, NextAuth.js là một giải pháp tuyệt vời để mang đến sự phức tạp của bảo mật mà không cần tốn quá nhiều công sức để xây dựng. Nó cung cấp danh sách các nhà cung cấp bảo mật thứ 3 để thêm xác thực OAuth nhanh chóng và cung cấp các adapter dành cho nhiều cơ sở dữ liệu và ORM khác nhau. diff --git a/www/src/pages/vi/usage/tailwind.md b/www/src/pages/vi/usage/tailwind.md index 779fd37720..22902ab2e0 100644 --- a/www/src/pages/vi/usage/tailwind.md +++ b/www/src/pages/vi/usage/tailwind.md @@ -66,7 +66,7 @@ Tru Narla, hay được biết đến dưới tên một người dùng Twitter Hãy đảm bảo rằng bạn đã cài đặt các plugin editor cho Tailwind CSS để cải thiện trải nghiệm viết Tailwind CSS. -### Extensions and Plugins +### Extensions và Plugins - [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) - [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)