From 9aee8feaf48046a9e5098640307f21b26c7ca71d Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Wed, 15 Jan 2025 13:55:24 -0600 Subject: [PATCH] feat: translate embeds --- .../core/localization/strings/constants.ts | 1 + packages/i18n/src/supportedLocales.ts | 3 + packages/i18n/strings/en.json | 88 ++++++++++++++++++- packages/i18n/strings/pl.json | 1 + .../website/src/components/Embeds/Enum.tsx | 4 +- .../src/components/Embeds/GenerateURL.tsx | 55 ++++++++---- .../website/src/components/Embeds/Import.tsx | 23 +++-- .../src/components/Embeds/breakdown.tsx | 12 ++- .../tools/embed/[embed]/_index.tsx | 59 +++++++++---- .../tools/embed/[embed]/index.astro | 4 +- .../pages/[...locale]/tools/embed/_index.tsx | 52 +++++------ .../pages/[...locale]/tools/embed/index.astro | 4 +- .../website/src/stores/embedState/index.ts | 2 +- 13 files changed, 227 insertions(+), 81 deletions(-) create mode 100644 packages/i18n/strings/pl.json diff --git a/packages/bot/src/core/localization/strings/constants.ts b/packages/bot/src/core/localization/strings/constants.ts index 34c47c27f..e6ba71cc2 100644 --- a/packages/bot/src/core/localization/strings/constants.ts +++ b/packages/bot/src/core/localization/strings/constants.ts @@ -10,6 +10,7 @@ const SUPPORTED_LOCALES_DISCORD_MAP: Record = { zh: Locale.ChineseCN, fr: Locale.French, ja: Locale.Japanese, + pl: Locale.Polish, }; export const SUPPORTED_LOCALES_DISCORD_MAP_INVERSE = Object.fromEntries( diff --git a/packages/i18n/src/supportedLocales.ts b/packages/i18n/src/supportedLocales.ts index 0983b5b4f..130b7fa01 100644 --- a/packages/i18n/src/supportedLocales.ts +++ b/packages/i18n/src/supportedLocales.ts @@ -7,6 +7,7 @@ export const SUPPORTED_LOCALES = [ 'ru', 'uk', 'zh', + 'pl', ] as const; export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number]; @@ -22,6 +23,7 @@ export const SUPPORTED_LOCALE_BLITZ_MAP: Record = { ru: 'ru', uk: 'uk', zh: 'zh-Hans', + pl: 'pl', }; export const SUPPORTED_LOCALE_FLAGS: Record = { @@ -33,4 +35,5 @@ export const SUPPORTED_LOCALE_FLAGS: Record = { ru: 'πŸ‡·πŸ‡Ί', uk: 'πŸ‡ΊπŸ‡¦', zh: 'πŸ‡¨πŸ‡³', + pl: 'πŸ‡΅πŸ‡±', }; diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json index 229ad0993..69c06cada 100644 --- a/packages/i18n/strings/en.json +++ b/packages/i18n/strings/en.json @@ -52,7 +52,8 @@ "uk": "Ukrainian", "zh": "Chinese", "ja": "Japanese", - "fr": "French" + "fr": "French", + "pl": "Polish" }, "wn8_percentile": { @@ -741,6 +742,12 @@ }, "common": { + "player_search": { + "hint": "Search players...", + "no_results": "No results", + "searching": "Searching..." + }, + "copy_button": { "copied": "Copied!" }, @@ -1211,7 +1218,84 @@ "name": "Embed", "button": "Create now", "description": "Embeds for streaming", - "seo_description": "Create embeds for streaming World of Tanks Blitz with extreme customization" + "seo_description": "Create embeds for streaming World of Tanks Blitz with extreme customization", + "coming_soon": "More embeds coming soon.", + "suggest": "Suggest ideas.", + + "preview": { + "title": "Example preview", + "upload": "Upload test background" + }, + + "configuration": { + "import": { + "title": "Import", + "description": "Paste your current URL if you have one already to import your settings", + "hint": "Paste URL...", + "apply": "Apply", + "idiot_title": "Invalid URL", + "idiot_description": "Try pasting the URL that BlitzKit previously generated, you silly goose!", + "idiot_button": "Okay, my bad" + }, + + "export": { + "title": "Export", + "description": "Copy all properties for you streaming software", + "generate": { + "button": "Generate URL", + "title": "Generate URL", + "subtitle": "Search an account to track", + "cancel": "Cancel", + "success": { + "title": "Copy URL", + "info": "Generated the URL for %s1. The embed will start tracking as soon as the URL is pasted. Reset at any time by right-clicking on PC or long-pressing on mobile and then selecting \"Reset\".", + "back": "Back", + "copy": "Copy URL" + } + }, + "css": "Copy CSS", + "width": "Copy Width", + "height": "Copy Height", + "framerate": "Copy Framerate" + }, + + "customize": { + "title": "Customize", + "reset": "Reset", + "description": "Bells and whistles of your embed" + } + }, + + "types": { + "breakdown": { + "name": "Breakdown", + "options": { + "width": "Width", + "height": "Height", + "showTotal": "Show total", + "listGap": "List gap", + "listMaxTanks": "Max tanks", + "cardRadius": "Card radius", + "cardHeaderBackgroundColor": "Card header background color", + "cardHeaderPadding": "Card header padding", + "cardTitle": "Card title", + "cardTitleTypeColor": "Card title type color", + "cardTitleClassIcon": "Card title class icon", + "cardBodyBackgroundColor": "Card body background color", + "cardBodyPadding": "Card body padding", + "columnGap": "Column gap", + "columnValue": "Column value", + "columnLabel": "Column label", + "column1": "Column 1", + "column2": "Column 2", + "column3": "Column 3", + "column4": "Column 4", + "column1CustomLabel": "Column 1 label", + "column2CustomLabel": "Column 2 label", + "column3CustomLabel": "Column 3 label" + } + } + } }, "charts": { "name": "Charts", diff --git a/packages/i18n/strings/pl.json b/packages/i18n/strings/pl.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/packages/i18n/strings/pl.json @@ -0,0 +1 @@ +{} diff --git a/packages/website/src/components/Embeds/Enum.tsx b/packages/website/src/components/Embeds/Enum.tsx index 865abb527..fe6ad35ba 100644 --- a/packages/website/src/components/Embeds/Enum.tsx +++ b/packages/website/src/components/Embeds/Enum.tsx @@ -1,4 +1,5 @@ import { Select } from '@radix-ui/themes'; +import { useLocale } from '../../hooks/useLocale'; import type { EmbedPreviewControllerProps } from '../../pages/[...locale]/tools/embed/[embed]/_index'; import { EmbedState } from '../../stores/embedState'; import type { @@ -13,6 +14,7 @@ export function Enum({ config: EmbedConfigItemType; }) { const mutateEmbedState = EmbedState.useMutation(); + const { locale } = useLocale(); return ( {config.options.map((option) => ( - {option.label} + {option.locales[locale]} ))} diff --git a/packages/website/src/components/Embeds/GenerateURL.tsx b/packages/website/src/components/Embeds/GenerateURL.tsx index 57a8f4ef0..2143513cf 100644 --- a/packages/website/src/components/Embeds/GenerateURL.tsx +++ b/packages/website/src/components/Embeds/GenerateURL.tsx @@ -3,7 +3,6 @@ import { type AccountListItem, type AccountListWithServer, } from '@blitzkit/core'; -import strings from '@blitzkit/i18n/strings/en.json'; import { CaretLeftIcon, Link2Icon, PersonIcon } from '@radix-ui/react-icons'; import { Badge, @@ -19,6 +18,8 @@ import { debounce } from 'lodash-es'; import { useCallback, useRef, useState } from 'react'; import { stringify } from 'urlon'; import type { embedConfigurations } from '../../constants/embeds'; +import { literals } from '../../core/i18n/literals'; +import { useLocale } from '../../hooks/useLocale'; import { EmbedState, type EmbedStateStore } from '../../stores/embedState'; import { CopyButton } from '../CopyButton'; @@ -34,6 +35,7 @@ export function GenerateURL({ embed }: GenerateURLProps) { const input = useRef(null); const [searching, setSearching] = useState(false); const [results, setResults] = useState([]); + const { strings } = useLocale(); const performSearch = useCallback( debounce(async () => { if (!input.current) return; @@ -72,20 +74,27 @@ export function GenerateURL({ embed }: GenerateURLProps) { - Generate URL - Search an account to track + + {strings.website.tools.embed.configuration.export.generate.title} + + + { + strings.website.tools.embed.configuration.export.generate + .subtitle + } + @@ -98,12 +107,14 @@ export function GenerateURL({ embed }: GenerateURLProps) { {searching && ( - Searching + {strings.website.common.player_search.searching} )} {!searching && results.length === 0 && ( - No results + + {strings.website.common.player_search.no_results} + )} {!searching && results.length > 0 && ( @@ -131,7 +142,7 @@ export function GenerateURL({ embed }: GenerateURLProps) { @@ -140,12 +151,18 @@ export function GenerateURL({ embed }: GenerateURLProps) { - Copy URL + + { + strings.website.tools.embed.configuration.export.generate + .success.title + } + - Generated the URL for {copyUser?.nickname}. The embed will start - tracking as soon as the URL is pasted. Reset at any time by - right-clicking on PC or long-pressing on mobile and then selecting - "Reset". + {literals( + strings.website.tools.embed.configuration.export.generate + .success.info, + [`${copyUser?.nickname}`], + )} @@ -158,7 +175,11 @@ export function GenerateURL({ embed }: GenerateURLProps) { setSearchDialogOpen(true); }} > - Back + {' '} + { + strings.website.tools.embed.configuration.export.generate + .success.back + } - Copy URL + {' '} + { + strings.website.tools.embed.configuration.export.generate + .success.copy + } diff --git a/packages/website/src/components/Embeds/Import.tsx b/packages/website/src/components/Embeds/Import.tsx index 32ad5f769..da1e34fed 100644 --- a/packages/website/src/components/Embeds/Import.tsx +++ b/packages/website/src/components/Embeds/Import.tsx @@ -9,6 +9,7 @@ import { } from '@radix-ui/themes'; import { useRef, useState } from 'react'; import { parse } from 'urlon'; +import { useLocale } from '../../hooks/useLocale'; import { EmbedState } from '../../stores/embedState'; export function Import() { @@ -16,12 +17,15 @@ export function Import() { const [showInvalidURLPrompt, setShowInvalidURLPrompt] = useState(false); const [showConfirmation, setConfirmation] = useState(false); const mutateEmbedState = EmbedState.useMutation(); + const { strings } = useLocale(); return ( <> - Import + + {strings.website.tools.embed.configuration.import.title} + - Paste your current URL if you have one already to import your settings + {strings.website.tools.embed.configuration.import.description} - Invalid URL + + {strings.website.tools.embed.configuration.import.idiot_title} + - Try pasting the URL that BlitzKit previously generated, you silly - goose! + {strings.website.tools.embed.configuration.import.idiot_description} - + @@ -46,7 +53,7 @@ export function Import() { @@ -72,7 +79,7 @@ export function Import() { } }} > - Apply + {strings.website.tools.embed.configuration.import.apply} diff --git a/packages/website/src/components/Embeds/breakdown.tsx b/packages/website/src/components/Embeds/breakdown.tsx index 5c2524f0e..14ca3a885 100644 --- a/packages/website/src/components/Embeds/breakdown.tsx +++ b/packages/website/src/components/Embeds/breakdown.tsx @@ -8,7 +8,7 @@ import { sumCompositeStats, type IndividualTankStats, } from '@blitzkit/core'; -import strings from '@blitzkit/i18n/strings/en.json'; +import { localizedStrings } from '@blitzkit/i18n'; import { ReloadIcon } from '@radix-ui/react-icons'; import { ContextMenu } from '@radix-ui/themes'; import { useEffect, useMemo, useState } from 'react'; @@ -20,8 +20,16 @@ import { useEmbedStateCurry } from '../../stores/embedState/utilities'; import { BreakdownEmbedCard, BreakdownEmbedWrapper } from '../TanksEmbed'; export const compositeStatsKeysOptions = compositeStatsKeys.map((value) => ({ - label: strings.common.composite_stats[value], value, + locales: Object.entries(localizedStrings).reduce( + (accumulator, [locale, strings]) => { + return { + ...accumulator, + [locale]: strings.common.composite_stats[value], + }; + }, + {}, + ), })); const [tankDefinitions, averageDefinitions] = await Promise.all([ diff --git a/packages/website/src/pages/[...locale]/tools/embed/[embed]/_index.tsx b/packages/website/src/pages/[...locale]/tools/embed/[embed]/_index.tsx index adb33d8b4..74328579b 100644 --- a/packages/website/src/pages/[...locale]/tools/embed/[embed]/_index.tsx +++ b/packages/website/src/pages/[...locale]/tools/embed/[embed]/_index.tsx @@ -8,7 +8,6 @@ import { WidthIcon, } from '@radix-ui/react-icons'; import { Box, Button, Flex, Heading, ScrollArea, Text } from '@radix-ui/themes'; -import { capitalize, startCase } from 'lodash-es'; import { useEffect, useRef, useState, type ReactNode } from 'react'; import { CopyButton } from '../../../../../components/CopyButton'; import { Boolean } from '../../../../../components/Embeds/Boolean'; @@ -29,6 +28,11 @@ import { extractEmbedConfigDefaults, } from '../../../../../constants/embeds'; import { NAVBAR_HEIGHT } from '../../../../../constants/navbar'; +import { + LocaleProvider, + useLocale, + type LocaleAcceptorProps, +} from '../../../../../hooks/useLocale'; import { App } from '../../../../../stores/app'; import { EmbedState, type EmbedConfig } from '../../../../../stores/embedState'; import { EmbedItemType } from '../../../../../stores/embedState/constants'; @@ -41,15 +45,17 @@ interface PageProps { embed: keyof typeof embedConfigurations; } -export function Page({ embed }: PageProps) { +export function Page({ embed, locale }: PageProps & LocaleAcceptorProps) { const config = embedConfigurations[embed]; return ( - - - - - + + + + + + + ); } @@ -60,6 +66,7 @@ function Content({ embed }: PageProps) { imgur('SO13zur', { format: 'jpeg' }), ); const fileInput = useRef(); + const { strings } = useLocale(); useEffect(() => { fileInput.current = document.createElement('input'); @@ -83,9 +90,11 @@ function Content({ embed }: PageProps) { - Export + + {strings.website.tools.embed.configuration.export.title} + - Copy all properties for you streaming software + {strings.website.tools.embed.configuration.export.description} @@ -98,30 +107,32 @@ function Content({ embed }: PageProps) { } > - Copy CSS + {strings.website.tools.embed.configuration.export.css} `${embedStateStore.getState().width}`} > - Copy width + {strings.website.tools.embed.configuration.export.width} `${embedStateStore.getState().height}`} > - Copy height + {strings.website.tools.embed.configuration.export.height} '1'}> - Copy framerate + {strings.website.tools.embed.configuration.export.framerate} - Customize + + {strings.website.tools.embed.configuration.customize.title} + - Bells and whistles of your embed + {strings.website.tools.embed.configuration.customize.description} {Object.keys(config).map((configKey) => { @@ -206,7 +218,14 @@ function Content({ embed }: PageProps) { mb={oneLiner ? '2' : '4'} pb={item.pad ? '6' : undefined} > - {capitalize(startCase(configKey as string))} + + { + ( + strings.website.tools.embed.types[embed] + .options as Record + )[configKey] + } + - Example preview + + {strings.website.tools.embed.preview.title} + diff --git a/packages/website/src/pages/[...locale]/tools/embed/[embed]/index.astro b/packages/website/src/pages/[...locale]/tools/embed/[embed]/index.astro index 72313bcc9..58103ddf6 100644 --- a/packages/website/src/pages/[...locale]/tools/embed/[embed]/index.astro +++ b/packages/website/src/pages/[...locale]/tools/embed/[embed]/index.astro @@ -20,6 +20,8 @@ export const getStaticPaths = (() => { ) .flat(); }) satisfies GetStaticPaths; + +const { locale } = Astro.params; --- BlitzKit - {capitalize(Astro.params.embed)} embed @@ -44,5 +46,5 @@ export const getStaticPaths = (() => { - + diff --git a/packages/website/src/pages/[...locale]/tools/embed/_index.tsx b/packages/website/src/pages/[...locale]/tools/embed/_index.tsx index 0f92f4b41..15a183f76 100644 --- a/packages/website/src/pages/[...locale]/tools/embed/_index.tsx +++ b/packages/website/src/pages/[...locale]/tools/embed/_index.tsx @@ -1,6 +1,5 @@ import { imgur, ImgurSize } from '@blitzkit/core'; import { Box, Flex, Link, Text } from '@radix-ui/themes'; -import { capitalize } from 'lodash-es'; import { PreviewWrapper } from '../../../../components/Embeds/PreviewWrapper'; import { LinkI18n } from '../../../../components/LinkI18n'; import { PageWrapper } from '../../../../components/PageWrapper'; @@ -9,52 +8,37 @@ import { extractEmbedConfigDefaults, } from '../../../../constants/embeds'; import { Var } from '../../../../core/radix/var'; -import { useLocale } from '../../../../hooks/useLocale'; +import { + LocaleProvider, + useLocale, + type LocaleAcceptorProps, +} from '../../../../hooks/useLocale'; import { App } from '../../../../stores/app'; import { EmbedState } from '../../../../stores/embedState'; -export function Page() { +export function Page({ locale }: LocaleAcceptorProps) { return ( - - - + + + + + ); } function Content() { - // const wargaming = App.useDeferred((state) => state.logins.wargaming, { - // token: '', - // id: 0, - // expires: 0, - // }); - - const { locale } = useLocale(); + const { locale, strings } = useLocale(); return ( - {/* {!wargaming && ( - - - - - - - You must log in to generate embeds. - - - - Log in with Wargaming - - )} */} - - More embeds coming soon.{' '} + {strings.website.tools.embed.coming_soon}{' '} - Suggest ideas + {strings.website.tools.embed.suggest} . @@ -86,7 +70,13 @@ function Content() { }} > - {capitalize(embed)} + + { + strings.website.tools.embed.types[ + embed as keyof typeof strings.website.tools.embed.types + ].name + } + - + diff --git a/packages/website/src/stores/embedState/index.ts b/packages/website/src/stores/embedState/index.ts index 91ed41320..28412a65d 100644 --- a/packages/website/src/stores/embedState/index.ts +++ b/packages/website/src/stores/embedState/index.ts @@ -94,8 +94,8 @@ export type EmbedConfigItem = ( type: EmbedItemType.Enum; default: string; options: { - label: string; value: string; + locales: Record; }[]; } ) & {