Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Feat: enable i18n #367

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions LangPath.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"en":["/book/cs/_meta.en.json","/book/cs/from-func.en.mdx","/book/cs/from-solidity.en.mdx","/book/guides/getting-started/_meta.en.json","/book/guides/getting-started/deploy.en.mdx","/book/guides/getting-started/first.en.mdx","/book/guides/getting-started/test.en.mdx","/book/guides/_meta.en.json","/book/guides/getting-started.en.mdx","/book/_meta.en.json","/book/bounced.en.mdx","/book/cells.en.mdx","/book/config.en.mdx","/book/constants.en.mdx","/book/contracts.en.mdx","/book/debug.en.mdx","/book/deploy.en.mdx","/book/exit-codes.en.mdx","/book/expressions.en.mdx","/book/external.en.mdx","/book/func.en.mdx","/book/functions.en.mdx","/book/import.en.mdx","/book/index.en.mdx","/book/integers.en.mdx","/book/lifecycle.en.mdx","/book/maps.en.mdx","/book/masterchain.en.mdx","/book/message-mode.en.mdx","/book/operators.en.mdx","/book/optionals.en.mdx","/book/programmatic.en.mdx","/book/receive.en.mdx","/book/send.en.mdx","/book/statements.en.mdx","/book/structs-and-messages.en.mdx","/book/types.en.mdx","/book/upgrades.en.mdx","/cookbook/dexes/_meta.en.json","/cookbook/dexes/dedust.en.mdx","/cookbook/dexes/stonfi.en.mdx","/cookbook/_meta.en.json","/cookbook/access.en.mdx","/cookbook/algo.en.mdx","/cookbook/data-structures.en.mdx","/cookbook/index.en.mdx","/cookbook/jettons.en.mdx","/cookbook/misc.en.mdx","/cookbook/multi-communication.en.mdx","/cookbook/nfts.en.mdx","/cookbook/random.en.mdx","/cookbook/single-communication.en.mdx","/cookbook/time.en.mdx","/cookbook/type-conversion.en.mdx","/ecosystem/tools/_meta.en.json","/ecosystem/tools/jetbrains.en.mdx","/ecosystem/tools/overview.en.mdx","/ecosystem/tools/typescript.en.mdx","/ecosystem/tools/vscode.en.mdx","/ecosystem/_meta.en.json","/ecosystem/index.en.mdx","/ref/evolution/OTP-001.en.mdx","/ref/evolution/OTP-002.en.mdx","/ref/evolution/OTP-003.en.mdx","/ref/evolution/OTP-004.en.mdx","/ref/evolution/OTP-005.en.mdx","/ref/evolution/OTP-006.en.mdx","/ref/evolution/_meta.en.json","/ref/evolution/overview.en.mdx","/ref/_meta.en.json","/ref/core-advanced.en.mdx","/ref/core-base.en.mdx","/ref/core-cells.en.mdx","/ref/core-common.en.mdx","/ref/core-comptime.en.mdx","/ref/core-debug.en.mdx","/ref/core-math.en.mdx","/ref/core-random.en.mdx","/ref/core-strings.en.mdx","/ref/index.en.mdx","/ref/spec.en.mdx","/ref/standard-libraries.en.mdx","/ref/stdlib-config.en.mdx","/ref/stdlib-content.en.mdx","/ref/stdlib-deploy.en.mdx","/ref/stdlib-dns.en.mdx","/ref/stdlib-ownable.en.mdx","/ref/stdlib-stoppable.en.mdx","/_meta.en.json","/index.en.mdx"],"zh-CN":["/_meta.zh-CN.json","/index.zh-CN.mdx"]}
7 changes: 7 additions & 0 deletions crowdin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
project_id: "674258"
api_token_env: CROWDIN_PERSONAL_TOKEN
preserve_hierarchy: true
files:
- source: /pages/**/*.en.*
translation: /pages/**/%file_name%.%two_letters_code%.%file_extension%
"translation_replace": { ".en": "" }
133 changes: 133 additions & 0 deletions locales.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { addBasePath } from "next/dist/client/add-base-path";
import { addLocale } from "next/dist/client/add-locale";
import { hasBasePath } from "next/dist/client/has-base-path";
import { removeBasePath } from "next/dist/client/remove-base-path";
import { removeLocale } from "next/dist/client/remove-locale";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";

