diff --git a/website/src/components/templates/BaseTemplate.tsx b/website/src/components/templates/BaseTemplate.tsx index c6f1d7f393..0ca8b22aca 100644 --- a/website/src/components/templates/BaseTemplate.tsx +++ b/website/src/components/templates/BaseTemplate.tsx @@ -1,7 +1,7 @@ import { html } from "hono/html"; import type { FC, PropsWithChildren } from "hono/jsx"; import { basePath, originUrl, typstOfficialDocsUrl } from "../../metadata"; -import { Translation, translation } from "../../translation"; +import { Translation, translation } from "../../translation/"; import type { Page } from "../../types/model"; import { joinPath, removeBasePath } from "../../utils/path"; import { getTranslationStatus } from "../../utils/translationStatus"; diff --git a/website/src/components/templates/CategoryTemplate.tsx b/website/src/components/templates/CategoryTemplate.tsx index 5eeafda15f..9d53269ae1 100644 --- a/website/src/components/templates/CategoryTemplate.tsx +++ b/website/src/components/templates/CategoryTemplate.tsx @@ -1,5 +1,5 @@ import type { FC } from "hono/jsx"; -import { Translation } from "../../translation"; +import { Translation } from "../../translation/"; import type { CategoryBody, Page } from "../../types/model"; import { HtmlContent } from "../ui/HtmlContent"; import BaseTemplate, { type BaseTemplateProps } from "./BaseTemplate"; diff --git a/website/src/components/templates/FuncTemplate.tsx b/website/src/components/templates/FuncTemplate.tsx index 807d966d23..e2aae8cb5c 100644 --- a/website/src/components/templates/FuncTemplate.tsx +++ b/website/src/components/templates/FuncTemplate.tsx @@ -1,5 +1,5 @@ import type { FC } from "hono/jsx"; -import { Translation } from "../../translation"; +import { Translation } from "../../translation/"; import type { Func, FuncBody, Page } from "../../types/model"; import { FunctionDefinition, diff --git a/website/src/components/templates/TypeTemplate.tsx b/website/src/components/templates/TypeTemplate.tsx index 50a9a11a78..60a943d2c9 100644 --- a/website/src/components/templates/TypeTemplate.tsx +++ b/website/src/components/templates/TypeTemplate.tsx @@ -1,5 +1,5 @@ import type { FC } from "hono/jsx"; -import { Translation } from "../../translation"; +import { Translation } from "../../translation/"; import type { Page, TypeBody } from "../../types/model"; import { FunctionDisplay, Tooltip } from "../ui"; import { HtmlContent } from "../ui/HtmlContent"; diff --git a/website/src/components/ui/FunctionDisplay.tsx b/website/src/components/ui/FunctionDisplay.tsx index c884644147..9ae1ae7012 100644 --- a/website/src/components/ui/FunctionDisplay.tsx +++ b/website/src/components/ui/FunctionDisplay.tsx @@ -1,5 +1,5 @@ import type { FC } from "hono/jsx"; -import { Translation } from "../../translation"; +import { Translation } from "../../translation/"; import type { Func } from "../../types/model"; import { ChevronRightIcon } from "../icons"; import { FunctionDefinition } from "./FunctionDefinition"; diff --git a/website/src/components/ui/FunctionParameters.tsx b/website/src/components/ui/FunctionParameters.tsx index fead4c3600..88e164d789 100644 --- a/website/src/components/ui/FunctionParameters.tsx +++ b/website/src/components/ui/FunctionParameters.tsx @@ -1,6 +1,6 @@ import type { FC } from "hono/jsx"; import { basePath } from "../../metadata"; -import { Translation } from "../../translation"; +import { Translation } from "../../translation/"; import type { Func } from "../../types/model"; import { joinPath } from "../../utils/path"; import { ChevronRightIcon } from "../icons"; diff --git a/website/src/components/ui/Tooltip.tsx b/website/src/components/ui/Tooltip.tsx index 37a50ac2cc..be6dc8d4e0 100644 --- a/website/src/components/ui/Tooltip.tsx +++ b/website/src/components/ui/Tooltip.tsx @@ -1,5 +1,5 @@ import type { FC } from "hono/jsx"; -import { Translation, translation } from "../../translation"; +import { Translation, translation } from "../../translation/"; import { CloseIcon, HelpCircleIcon } from "../icons"; export type TooltipProps = { diff --git a/website/src/components/ui/common/Footer.tsx b/website/src/components/ui/common/Footer.tsx index ed4a081926..c783e96dcf 100644 --- a/website/src/components/ui/common/Footer.tsx +++ b/website/src/components/ui/common/Footer.tsx @@ -3,6 +3,7 @@ import { githubOrganizationUrl, githubRepositoryUrl, } from "../../../metadata"; +import { Translation } from "../../../translation/"; import { DiscordIcon, GitHubIcon } from "../../icons"; export const Footer = () => { @@ -32,13 +33,7 @@ export const Footer = () => {

- Translated by{" "} - - Typst Japanese Community - +

diff --git a/website/src/components/ui/common/Header.tsx b/website/src/components/ui/common/Header.tsx index 58bf5a27b4..85424867a3 100644 --- a/website/src/components/ui/common/Header.tsx +++ b/website/src/components/ui/common/Header.tsx @@ -5,7 +5,7 @@ import { typstOfficialUrl, version, } from "../../../metadata"; -import { Translation, translation } from "../../../translation"; +import { Translation, translation } from "../../../translation/"; import { calculateTranslationProgressRate } from "../../../utils/translationStatus"; import { DiscordIcon, diff --git a/website/src/components/ui/common/SearchWindow.tsx b/website/src/components/ui/common/SearchWindow.tsx index 06723eaa0d..d1384add4c 100644 --- a/website/src/components/ui/common/SearchWindow.tsx +++ b/website/src/components/ui/common/SearchWindow.tsx @@ -1,6 +1,6 @@ import type { FC } from "hono/jsx"; import { basePath } from "../../../metadata"; -import { Translation, translation } from "../../../translation"; +import { Translation, translation } from "../../../translation/"; import { joinPath } from "../../../utils/path"; import { CloseIcon } from "../../icons"; diff --git a/website/src/components/ui/common/SiteNoticeBanner.tsx b/website/src/components/ui/common/SiteNoticeBanner.tsx index 028e8761f2..23361797dc 100644 --- a/website/src/components/ui/common/SiteNoticeBanner.tsx +++ b/website/src/components/ui/common/SiteNoticeBanner.tsx @@ -1,4 +1,4 @@ -import { Translation } from "../../../translation"; +import { Translation } from "../../../translation/"; import { InfoCircleIcon } from "../../icons"; export const SiteNoticeBanner = () => { diff --git a/website/src/components/ui/common/SiteTitle.tsx b/website/src/components/ui/common/SiteTitle.tsx index 0777caf424..c104ffc703 100644 --- a/website/src/components/ui/common/SiteTitle.tsx +++ b/website/src/components/ui/common/SiteTitle.tsx @@ -1,5 +1,5 @@ import { basePath } from "../../../metadata"; -import { Translation } from "../../../translation"; +import { Translation } from "../../../translation/"; export const SiteTitle = () => { return ( diff --git a/website/src/components/ui/common/TableOfContents.tsx b/website/src/components/ui/common/TableOfContents.tsx index c3eb4ff0c1..7e80280972 100644 --- a/website/src/components/ui/common/TableOfContents.tsx +++ b/website/src/components/ui/common/TableOfContents.tsx @@ -1,4 +1,4 @@ -import { Translation } from "../../../translation"; +import { Translation } from "../../../translation/"; import type { OutlineItem } from "../../../types/model"; export type TableOfContentsProps = { diff --git a/website/src/components/ui/common/TranslationStatusAlert.tsx b/website/src/components/ui/common/TranslationStatusAlert.tsx index 22797993ab..8f457a6eab 100644 --- a/website/src/components/ui/common/TranslationStatusAlert.tsx +++ b/website/src/components/ui/common/TranslationStatusAlert.tsx @@ -1,6 +1,6 @@ import type { FC } from "hono/jsx"; import { twMerge } from "tailwind-merge"; -import { Translation } from "../../../translation"; +import { Translation } from "../../../translation/"; import type { TranslationStatus } from "../../../utils/translationStatus"; import { LanguageIcon } from "../../icons"; diff --git a/website/src/translation/en-US.tsx b/website/src/translation/en-US.tsx new file mode 100644 index 0000000000..65fe5b7164 --- /dev/null +++ b/website/src/translation/en-US.tsx @@ -0,0 +1,205 @@ +import type { TooltipProps } from "../components/ui/Tooltip"; +import { githubOrganizationUrl } from "../metadata"; +import type { TranslationComponent, TranslationObject } from "./"; + +export const translation: TranslationObject = { + htmlLang: () => "en", + documentationTitle: () => "Typst Documentation (English)", + close: () => "Close", + closeMenu: () => "Close menu", + closeSearch: () => "Close search", + openMenu: () => "Open menu", + openSearch: () => "Open search", + showInformation: (props: { name: string }) => + `Show details for ${props.name}`, + tooltipKind: (props: { kind: TooltipProps["kind"] }) => { + switch (props.kind) { + case "element": + return "Element"; + case "contextual": + return "Contextual"; + case "definitions": + return "Definition"; + case "parameters": + return "Parameter"; + case "variadic": + return "Variadic"; + case "settable": + return "Settable"; + case "positional": + return "Positional"; + case "required": + return "Required"; + default: + return props.kind; + } + }, +} as const; + +export const Translation: TranslationComponent = (props) => { + switch (props.translationKey) { + case "definition": + return <>Definition; + case "constructor": + return <>Constructor; + case "definitionOf": + return ( + <> + {props.name} Definition + + ); + case "search": + return <>Search; + case "defaultValue": + return <>Default value:; + case "stringValues": + return <>Available string values:; + case "showExample": + return <>Show example; + case "tableOfContents": + return <>On this page; + case "nextPage": + return <>Next page; + case "previousPage": + return <>Previous page; + case "referenceDescription": + return ( + <> + Detailed reference for all Typst syntax, concepts, types, and + functions. + + ); + case "tutorialDescription": + return <>Learn how to use Typst step by step.; + case "tutorial": + return <>Tutorial; + case "openOfficialDocs": + return <>Open official docs; + case "reference": + return <>Reference; + case "typstOfficialDocs": + return <>Typst official docs; + case "typstOfficialWebsite": + return <>Typst official website; + case "untranslated": + return <>Untranslated; + case "untranslatedMessage": + return ( + <> + This page has not been translated yet. The original content is shown. + + ); + case "communityContent": + return <>Community original content; + case "contentAddedByCommunity": + return ( + <> + This page contains content that is not part of the official + documentation, added independently by the community. + + ); + case "partiallyTranslated": + return <>Partially translated; + case "partiallyTranslatedMessage": + return ( + <> + This page is partially translated. Some original content is included. + + ); + case "translated": + return <>Translated; + case "translatedMessage": + return <>This page has been translated into English.; + case "elementFunction": + return <>Element; + case "elementFunctionDescription": + return ( + <> + Element functions can be customized with set and{" "} + show rules. + + ); + case "contextFunction": + return <>Context; + case "contextFunctionDescription": + return <>Context functions can only be used when the context is known.; + case "definitionTooltip": + return <>Definition; + case "definitionTooltipDescription": + return ( + <> + These functions and types can have related definitions. To access a + definition, specify the name of the function or type, followed by the + definition name separated by a period. + + ); + case "argument": + return <>Parameter; + case "argumentDescription": + return ( + <> + Parameters are input values for functions. Specify them in parentheses + after the function name. + + ); + case "variadic": + return <>Variadic; + case "variadicDescription": + return <>Variadic parameters can be specified multiple times.; + case "positional": + return <>Positional; + case "positionalDescription": + return ( + <> + Positional parameters can be set by specifying them in order, omitting + the parameter name. + + ); + case "required": + return <>Required; + case "requiredDescription": + return ( + <>Required parameters must be specified when calling the function. + ); + case "document": + return <>Document; + case "langVersion": + return <>English; + case "translationRate": + return <>Translated; + case "settable": + return <>Settable; + case "settableDescription": + return ( + <> + Settable parameters can be set using the set rule, + changing the default value used thereafter. + + ); + case "siteNoticeBannerTitle": + return <>Info; + case "siteNoticeBannerDescription": + return ( + <> + This site is generated using the static site generator developed by + the Typst Community. + Please adjust the text content of this banner according to your usage + requirements. At Typst GmbH's request, when publishing documentation, + you must clearly indicate that it is non-official and display the + version of Typst being documented. For details, refer to{" "} + + Issue #874 on typst/typst + + . + + ); + case "footer": + return ( + <> + Translated by Typst Community + + ); + default: + return null; + } +}; diff --git a/website/src/translation/index.tsx b/website/src/translation/index.tsx new file mode 100644 index 0000000000..a724f67c88 --- /dev/null +++ b/website/src/translation/index.tsx @@ -0,0 +1,86 @@ +import type { FC } from "hono/jsx"; +import type { TooltipProps } from "../components/ui/Tooltip"; + +/** + * Translation dictionary for UI attributes and aria labels. + * + * @example + * translation.closeMenu() + * translation.showInformation({ name: "foo" }) + */ +export type TranslationObject = { + htmlLang: () => string; + documentationTitle: () => string; + close: () => string; + closeMenu: () => string; + closeSearch: () => string; + openMenu: () => string; + openSearch: () => string; + showInformation: (props: { name: string }) => string; + tooltipKind: (props: { kind: TooltipProps["kind"] }) => string; +}; + +type TranslationComponentKey = + | "definition" + | "constructor" + | "tableOfContents" + | "untranslated" + | "untranslatedMessage" + | "document" + | "langVersion" + | "elementFunction" + | "elementFunctionDescription" + | "contextFunction" + | "contextFunctionDescription" + | "definitionTooltip" + | "definitionTooltipDescription" + | "variadic" + | "translationRate" + | "variadicDescription" + | "typstOfficialDocs" + | "typstOfficialWebsite" + | "communityContent" + | "contentAddedByCommunity" + | "partiallyTranslated" + | "partiallyTranslatedMessage" + | "translated" + | "translatedMessage" + | "siteNoticeBannerTitle" + | "siteNoticeBannerDescription" + | "tutorial" + | "tutorialDescription" + | "referenceDescription" + | "reference" + | "openOfficialDocs" + | "search" + | "argument" + | "argumentDescription" + | "required" + | "requiredDescription" + | "positional" + | "positionalDescription" + | "defaultValue" + | "stringValues" + | "showExample" + | "settable" + | "settableDescription" + | "previousPage" + | "nextPage" + | "footer"; + +export type TranslationComponentProps = + | { translationKey: TranslationComponentKey } + | { translationKey: "definitionOf"; name: string }; + +/** + * Translation component for UI text, descriptions, and other content to be embedded as JSX. + * + * @example + * + */ +export type TranslationComponent = FC; + +/** + * Switch translation language here. + */ +export { translation, Translation } from "./ja-JP"; diff --git a/website/src/translation.tsx b/website/src/translation/ja-JP.tsx similarity index 80% rename from website/src/translation.tsx rename to website/src/translation/ja-JP.tsx index 758d507ead..ef201c7594 100644 --- a/website/src/translation.tsx +++ b/website/src/translation/ja-JP.tsx @@ -1,21 +1,14 @@ -import type { FC } from "hono/jsx"; -import type { TooltipProps } from "./components/ui/Tooltip"; +import type { TooltipProps } from "../components/ui/Tooltip"; import { discordServerUrl, githubOrganizationUrl, githubRepositoryUrl, typstOfficialDocsUrl, version, -} from "./metadata"; +} from "../metadata"; +import type { TranslationComponent, TranslationObject } from "./"; -/** - * Translation dictionary for UI attributes and aria labels. - * - * @example - * translation.closeMenu() - * translation.showInformation({ name: "foo" }) - */ -export const translation = { +export const translation: TranslationObject = { htmlLang: () => "ja", documentationTitle: () => "Typstドキュメント日本語版", close: () => "閉じる", @@ -48,64 +41,7 @@ export const translation = { }, } as const; -type TranslationKey = - | "definition" - | "constructor" - | "tableOfContents" - | "untranslated" - | "untranslatedMessage" - | "document" - | "langVersion" - | "elementFunction" - | "elementFunctionDescription" - | "contextFunction" - | "contextFunctionDescription" - | "definitionTooltip" - | "definitionTooltipDescription" - | "variadic" - | "translationRate" - | "variadicDescription" - | "typstOfficialDocs" - | "typstOfficialWebsite" - | "communityContent" - | "contentAddedByCommunity" - | "partiallyTranslated" - | "partiallyTranslatedMessage" - | "translated" - | "translatedMessage" - | "siteNoticeBannerTitle" - | "siteNoticeBannerDescription" - | "tutorial" - | "tutorialDescription" - | "referenceDescription" - | "reference" - | "openOfficialDocs" - | "search" - | "argument" - | "argumentDescription" - | "required" - | "requiredDescription" - | "positional" - | "positionalDescription" - | "defaultValue" - | "stringValues" - | "showExample" - | "settable" - | "settableDescription" - | "previousPage" - | "nextPage"; - -export type TranslationProps = - | { translationKey: TranslationKey } - | { translationKey: "definitionOf"; name: string }; - -/** - * Translation component for UI text, descriptions, and other content to be embedded as JSX. - * - * @example - * - */ -export const Translation: FC = (props) => { +export const Translation: TranslationComponent = (props) => { switch (props.translationKey) { case "definition": return <>定義; @@ -262,6 +198,13 @@ export const Translation: FC = (props) => { our Discord server "Kumihan Club". ); + case "footer": + return ( + <> + Translated by{" "} + Typst Japanese Community + + ); default: return null; }