diff --git a/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/programs/new/form.tsx b/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/programs/new/form.tsx index cbfbbb6ca5a..f8c4d1c48e2 100644 --- a/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/programs/new/form.tsx +++ b/apps/web/app/(ee)/app.dub.co/(new-program)/[slug]/programs/new/form.tsx @@ -1,4 +1,6 @@ "use client"; +import { useTranslations } from "next-intl"; + import { onboardProgramAction } from "@/lib/actions/partners/onboard-program"; import { getLinkStructureOptions } from "@/lib/partners/get-link-structure-options"; @@ -27,6 +29,8 @@ import { toast } from "sonner"; import useSWRImmutable from "swr/immutable"; export function Form() { +const t = useTranslations("program-creation-form"); + const router = useRouter(); const { isMobile } = useMediaQuery(); const [isUploading, setIsUploading] = useState(false); @@ -127,27 +131,19 @@ export function Form() { return (
- -

- The name of the company you're setting up the program for -

+ +

{t('descriptions.company-name')}

- -

- A square logo that will be used in various parts of your program -

+ +

{t('descriptions.logo')}

-

- Referral link -

-

- Set the custom domain and destination URL for your referral links -

+

{t('headings.referral-link')}

+

{t('descriptions.referral-link-setup')}

- + @@ -204,9 +194,7 @@ export function Form() { setSelectedDomain={(domain) => setValue("domain", domain)} /> -

- Custom domain that will be used for your program's referral links -

+

{t('descriptions.custom-domain')}

@@ -227,19 +215,14 @@ export function Form() {
- + -

- Where people will be redirected to when they click on your program's - referral links -

+

{t('descriptions.destination-url')}

@@ -253,9 +236,7 @@ export function Form() { transition={{ duration: 0.2 }} className="space-y-2" > -

- Referral link preview -

+

{t('headings.referral-link-preview')}

@@ -301,7 +282,7 @@ export function Form() {
)} @@ -214,22 +212,23 @@ export function ProgramApplicationForm({ )} {...register("termsAgreement", { required: true })} /> -
)}
diff --git a/apps/web/app/app.dub.co/(dashboard)/account/settings/security/update-password.tsx b/apps/web/app/app.dub.co/(dashboard)/account/settings/security/update-password.tsx index 6b6a0546da2..96209264a25 100644 --- a/apps/web/app/app.dub.co/(dashboard)/account/settings/security/update-password.tsx +++ b/apps/web/app/app.dub.co/(dashboard)/account/settings/security/update-password.tsx @@ -1,4 +1,6 @@ "use client"; +import { useTranslations } from "next-intl"; + import z from "@/lib/zod"; import { updatePasswordSchema } from "@/lib/zod/schemas/auth"; @@ -8,6 +10,8 @@ import { toast } from "sonner"; // Allow the user to update their existing password export const UpdatePassword = () => { +const t = useTranslations("update-password-form"); + const { register, handleSubmit, @@ -46,14 +50,12 @@ export const UpdatePassword = () => { >
-

Password

-

- Manage your account password on {process.env.NEXT_PUBLIC_APP_NAME}. -

+

{t('headings.password')}

+

{t('descriptions.manage-password', { "processEnvNextPublicAppName": process.env.NEXT_PUBLIC_APP_NAME })}

- + {
- + {
-

- Password requirements -

+

{t('tooltips.password-requirements')}

)}
@@ -311,26 +315,21 @@ export function CustomerTable() { src="https://assets.dub.co/misc/customer-screenshot.jpg" fill className="object-contain object-top" - alt="Customer overview screenshot" + alt={t('accessibility.customer-screenshot-alt')} draggable={false} />
- - Customer Insights - -

- Want to see more details about your customers' LTV, country - breakdown etc.? Upgrade to our Business Plan to get deeper, - real-time customer insights.{" "} - {t('upgrade-overlay.heading')} +

{t.rich('upgrade-overlay.description', { + component0: (chunks) => - Learn more ↗ - + >{chunks} + })} +

- - Upgrade to Business - + {t('upgrade-overlay.button-text')}
@@ -353,12 +350,8 @@ export function CustomerTable() { ) : ( }) { +const t = useTranslations("customer-table"); + const [isOpen, setIsOpen] = useState(false); const [, copyToClipboard] = useCopyToClipboard(); @@ -398,9 +393,7 @@ function RowMenuButton({ row }: { row: Row }) { }); setIsOpen(false); }} - > - Copy external ID - + >{t('context-menu.copy-external-id')} )} {row.original.email && ( }) { }); setIsOpen(false); }} - > - Copy email - + >{t('context-menu.copy-email')} )} diff --git a/apps/web/ui/layout/changelog-popup.tsx b/apps/web/ui/layout/changelog-popup.tsx index 67c76973c66..ebc1342ed99 100644 --- a/apps/web/ui/layout/changelog-popup.tsx +++ b/apps/web/ui/layout/changelog-popup.tsx @@ -1,4 +1,6 @@ "use client"; +import { useTranslations } from "next-intl"; + import { BlurImage, Popup, PopupContext } from "@dub/ui"; import { motion } from "framer-motion"; @@ -22,6 +24,8 @@ export default function ChangelogPopup() { } export function ChangelogPopupInner() { +const t = useTranslations("changelog-popup"); + const { hidePopup } = useContext(PopupContext); return ( @@ -49,7 +53,7 @@ export function ChangelogPopupInner() {
({ const HIDDEN_COOKIE_ID = "hideUserSurveyPopup"; export default function UserSurveyButton() { +const t = useTranslations("user-survey"); + const { data: session } = useSession(); const [hidden, setHidden] = useState(Cookies.get(HIDDEN_COOKIE_ID) === "1"); const [openPopover, setOpenPopover] = useState(false); @@ -52,9 +56,7 @@ export default function UserSurveyButton() { "hover:text-neutral-600 data-[state=open]:text-neutral-600", "outline-none focus-visible:ring-2 focus-visible:ring-black/50", )} - > - Where did you hear about Dub? - + >{t('prompts.where-did-you-hear')} )} @@ -65,6 +67,8 @@ export default function UserSurveyButton() { } export function UserSurveyPopupInner({ hide }: { hide: () => void }) { +const t = useTranslations("user-survey"); + const { update } = useSession(); const [status, setStatus] = useState("idle"); @@ -109,7 +113,7 @@ export function UserSurveyPopupInner({ hide }: { hide: () => void }) { className="absolute inset-0 flex flex-col items-center justify-center space-y-3 rounded-lg bg-white text-sm" > -

Thank you for your response!

+

{t('messages.thank-you-response')}

)} diff --git a/apps/web/ui/links/link-display.tsx b/apps/web/ui/links/link-display.tsx index 1e2186e274d..79661efd0d0 100644 --- a/apps/web/ui/links/link-display.tsx +++ b/apps/web/ui/links/link-display.tsx @@ -1,3 +1,4 @@ +import { useTranslations } from "next-intl"; import { linksDisplayProperties, LinksViewMode, @@ -25,6 +26,8 @@ import LinkSort from "./link-sort"; import { LinksDisplayContext } from "./links-display-provider"; export default function LinkDisplay() { +const t = useTranslations("link-display"); + const { viewMode, setViewMode, @@ -82,9 +85,7 @@ export default function LinkDisplay() { {!isMegaFolder && (
- - Ordering - + {t('sections.ordering')}
@@ -95,12 +96,8 @@ export default function LinkDisplay() {
- - A - -
- Show archived links -
+ {t('keyboard-shortcuts.archive-toggle')} +
{t('toggles.show-archived-links')}
)}
- - Display Properties - + {t('sections.display-properties')}
{linksDisplayProperties.map((property) => { const active = displayProperties.includes(property.id); @@ -172,13 +167,13 @@ export default function LinkDisplay() {
@@ -204,7 +199,7 @@ export default function LinkDisplay() {
)}
- Display + {t('labels.display')} >; }) { +const t = useTranslations("delete-account-modal"); + const router = useRouter(); const { data: session, update } = useSession(); const [deleting, setDeleting] = useState(false); @@ -53,11 +56,8 @@ function DeleteAccountModal({ >
-

Delete Account

-

- Warning: This will permanently delete your account, all your - workspaces, and all your short links. -

+

{t('headings.delete-account')}

+

{t('warnings.permanent-deletion')}

- To verify, type{" "} - - confirm delete account - {" "} - below - + >{t.rich('labels.verification-instruction', { + component0: (chunks) => {chunks} + })} +
@@ -169,7 +170,7 @@ function ImportRewardfulModal({ ) : isLoadingCampaigns || !workspaceId ? (
-

Loading campaigns...

+

{t('messages.loading-campaigns')}

) : campaigns ? ( -

- Failed to load campaigns. Please try again. -

+

{t('errors.failed-to-load-campaigns')}

)}
@@ -203,6 +202,8 @@ function TokenStep({ isSubmittingToken: boolean; onSubmit: (e: React.FormEvent) => Promise; }) { +const t = useTranslations("import-rewardful-modal"); + const { isMobile } = useMediaQuery(); return ( @@ -210,33 +211,30 @@ function TokenStep({ + >{t('labels.api-secret')} setApiToken(e.target.value)} - placeholder="Enter your Rewardful API token" + placeholder={t('placeholders.enter-api-token')} className="mt-1 block w-full rounded-md border border-neutral-200 px-3 py-2 placeholder-neutral-400 focus:border-neutral-500 focus:outline-none focus:ring-neutral-500 sm:text-sm" required /> -

- You can find your Rewardful API Secret on your{" "} - {t.rich('descriptions.api-secret-location', { + component0: (chunks) => - Company settings page - + >{chunks} + })} +