import LangPath from "./LangPath.json";

type langKeys = "en" | "zh-CN";

type LegacyMiddlewareCookies = Record<string, string>;
type StableMiddlewareCookies = Map<string, string>;
type Next13MiddlewareCookies = NextRequest["cookies"];

function getCookie(
cookies:
| LegacyMiddlewareCookies
| StableMiddlewareCookies
| Next13MiddlewareCookies,
key: string
): string | undefined {
if (typeof cookies.get === "function") {
const cookie = cookies.get(key);
if (cookie && typeof cookie === "object") {
return cookie.value;
}
return cookie as any;
}
return (cookies as LegacyMiddlewareCookies)[key];
}

export function locales(request: NextRequest) {
const { nextUrl } = request;

if (/\/_meta(\.[a-z]{2}-[A-Z]{2})?$/.test(nextUrl.pathname)) {
const url = nextUrl.clone();
url.pathname = `/404`;

return NextResponse.rewrite(url);
}

const rootDirArray = ["/book", "/ecosystem", "/cookbook", "/ref"];

const shouldHandleLocale =
!/^\/(api|_next)\//.test(nextUrl.pathname) &&
!/\.(jpe?g|svg|png|webmanifest|xml|ico|txt|mp4)$/.test(nextUrl.pathname) &&
nextUrl.locale !== "" &&
// not Server-Side Error page
nextUrl.pathname !== "/500";

if (!shouldHandleLocale) return;

// The locale code prefixed in the current URL, which can be empty.
const locale = nextUrl.locale === nextUrl.defaultLocale ? "" : nextUrl.locale;

// pathname for default locale doesn't contain basePath and locale segment
nextUrl.pathname = hasBasePath(nextUrl.pathname)
? removeLocale(removeBasePath(nextUrl.pathname), nextUrl.locale)
: nextUrl.pathname;

let finalLocale;

if (locale) {
// If a locale is explicitly set, we don't do any modifications.
finalLocale = locale;
} else {
// If there is a locale cookie, we try to use it. If it doesn't exist, or
// it's invalid, `nextUrl.locale` will be automatically figured out by Next
// via the `accept-languages` header.
const clientLocale = getCookie(request.cookies, "NEXT_LOCALE");
if (clientLocale) {
try {
nextUrl.locale = clientLocale;
} catch {
// The locale from the cookie isn't valid.
// https://github.com/vercel/next.js/blob/e5dee17f776dcc79ebb269f7b7341fa6e2b6c3f1/packages/next/server/web/next-url.ts#L122-L129
}
}
finalLocale = nextUrl.locale;

// Now we want to display the locale. If it's not the default one, we have
// to prefix the URL with that locale since it's missing. Only the default
// locale can be missing from there for consistency.
if (finalLocale !== nextUrl.defaultLocale) {
const url = addBasePath(
addLocale(
`${nextUrl.pathname}${nextUrl.search}`,
finalLocale,
nextUrl.defaultLocale
)
);

return NextResponse.redirect(new URL(url, request.url));
}
}
let pathname = nextUrl.pathname || "/";
if (pathname === "/") pathname += "index";
else if (pathname.endsWith("/")) pathname = pathname.slice(0, -1);

const isValidRoute = LangPath[finalLocale].includes(
`${
rootDirArray?.includes(pathname) ? pathname + "/index" : pathname
}.${finalLocale}.mdx`
);

// If we are not showing the correct localed page, rewrite the current request.
if (!pathname.endsWith("." + finalLocale)) {
let url = addBasePath(
addLocale(
`${
rootDirArray?.includes(pathname) ? pathname + "/index" : pathname
}.${finalLocale}${nextUrl.search}`,
finalLocale,
nextUrl.defaultLocale
)
);

if (!isValidRoute)
url = url
.replace(`/${finalLocale}`, "")
.replace(`${finalLocale}`, nextUrl.defaultLocale);

return NextResponse.rewrite(new URL(url, request.url));
}
}

