Skip to content

Commit

Permalink
feat(i18n): added i18n
Browse files Browse the repository at this point in the history
  • Loading branch information
Giacomo Materozzi committed Mar 5, 2024
1 parent beacf3b commit c61373b
Show file tree
Hide file tree
Showing 16 changed files with 286 additions and 63 deletions.
7 changes: 6 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,9 @@ STRIPE_PRO_MONTHLY_PLAN_ID=
# -----------------------------------------------------------------------------
# OpenAI
# -----------------------------------------------------------------------------
OPEN_AI_API_KEY=test
OPEN_AI_API_KEY=test

# -----------------------------------------------------------------------------
# I18n
# -----------------------------------------------------------------------------
TRANSLO_I18N_BASE_URL=https://translo.app/
7 changes: 6 additions & 1 deletion .env.github
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,9 @@ STRIPE_PRO_MONTHLY_PLAN_ID=test
# -----------------------------------------------------------------------------
# OpenAI
# -----------------------------------------------------------------------------
OPEN_AI_API_KEY=test
OPEN_AI_API_KEY=test

# -----------------------------------------------------------------------------
# I18n
# -----------------------------------------------------------------------------
TRANSLO_I18N_BASE_URL=https://translo.app/
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,11 @@ stripe login
```sh
pnpm run stripe:webhook
```

## Update i18n

Set the base URL of Translo in the `TRANSLO_I18N_BASE_URL` environment

```sh
pnpm run i18n
```
3 changes: 2 additions & 1 deletion app/(marketing)/pricing/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Link from "next/link"