export function withLocales(middleware: any) {
return (...args: any[]) => {
return locales(args[0]) || middleware(...args);
};
}
1 change: 1 addition & 0 deletions middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { locales as middleware } from "./locales";
sansx marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 5 additions & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,14 @@ const withNextra = nextra({
* @type {import('next').NextConfig}
*/
export default withNextra({
output: 'export',
images: {
unoptimized: true
},
i18n: {
locales: ["en", "zh-CN"],
defaultLocale: "en",
localeDetection: false,
},
// i18n: {
// // locales: ['default', 'en', 'zh'],
// locales: ['default', 'en'],
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
"scripts": {
"clean": "rm -fr .next out",
"deps": "yarn install --frozen-lockfile",
"dev": "yarn deps && yarn clean && next",
"build": "yarn deps && yarn clean && next build",
"dev": "node ./scripts/I18nPathJson-generate.js && yarn deps && yarn clean && next",
"build": "node ./scripts/I18nPathJson-generate.js && yarn deps && yarn clean && next build",
"post-build": "echo 'spell checking, link checking, formatting'",
"build-pages": "yarn build && node ./scripts/redirects-generate.js",
"build-pages": "node ./scripts/I18nPathJson-generate.js && yarn build && next export && node ./scripts/redirects-generate.js",
"next": "next",
"spell": "cspell \"**\""
},
Expand Down
26 changes: 26 additions & 0 deletions pages/_meta.en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"index": {
"title": "Tact Documentation",
"type": "page",
"display": "hidden",
"theme": {
"typesetting": "article"
}
},
"book": {
"title": "Book",
"type": "page"
},
"cookbook": {
"title": "Cookbook",
"type": "page"
},
"ref": {
"title": "Reference",
"type": "page"
},
"ecosystem": {
"title": "Ecosystem",
"type": "page"
}
}
26 changes: 0 additions & 26 deletions pages/_meta.js

This file was deleted.

26 changes: 26 additions & 0 deletions pages/_meta.zh-CN.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"index": {
"title": "Tact Documentation",
"type": "page",
"display": "hidden",
"theme": {
"typesetting": "article"
}
},
"book": {
"title": "Book",
"type": "page"
},
"cookbook": {
"title": "Cookbook",
"type": "page"
},
"ref": {
"title": "Reference",
"type": "page"
},
"ecosystem": {
"title": "Ecosystem",
"type": "page"
}
}
61 changes: 61 additions & 0 deletions pages/book/_meta.en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"index": "Overview",
"guides": "Guides",
"cs": "Cheatsheets",
"-- 1": {
"type": "separator",
"title": "Fundamentals of Tact"
},
"types": "Type system overview",
"integers": "Integers",
"cells": "Cells, Builders and Slices",
"maps": "Maps",
"structs-and-messages": "Structs and Messages",
"optionals": "Optionals",
"contracts": "Contracts",
"exit-codes": "Exit codes",
"-- 2": {
"type": "separator",
"title": "Expressiveness"
},
"operators": "Operators",
"expressions": "Expressions",
"statements": "Statements",
"constants": "Constants",
"functions": "Functions",
"-- 3": {
"type": "separator",
"title": "Communication"
},
"receive": "Receive messages",
"bounced": "Bounced messages",
"external": "External messages",
"lifecycle": "Message lifecycle",
"send": "Sending messages",
"message-mode": "Message mode",
"-- 4": {
"type": "separator",
"title": "Going places"
},
"deploy": "Deployment",
"debug": "Debugging",
"upgrades": "Contract upgrades",
"import": "Importing code",
"config": "Configuration",
"masterchain": "Masterchain",
"func": "Compatibility with FunC",
"programmatic": "Programmatic API",
"-- Community": {
"type": "separator"
},
"telegram-link": {
"title": "✈️ Telegram",
"href": "https://t.me/tactlang",
"newWindow": true
},
"xtwitter-link": {
"title": "🐦 X/Twitter",
"href": "https://twitter.com/tact_language",
"newWindow": true
}
}
64 changes: 0 additions & 64 deletions pages/book/_meta.js

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions pages/book/cs/_meta.en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"from-func": "Coming from FunC",
"from-solidity": "Coming from Solidity"
}
4 changes: 0 additions & 4 deletions pages/book/cs/_meta.js

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 3 additions & 0 deletions pages/book/guides/_meta.en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"getting-started": "Getting started"
}
Loading
Loading