import i18n from "@/lib/i18n"
import { cn } from "@/lib/utils"
import { buttonVariants } from "@/components/ui/button"
import { Icons } from "@/components/icons"
Expand Down Expand Up @@ -54,7 +55,7 @@ export default function PricingPage() {
</p>
</div>
<Link href="/login" className={cn(buttonVariants({ size: "lg" }))}>
Get Started
{i18n.t("app.Get started")}
</Link>
</div>
</div>
Expand Down
3 changes: 3 additions & 0 deletions app/client-providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import { ChakraProvider } from "@chakra-ui/react"
import { SessionProvider } from "next-auth/react"
import { QueryClient, QueryClientProvider } from "react-query"

import i18n from "@/lib/i18n"

export default function RootLayout(props: { children: React.ReactNode }) {
i18n.changeLanguage("en")
const [queryClient] = useState(() => new QueryClient())

return (
Expand Down
1 change: 1 addition & 0 deletions commitizen.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const scopesValues = [
"landing",
"subscription",
"user",
"i18n",
].sort((prev, next) => {
if (prev > next) {
return 1
Expand Down
4 changes: 3 additions & 1 deletion components/app/homepage/get-started.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import i18n from "@/lib/i18n"

const GetStarterd = () => {
return (
<div className="text-center">
<a
className="py-3 px-4 inline-flex justify-center items-center gap-x-2 text-sm font-semibold rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600"
href="/register"
>
Get started
{i18n.t("app.Get started")}
<svg
className="shrink-0 size-4"
xmlns="http://www.w3.org/2000/svg"
Expand Down
2 changes: 2 additions & 0 deletions env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const env = createEnv({
MAIL_SMTP_PASSWORD: z.string().min(1),
MAIL_SMTP_FROM: z.string().min(1),
OPEN_AI_API_KEY: z.string().min(1),
TRANSLO_I18N_BASE_URL: z.string().optional(),
},
client: {
NEXT_PUBLIC_APP_URL: z.string().min(1),
Expand All @@ -39,5 +40,6 @@ export const env = createEnv({
STRIPE_PRO_MONTHLY_PLAN_ID: process.env.STRIPE_PRO_MONTHLY_PLAN_ID,
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
OPEN_AI_API_KEY: process.env.OPEN_AI_API_KEY,
TRANSLO_I18N_BASE_URL: process.env.TRANSLO_I18N_BASE_URL,
},
})
50 changes: 50 additions & 0 deletions lib/i18n/import.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import fs from "fs"
import path from "path"
import util from "util"

import { languagesSupported } from "./index"

require("dotenv").config()

const pWriteFile = util.promisify(fs.writeFile)

const saveFileToFileSystem = async (fileUrl, filePath) => {
try {
const response = await fetch(fileUrl)
if (!response.ok) {
throw new Error("Failed to download file")
}

const json = await response.text()
await pWriteFile(filePath, JSON.stringify(JSON.parse(json), null, 4), {
encoding: "utf-8",
})
} catch (error) {
fs.unlink(filePath, () => {}) // Delete the file if an error occurs
}
}

/**
* Main entry points that executes all the functions
*/
const doWork = async () => {
await Promise.all(
languagesSupported.map((lang) => {
const root = path.join(__dirname, "..")
const filePath = path.join(root, "i18n", "languages", `${lang}.json`)

// eslint-disable-next-line no-console
console.log(`prepare ${lang}...`)

return saveFileToFileSystem(
`${process.env.TRANSLO_I18N_BASE_URL}/${lang}.json`,
filePath
)
})
)

// eslint-disable-next-line no-console
console.log("all languages imported.")
}

doWork()
44 changes: 44 additions & 0 deletions lib/i18n/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import i18next from "i18next"

import translationEN from "./languages/en.json"
import translationES from "./languages/es.json"
import translationIT from "./languages/it.json"

export const languagesSupported = ["en", "es", "it"]

export const defaultLanguage = "en"

i18next.init({
resources: {
en: {
translation: translationEN,
},
es: {
translation: translationES,
},
it: {
translation: translationIT,
},
},
lng: defaultLanguage,
debug: false,
interpolation: {
escapeValue: false,
},
nsSeparator: false,
keySeparator: false,
fallbackLng: false,
})

export type I18nKey = keyof typeof translationEN

export default {
changeLanguage: (lang: string) => {
if (!languagesSupported.includes(lang)) {
throw "Language not found"
}

i18next.changeLanguage(lang)
},
t: (key: I18nKey) => i18next.t(key),
}
3 changes: 3 additions & 0 deletions lib/i18n/languages/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app.Get started": "Get started"
}
3 changes: 3 additions & 0 deletions lib/i18n/languages/es.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app.Get started": "Comienza ahora"
}
3 changes: 3 additions & 0 deletions lib/i18n/languages/it.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app.Get started": "Inizia ora"
}
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"prisma:migrate:dev": "pnpm prisma format & pnpm dotenv -e .env.local pnpm prisma generate && pnpm dotenv -e .env.local pnpm prisma migrate dev --create-only && pnpm prisma:generate",
"prisma:studio": "pnpm prisma:generate && BROWSER=none pnpm dotenv -e .env.local pnpm prisma studio",
"prisma:generate": "pnpm dotenv -e .env.local pnpm prisma format && pnpm prisma generate",
"stripe:webhook": "stripe listen --forward-to localhost:3000/api/webhooks/stripe"
"stripe:webhook": "stripe listen --forward-to localhost:3000/api/webhooks/stripe",
"i18n": "pnpm dotenv -e .env.local npx ts-node lib/i18n/import.ts"
},
"dependencies": {
"@chakra-ui/react": "^2.8.2",
Expand Down Expand Up @@ -73,6 +74,8 @@
"dotenv-cli": "^7.3.0",
"flowbite": "^2.3.0",
"framer-motion": "^11.0.5",
"i18next": "^23.10.0",
"i18next-resources-to-backend": "^1.2.0",
"lucide-react": "^0.92.0",
"next": "13.3.2-canary.13",
"next-auth": "4.22.1",
Expand All @@ -87,6 +90,7 @@
"react-dom": "^18.2.0",
"react-editor-js": "^2.1.0",
"react-hook-form": "^7.43.9",
"react-i18next": "^14.0.5",
"react-icons": "^5.0.1",
"react-query": "^3.39.3",
"react-textarea-autosize": "^8.4.1",
Expand Down Expand Up @@ -118,6 +122,7 @@
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-tailwindcss": "^3.11.0",
"fs": "0.0.1-security",
"git-precommit-checks": "^3.1.0",
"husky": "^8.0.3",
"mdast-util-toc": "^6.1.1",
Expand All @@ -133,6 +138,7 @@
"remark": "^14.0.2",
"remark-gfm": "^3.0.1",
"tailwindcss": "^3.3.1",
"ts-node": "^10.9.2",
"typescript": "4.7.4",
"unist-util-visit": "^4.1.2"
},
Expand Down
Loading

0 comments on commit c61373b

Please sign in to comment.