Merged in feat/lokalise-rebuild (pull request #2993)
Feat/lokalise rebuild * chore(lokalise): update translation ids * chore(lokalise): easier to switch between projects * chore(lokalise): update translation ids * . * . * . * . * . * . * chore(lokalise): update translation ids * chore(lokalise): update translation ids * . * . * . * chore(lokalise): update translation ids * chore(lokalise): update translation ids * . * . * chore(lokalise): update translation ids * chore(lokalise): update translation ids * chore(lokalise): new translations * merge * switch to errors for missing id's * merge * sync translations Approved-by: Linus Flood
This commit is contained in:
@@ -63,6 +63,7 @@ export const editProfile = protectedServerActionProcedure
|
||||
message: issue.message,
|
||||
})),
|
||||
message: intl.formatMessage({
|
||||
id: "editProfile.validationErrorMessage",
|
||||
defaultMessage:
|
||||
"An error occurred when trying to update your profile.",
|
||||
}),
|
||||
@@ -84,6 +85,7 @@ export const editProfile = protectedServerActionProcedure
|
||||
data: input,
|
||||
issues: [],
|
||||
message: intl.formatMessage({
|
||||
id: "editProfile.validationErrorMessage",
|
||||
defaultMessage:
|
||||
"An error occurred when trying to update your profile.",
|
||||
}),
|
||||
@@ -143,6 +145,7 @@ export const editProfile = protectedServerActionProcedure
|
||||
return {
|
||||
data: input,
|
||||
message: intl.formatMessage({
|
||||
id: "editProfile.successMessage",
|
||||
defaultMessage: "Successfully updated profile!",
|
||||
}),
|
||||
status: Status.success,
|
||||
@@ -179,6 +182,7 @@ export const editProfile = protectedServerActionProcedure
|
||||
data: input,
|
||||
issues: [],
|
||||
message: intl.formatMessage({
|
||||
id: "editProfile.validationErrorMessage",
|
||||
defaultMessage:
|
||||
"An error occurred when trying to update your profile.",
|
||||
}),
|
||||
@@ -216,6 +220,7 @@ export const editProfile = protectedServerActionProcedure
|
||||
message: issue.message,
|
||||
})),
|
||||
message: intl.formatMessage({
|
||||
id: "editProfile.validationErrorMessage",
|
||||
defaultMessage:
|
||||
"An error occurred when trying to update your profile.",
|
||||
}),
|
||||
@@ -226,6 +231,7 @@ export const editProfile = protectedServerActionProcedure
|
||||
return {
|
||||
data: validatedData.data,
|
||||
message: intl.formatMessage({
|
||||
id: "editProfile.successMessage",
|
||||
defaultMessage: "Successfully updated profile!",
|
||||
}),
|
||||
status: Status.success,
|
||||
|
||||
@@ -25,6 +25,7 @@ export default function Error({
|
||||
<strong>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "myPages.breadcrumbsError",
|
||||
defaultMessage: "Breadcrumbs failed for this page ({errorId})",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@ export default function Error({
|
||||
<strong>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "myPages.errorLoadingPage",
|
||||
defaultMessage: "Error loading this page ({errorId})",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -64,6 +64,7 @@ export default async function MyPages({}: PageArgs<
|
||||
) : (
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "myPages.missingContent",
|
||||
defaultMessage: "No content published",
|
||||
})}
|
||||
</p>
|
||||
|
||||
@@ -28,6 +28,7 @@ export default function Error({
|
||||
<strong>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "destinationOverviewPage.errorOccurred",
|
||||
defaultMessage: "An error occurred ({errorId})",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -38,6 +38,7 @@ export async function generateMetadata({
|
||||
|
||||
const title = intl.formatMessage(
|
||||
{
|
||||
id: "alternativeHotels.title",
|
||||
defaultMessage: "Alternatives for {value}",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -40,6 +40,7 @@ export async function generateMetadata({
|
||||
|
||||
const title = intl.formatMessage(
|
||||
{
|
||||
id: "alternativeHotels.title",
|
||||
defaultMessage: "Alternatives for {value}",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -17,6 +17,9 @@ export async function generateMetadata() {
|
||||
const intl = await getIntl()
|
||||
|
||||
return {
|
||||
title: intl.formatMessage({ defaultMessage: "Find booking" }),
|
||||
title: intl.formatMessage({
|
||||
id: "booking.findBooking",
|
||||
defaultMessage: "Find booking",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ export default function Error({
|
||||
<section className={styles.layout}>
|
||||
<div className={styles.content}>
|
||||
{intl.formatMessage({
|
||||
id: "errorMessage.somethingWentWrong",
|
||||
defaultMessage: "Something went wrong!",
|
||||
})}
|
||||
{env.NEXT_PUBLIC_NODE_ENV === "development" && (
|
||||
|
||||
@@ -47,6 +47,7 @@ export default function LinkEmploymentErrorPage() {
|
||||
/>
|
||||
<span className={styles.navBackText}>
|
||||
{intl.formatMessage({
|
||||
id: "common.goBack",
|
||||
defaultMessage: "Go back",
|
||||
})}
|
||||
</span>
|
||||
@@ -69,6 +70,7 @@ export default function LinkEmploymentErrorPage() {
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
id: "linkEmploymentError.contactHeading",
|
||||
defaultMessage: "Contact our member service",
|
||||
})}
|
||||
</h3>
|
||||
@@ -102,9 +104,11 @@ export default function LinkEmploymentErrorPage() {
|
||||
const getErrorContent = (error: string | null, intl: IntlShape) => {
|
||||
const defaultErrorContent = {
|
||||
heading: intl.formatMessage({
|
||||
id: "linkEmploymentError.genericHeading",
|
||||
defaultMessage: "Your account could not be connected",
|
||||
}),
|
||||
message: intl.formatMessage({
|
||||
id: "linkEmploymentError.genericMessage",
|
||||
defaultMessage:
|
||||
"We couldn't connect your accounts. Please contact us and we'll help you resolve this.",
|
||||
}),
|
||||
@@ -114,9 +118,11 @@ const getErrorContent = (error: string | null, intl: IntlShape) => {
|
||||
case "unable_to_verify_employee_id":
|
||||
return {
|
||||
heading: intl.formatMessage({
|
||||
id: "linkEmploymentError.notEligibleHeading",
|
||||
defaultMessage: "You're not eligible for employee benefits",
|
||||
}),
|
||||
message: intl.formatMessage({
|
||||
id: "linkEmploymentError.notEligibleMessage",
|
||||
defaultMessage:
|
||||
"This may be because your employment has not yet started, has ended, or you are a consultant. If you believe this is an error, please contact us for assistance.",
|
||||
}),
|
||||
@@ -124,10 +130,12 @@ const getErrorContent = (error: string | null, intl: IntlShape) => {
|
||||
case "employee_id_already_linked":
|
||||
return {
|
||||
heading: intl.formatMessage({
|
||||
id: "linkEmploymentError.alreadyLinkedHeading",
|
||||
defaultMessage:
|
||||
"Employee number already linked to another Scandic Friends membership.",
|
||||
}),
|
||||
message: intl.formatMessage({
|
||||
id: "linkEmploymentError.alreadyLinkedMessage",
|
||||
defaultMessage:
|
||||
"If you believe this is an error, please contact us for assistance.",
|
||||
}),
|
||||
|
||||
@@ -25,6 +25,7 @@ export function AlreadyLinkedError() {
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.alreadyLinkedHeading",
|
||||
defaultMessage:
|
||||
"Your Scandic Friends and SAS EuroBonus accounts are already connected",
|
||||
})}
|
||||
@@ -33,6 +34,7 @@ export function AlreadyLinkedError() {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.alreadyLinkedMessage",
|
||||
defaultMessage:
|
||||
"Great news! You can go straight to My Pages to explore all your perks and rewards!",
|
||||
})}
|
||||
@@ -46,6 +48,7 @@ export function AlreadyLinkedError() {
|
||||
size={"Large"}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.viewLinkedAccountsButton",
|
||||
defaultMessage: "View your linked accounts",
|
||||
})}
|
||||
</ButtonLink>
|
||||
|
||||
@@ -26,6 +26,7 @@ export function DateOfBirthError() {
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.dateOfBirthErrorHeading",
|
||||
defaultMessage: "Date of birth not matching",
|
||||
})}
|
||||
</h1>
|
||||
@@ -33,6 +34,7 @@ export function DateOfBirthError() {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.couldntConnectAccountsErrorMessage",
|
||||
defaultMessage:
|
||||
"We couldn’t connect your accounts. Please contact us and we’ll help you resolve this.",
|
||||
})}
|
||||
@@ -41,6 +43,7 @@ export function DateOfBirthError() {
|
||||
<Button theme="base" asChild>
|
||||
<Link href={profile[lang]}>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.viewYourDetailsButton",
|
||||
defaultMessage: "View your details",
|
||||
})}
|
||||
</Link>
|
||||
|
||||
@@ -19,6 +19,7 @@ export function SASModalDivider() {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
id: "common.or",
|
||||
defaultMessage: "or",
|
||||
})}
|
||||
</span>
|
||||
@@ -31,6 +32,7 @@ export function SASModalContactBlock() {
|
||||
const intl = useIntl()
|
||||
|
||||
const phone = intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.contactPhoneNumber",
|
||||
defaultMessage: "+46 8 517 517 00",
|
||||
})
|
||||
|
||||
@@ -39,6 +41,7 @@ export function SASModalContactBlock() {
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h4 className={styles.contactBlockTitle}>
|
||||
{intl.formatMessage({
|
||||
id: "common.contactUs",
|
||||
defaultMessage: "Contact us",
|
||||
})}
|
||||
</h4>
|
||||
|
||||
@@ -13,6 +13,7 @@ export function TooManyCodesError() {
|
||||
return (
|
||||
<GenericError
|
||||
title={intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.tooManyCodesErrorHeading",
|
||||
defaultMessage: "You’ve requested too many codes",
|
||||
})}
|
||||
variant="info"
|
||||
@@ -20,12 +21,14 @@ export function TooManyCodesError() {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.tooManyFailedAttemptsErrorMessage",
|
||||
defaultMessage: "Please wait 1 hour before trying again.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Button theme="base" disabled>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.sendNewCodeButton",
|
||||
defaultMessage: "Send new code",
|
||||
})}
|
||||
</Button>
|
||||
|
||||
@@ -13,6 +13,7 @@ export function TooManyFailedAttemptsError() {
|
||||
return (
|
||||
<GenericError
|
||||
title={intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.tooManyFailedAttemptsErrorHeading",
|
||||
defaultMessage: "Too many failed attempts.",
|
||||
})}
|
||||
variant="info"
|
||||
@@ -20,12 +21,14 @@ export function TooManyFailedAttemptsError() {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.tooManyFailedAttemptsErrorMessage",
|
||||
defaultMessage: "Please wait 1 hour before trying again.",
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
<Button theme="base" disabled>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.sendNewCodeButton",
|
||||
defaultMessage: "Send new code",
|
||||
})}
|
||||
</Button>
|
||||
|
||||
@@ -13,12 +13,14 @@ export function UnlinkError() {
|
||||
return (
|
||||
<GenericError
|
||||
title={intl.formatMessage({
|
||||
id: "unlinkEuroBonusAccount.errorHeading",
|
||||
defaultMessage: "We could not unlink your accounts",
|
||||
})}
|
||||
>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "unlinkEuroBonusAccount.errorMessage",
|
||||
defaultMessage:
|
||||
"We couldn’t unlink your accounts. Please contact us and we’ll help you resolve this.",
|
||||
})}
|
||||
|
||||
@@ -27,12 +27,14 @@ export default function Error({
|
||||
return (
|
||||
<GenericError
|
||||
title={intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.genericErrorHeading",
|
||||
defaultMessage: "Something went wrong",
|
||||
})}
|
||||
>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.genericErrorMessage",
|
||||
defaultMessage: "Please try again later",
|
||||
})}
|
||||
</p>
|
||||
|
||||
@@ -13,9 +13,10 @@ import { UnlinkError } from "../components/UnlinkError"
|
||||
import type { LangParams, PageArgs, SearchParams } from "@/types/params"
|
||||
|
||||
export default async function Page(
|
||||
props: PageArgs<LangParams> & SearchParams<{ errorCode?: "dateOfBirthMismatch" }>
|
||||
props: PageArgs<LangParams> &
|
||||
SearchParams<{ errorCode?: "dateOfBirthMismatch" }>
|
||||
) {
|
||||
const searchParams = await props.searchParams;
|
||||
const searchParams = await props.searchParams
|
||||
const intl = await getIntl()
|
||||
|
||||
const { errorCode } = searchParams
|
||||
@@ -43,12 +44,14 @@ export default async function Page(
|
||||
return (
|
||||
<GenericError
|
||||
title={intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.genericErrorTitle",
|
||||
defaultMessage: "We could not connect your accounts",
|
||||
})}
|
||||
>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.couldntConnectAccountsErrorMessage",
|
||||
defaultMessage:
|
||||
"We couldn’t connect your accounts. Please contact us and we’ll help you resolve this.",
|
||||
})}
|
||||
|
||||
@@ -33,11 +33,13 @@ export default async function SasXScandicLayout(
|
||||
<ArrowLeft height={20} width={20} />
|
||||
<span className={styles.long}>
|
||||
{intl.formatMessage({
|
||||
id: "header.backToScandicHotelsCom",
|
||||
defaultMessage: "Back to scandichotels.com",
|
||||
})}
|
||||
</span>
|
||||
<span className={styles.short}>
|
||||
{intl.formatMessage({
|
||||
id: "common.back",
|
||||
defaultMessage: "Back",
|
||||
})}
|
||||
</span>
|
||||
@@ -55,6 +57,7 @@ async function MainMenuLogo() {
|
||||
return (
|
||||
<Logo
|
||||
alt={intl.formatMessage({
|
||||
id: "header.backToScandicHotelsCom",
|
||||
defaultMessage: "Back to scandichotels.com",
|
||||
})}
|
||||
/>
|
||||
|
||||
@@ -62,6 +62,7 @@ export function LinkAccountForm({
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.linkYourAccountsTitle",
|
||||
defaultMessage: "Link your accounts",
|
||||
})}
|
||||
</h3>
|
||||
@@ -73,6 +74,7 @@ export function LinkAccountForm({
|
||||
{userDateOfBirth
|
||||
? intl.formatMessage(
|
||||
{
|
||||
id: "linkEuroBonusAccount.birthDate",
|
||||
defaultMessage:
|
||||
"Birth date: {dateOfBirth, date, ::MMMM d yyyy}",
|
||||
},
|
||||
@@ -81,6 +83,7 @@ export function LinkAccountForm({
|
||||
}
|
||||
)
|
||||
: intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.birthDateMissing",
|
||||
defaultMessage: "Birth date is missing",
|
||||
})}
|
||||
</p>
|
||||
@@ -88,6 +91,7 @@ export function LinkAccountForm({
|
||||
<Typography variant="Label/xsRegular">
|
||||
<p className={styles.dateOfBirthDescription}>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.birthDateDescription",
|
||||
defaultMessage:
|
||||
"We require your birth date in order to link your Scandic Friends account with your SAS EuroBonus account. Please check that it is correct.",
|
||||
})}
|
||||
@@ -100,6 +104,7 @@ export function LinkAccountForm({
|
||||
textDecoration="underline"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.editPersonalDetailsLink",
|
||||
defaultMessage: "Edit your personal details",
|
||||
})}
|
||||
|
||||
@@ -113,6 +118,7 @@ export function LinkAccountForm({
|
||||
required: {
|
||||
value: true,
|
||||
message: intl.formatMessage({
|
||||
id: "common.mustAcceptTermsError",
|
||||
defaultMessage: "You must accept the terms and conditions",
|
||||
}),
|
||||
},
|
||||
@@ -122,6 +128,7 @@ export function LinkAccountForm({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "booking.acceptBookingTerms",
|
||||
defaultMessage: "I accept the booking and cancellation terms",
|
||||
})}
|
||||
</p>
|
||||
@@ -131,6 +138,7 @@ export function LinkAccountForm({
|
||||
<p className={styles.termsDescription}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "linkEuroBonusAccount.termsAndConditionsDescription",
|
||||
defaultMessage:
|
||||
"By linking your accounts you accept the <sasScandicTermsAndConditionsLink>Terms & Conditions for Scandic Friends and SAS EuroBonus Account Linking</sasScandicTermsAndConditionsLink>.",
|
||||
},
|
||||
@@ -158,6 +166,7 @@ export function LinkAccountForm({
|
||||
disabled={isPending || disableSubmit}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.linkMyAccountsButton",
|
||||
defaultMessage: "Link my accounts",
|
||||
})}
|
||||
</Button>
|
||||
|
||||
@@ -26,6 +26,7 @@ export default async function SASxScandicLinkPage(props: PageArgs<LangParams>) {
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.successTitle",
|
||||
defaultMessage: "Your accounts are linked",
|
||||
})}
|
||||
</h1>
|
||||
@@ -34,6 +35,7 @@ export default async function SASxScandicLinkPage(props: PageArgs<LangParams>) {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.successMessage",
|
||||
defaultMessage: "We successfully connected your accounts!",
|
||||
})}
|
||||
</p>
|
||||
@@ -41,6 +43,7 @@ export default async function SASxScandicLinkPage(props: PageArgs<LangParams>) {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.redirectMyPagesMessage",
|
||||
defaultMessage: "Redirecting you to My Pages.",
|
||||
})}
|
||||
</p>
|
||||
|
||||
@@ -54,14 +54,17 @@ export default async function SASxScandicLoginPage(
|
||||
|
||||
const intentDescriptions: Record<Intent, string> = {
|
||||
link: intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.loginRequired",
|
||||
defaultMessage:
|
||||
"Log in to your SAS EuroBonus account to confirm account linking.",
|
||||
}),
|
||||
unlink: intl.formatMessage({
|
||||
id: "unlinkEuroBonusAccount.loginRequired",
|
||||
defaultMessage:
|
||||
"Log in to your SAS EuroBonus account to confirm account unlinking.",
|
||||
}),
|
||||
transfer: intl.formatMessage({
|
||||
id: "transferEuroBonusPoints.loginRequired",
|
||||
defaultMessage:
|
||||
"In order to exchange your points, we'll ask you to sign in to your SAS EuroBonus account.",
|
||||
}),
|
||||
@@ -80,6 +83,7 @@ export default async function SASxScandicLoginPage(
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.redirectingToSAS",
|
||||
defaultMessage: "Redirecting you to SAS",
|
||||
})}
|
||||
</h1>
|
||||
@@ -92,6 +96,7 @@ export default async function SASxScandicLoginPage(
|
||||
<Footnote textAlign="center">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "linkEuroBonusAccount.manualRedirectLinkMessage",
|
||||
defaultMessage:
|
||||
"If you are not redirected automatically, please <loginLink>click here</loginLink>.",
|
||||
},
|
||||
|
||||
@@ -56,6 +56,7 @@ export default function OneTimePasswordForm({
|
||||
const cause = requestOtp.error?.data?.cause as RequestOtpError
|
||||
|
||||
const title = intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.oneTimePasswordGenericError",
|
||||
defaultMessage: "Error requesting OTP",
|
||||
})
|
||||
const body = getRequestErrorBody(intl, cause?.errorCode)
|
||||
@@ -123,10 +124,12 @@ export default function OneTimePasswordForm({
|
||||
|
||||
const errorMessages: Record<OtpError, ReactNode> = {
|
||||
invalidCode: intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.invalidOtpCodeMessage",
|
||||
defaultMessage: "The code you've entered is incorrect.",
|
||||
}),
|
||||
expiredCode: intl.formatMessage(
|
||||
{
|
||||
id: "linkEuroBonusAccount.expiredOtpCodeMessage",
|
||||
defaultMessage:
|
||||
"This code has expired. <resendOtpLink>Send new code.</resendOtpLink>",
|
||||
},
|
||||
@@ -188,6 +191,7 @@ export default function OneTimePasswordForm({
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "linkEuroBonusAccount.didNotReceiveCodeMessage",
|
||||
defaultMessage:
|
||||
"Didn't receive a code? <resendOtpLink>Resend code</resendOtpLink>",
|
||||
},
|
||||
@@ -226,10 +230,12 @@ const getRequestErrorBody = (
|
||||
switch (errorCode) {
|
||||
case "TOO_MANY_REQUESTS":
|
||||
return intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.tooManyOtpRequestsMessage",
|
||||
defaultMessage: "Too many requests. Please try again later.",
|
||||
})
|
||||
default:
|
||||
return intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.requestOtpGenericErrorMessage",
|
||||
defaultMessage: "An error occurred while requesting a new OTP",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ export default function Loading() {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.loadingMessage",
|
||||
defaultMessage: "Hang tight...",
|
||||
})}
|
||||
</p>
|
||||
|
||||
@@ -115,6 +115,7 @@ export default async function SASxScandicOneTimePasswordPage(
|
||||
const intentDescriptions: Record<Intent, ReactNode> = {
|
||||
link: intl.formatMessage(
|
||||
{
|
||||
id: "linkEuroBonusAccount.oneTimePasswordInputDescription",
|
||||
defaultMessage:
|
||||
"Please enter the code sent to <maskedContactInfo></maskedContactInfo> in order to confirm your account linking.",
|
||||
},
|
||||
@@ -122,6 +123,7 @@ export default async function SASxScandicOneTimePasswordPage(
|
||||
),
|
||||
unlink: intl.formatMessage(
|
||||
{
|
||||
id: "unlinkEuroBonusAccount.oneTimePasswordInputDescription",
|
||||
defaultMessage:
|
||||
"Please enter the code sent to <maskedContactInfo></maskedContactInfo> in order to unlink your accounts.",
|
||||
},
|
||||
@@ -129,6 +131,7 @@ export default async function SASxScandicOneTimePasswordPage(
|
||||
),
|
||||
transfer: intl.formatMessage(
|
||||
{
|
||||
id: "transferEuroBonusPoints.oneTimePasswordInputDescription",
|
||||
defaultMessage:
|
||||
"Please enter the code sent to <maskedContactInfo></maskedContactInfo> in order to transfer your points.",
|
||||
},
|
||||
@@ -139,10 +142,12 @@ export default async function SASxScandicOneTimePasswordPage(
|
||||
return (
|
||||
<OneTimePasswordForm
|
||||
heading={intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.oneTimePasswordHeading",
|
||||
defaultMessage: "Verification code",
|
||||
})}
|
||||
ingress={intentDescriptions[intent]}
|
||||
footnote={intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.oneTimePasswordDescription",
|
||||
defaultMessage: "This verification is needed for additional security.",
|
||||
})}
|
||||
otpLength={6}
|
||||
|
||||
@@ -48,6 +48,7 @@ export default async function SASxScandicTransferSuccessPage(
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
id: "transferEuroBonusPoints.successMessage",
|
||||
defaultMessage: "Point exchange completed!",
|
||||
})}
|
||||
</h1>
|
||||
@@ -62,6 +63,7 @@ export default async function SASxScandicTransferSuccessPage(
|
||||
>
|
||||
<Link href={partnerSas[params.lang]} color="none">
|
||||
{intl.formatMessage({
|
||||
id: "transferEuroBonusPoints.backToMyPagesButton",
|
||||
defaultMessage: "Go back to My Pages",
|
||||
})}
|
||||
</Link>
|
||||
@@ -91,6 +93,7 @@ async function TransactionCard({
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<h2>
|
||||
{intl.formatMessage({
|
||||
id: "transferEuroBonusPoints.transactionTitle",
|
||||
defaultMessage: "Your transaction",
|
||||
})}
|
||||
</h2>
|
||||
@@ -100,6 +103,7 @@ async function TransactionCard({
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
id: "transferEuroBonusPoints.pointsAddedTitle",
|
||||
defaultMessage: "Points added",
|
||||
})}
|
||||
</h3>
|
||||
@@ -113,6 +117,7 @@ async function TransactionCard({
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
id: "transferEuroBonusPoints.newTotalTitle",
|
||||
defaultMessage: "Your new total",
|
||||
})}
|
||||
</h3>
|
||||
@@ -128,6 +133,7 @@ async function TransactionCard({
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
id: "transferEuroBonusPoints.bonusNightAvailableTitle",
|
||||
defaultMessage: "You have enough points for a reward night!",
|
||||
})}
|
||||
</h3>
|
||||
@@ -135,6 +141,7 @@ async function TransactionCard({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "transferEuroBonusPoints.bonusNightAvailableDescription",
|
||||
defaultMessage:
|
||||
"Redeem your points for cozy stays, delicious meals at our restaurants, or hotel extras to elevate your stay!",
|
||||
})}
|
||||
@@ -152,6 +159,7 @@ async function TransactionCard({
|
||||
{/* TODO correct link */}
|
||||
<Link href={hotelreservation(lang)} color="none">
|
||||
{intl.formatMessage({
|
||||
id: "transferEuroBonusPoints.bookNowButton",
|
||||
defaultMessage: "Book now",
|
||||
})}
|
||||
{
|
||||
@@ -183,6 +191,7 @@ async function TotalPoints() {
|
||||
{"= "}
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "transferEuroBonusPoints.pointsResultText",
|
||||
defaultMessage: "{points, number} points",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@ export default async function SASxScandicUnlinkSuccessPage(
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h1>
|
||||
{intl.formatMessage({
|
||||
id: "unlinkEuroBonusAccount.successTitle",
|
||||
defaultMessage: "Your accounts are now unlinked",
|
||||
})}
|
||||
</h1>
|
||||
@@ -36,6 +37,7 @@ export default async function SASxScandicUnlinkSuccessPage(
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "linkEuroBonusAccount.redirectMyPagesMessage",
|
||||
defaultMessage: "Redirecting you to My Pages.",
|
||||
})}
|
||||
</p>
|
||||
|
||||
@@ -24,6 +24,7 @@ export default async function Layout(
|
||||
return (
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "webview.missingUserError",
|
||||
defaultMessage: "Error: No user could be loaded",
|
||||
})}
|
||||
</p>
|
||||
@@ -46,6 +47,7 @@ export default async function Layout(
|
||||
return (
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "webview.userNotFoundError",
|
||||
defaultMessage: "Error: user not found",
|
||||
})}
|
||||
</p>
|
||||
@@ -54,6 +56,7 @@ export default async function Layout(
|
||||
return (
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "webview.genericUserError",
|
||||
defaultMessage: "Unknown error occurred loading user",
|
||||
})}
|
||||
</p>
|
||||
|
||||
@@ -83,17 +83,20 @@ export default function CampaignHotelListingClient({
|
||||
}
|
||||
|
||||
let buttonText = intl.formatMessage({
|
||||
id: "common.showMore",
|
||||
defaultMessage: "Show more",
|
||||
})
|
||||
let iconDirection: MaterialIconProps["icon"] = "keyboard_arrow_down"
|
||||
|
||||
if (visibleCount === activeHotels.length) {
|
||||
buttonText = intl.formatMessage({
|
||||
id: "common.showLess",
|
||||
defaultMessage: "Show less",
|
||||
})
|
||||
iconDirection = "keyboard_arrow_up"
|
||||
} else if (canShowAll) {
|
||||
buttonText = intl.formatMessage({
|
||||
id: "common.showAll",
|
||||
defaultMessage: "Show all",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ export default function HotelListingItem({
|
||||
sizes="(min-width: 768px) 450px, 100vw"
|
||||
title={intl.formatMessage(
|
||||
{
|
||||
id: "common.imageGalleryWithTitle",
|
||||
defaultMessage: "{title} - Image gallery",
|
||||
},
|
||||
{ title: hotel.name }
|
||||
@@ -77,6 +78,7 @@ export default function HotelListingItem({
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "common.kmToCityCenter",
|
||||
defaultMessage: "{number} km to city center",
|
||||
},
|
||||
{
|
||||
@@ -121,6 +123,7 @@ export default function HotelListingItem({
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "destination.seeHotelDetails",
|
||||
defaultMessage: "See hotel details",
|
||||
})}
|
||||
</ButtonLink>
|
||||
|
||||
@@ -46,13 +46,15 @@ export default async function CampaignHotelListing({
|
||||
const sortItems: HotelSortItem[] = [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: "common.name",
|
||||
defaultMessage: "Name",
|
||||
}),
|
||||
value: HotelSortOption.Name,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Tripadvisor rating",
|
||||
id: "common.tripAdvisorRating",
|
||||
defaultMessage: "TripAdvisor rating",
|
||||
}),
|
||||
value: HotelSortOption.TripAdvisorRating,
|
||||
},
|
||||
|
||||
@@ -15,6 +15,7 @@ export default async function HowItWorks({ dynamic_content }: HowItWorksProps) {
|
||||
<section className={styles.container}>
|
||||
<Title level="h3">
|
||||
{intl.formatMessage({
|
||||
id: "common.howItWorks",
|
||||
defaultMessage: "How it works",
|
||||
})}
|
||||
</Title>
|
||||
|
||||
@@ -34,9 +34,11 @@ export default function Filter({
|
||||
items={countryFilters}
|
||||
defaultSelectedKey={""}
|
||||
label={intl.formatMessage({
|
||||
id: "common.country",
|
||||
defaultMessage: "Country",
|
||||
})}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "common.country",
|
||||
defaultMessage: "Country",
|
||||
})}
|
||||
name="country"
|
||||
@@ -46,9 +48,11 @@ export default function Filter({
|
||||
items={cityFilters}
|
||||
defaultSelectedKey={""}
|
||||
label={intl.formatMessage({
|
||||
id: "jobylonFeed.cityFilterLabel",
|
||||
defaultMessage: "Location (shown in local language)",
|
||||
})}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "jobylonFeed.cityFilterLabel",
|
||||
defaultMessage: "Location (shown in local language)",
|
||||
})}
|
||||
name="city"
|
||||
@@ -58,9 +62,11 @@ export default function Filter({
|
||||
items={departmentFilters}
|
||||
defaultSelectedKey={""}
|
||||
label={intl.formatMessage({
|
||||
id: "jobylonFeed.departmentFilterLabel",
|
||||
defaultMessage: "Hotel or office",
|
||||
})}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "jobylonFeed.departmentFilterLabel",
|
||||
defaultMessage: "Hotel or office",
|
||||
})}
|
||||
name="department"
|
||||
@@ -70,9 +76,11 @@ export default function Filter({
|
||||
items={categoryFilters}
|
||||
defaultSelectedKey={""}
|
||||
label={intl.formatMessage({
|
||||
id: "jobylonFeed.categoryFilterLabel",
|
||||
defaultMessage: "Category",
|
||||
})}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "jobylonFeed.categoryFilterLabel",
|
||||
defaultMessage: "Category",
|
||||
})}
|
||||
name="category"
|
||||
|
||||
@@ -33,6 +33,7 @@ export default function JobList({ allJobs }: JobListProps) {
|
||||
const countryFilters = [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: "jobylonFeed.allCountriesFilter",
|
||||
defaultMessage: "All countries",
|
||||
}),
|
||||
value: "",
|
||||
@@ -42,6 +43,7 @@ export default function JobList({ allJobs }: JobListProps) {
|
||||
const cityFilters = [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: "jobylonFeed.allLocationsFilter",
|
||||
defaultMessage: "All locations",
|
||||
}),
|
||||
value: "",
|
||||
@@ -51,6 +53,7 @@ export default function JobList({ allJobs }: JobListProps) {
|
||||
const departmentFilters = [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: "jobylonFeed.allDepartmentsFilter",
|
||||
defaultMessage: "All hotels and offices",
|
||||
}),
|
||||
value: "",
|
||||
@@ -60,6 +63,7 @@ export default function JobList({ allJobs }: JobListProps) {
|
||||
const categoryFilters = [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: "jobylonFeed.allCategoriesFilter",
|
||||
defaultMessage: "All categories",
|
||||
}),
|
||||
value: "",
|
||||
@@ -79,6 +83,7 @@ export default function JobList({ allJobs }: JobListProps) {
|
||||
<Subtitle type="two">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "jobylonFeed.resultCount",
|
||||
defaultMessage: "{count, plural, one {# Result} other {# Results}}",
|
||||
},
|
||||
{ count: state.jobs.length }
|
||||
|
||||
@@ -24,11 +24,13 @@ export default function JobylonCard({ job }: JobylonCardProps) {
|
||||
const deadlineText = job.toDate
|
||||
? intl.formatMessage(
|
||||
{
|
||||
id: "jobylonFeed.card.deadlineText",
|
||||
defaultMessage: "Deadline: {date}",
|
||||
},
|
||||
{ date: dt(job.toDate).locale(lang).format("Do MMMM") }
|
||||
)
|
||||
: intl.formatMessage({
|
||||
id: "jobylonFeed.card.openForApplication",
|
||||
defaultMessage: "Open for application",
|
||||
})
|
||||
|
||||
@@ -57,6 +59,7 @@ export default function JobylonCard({ job }: JobylonCardProps) {
|
||||
>
|
||||
<a href={job.url} target="_blank" rel="noopener noreferrer">
|
||||
{intl.formatMessage({
|
||||
id: "jobylonFeed.card.viewAndApplyButton",
|
||||
defaultMessage: "View & apply",
|
||||
})}
|
||||
<MaterialIcon icon="open_in_new" size={20} />
|
||||
|
||||
@@ -39,6 +39,7 @@ async function LevelCard({ level }: LevelCardProps) {
|
||||
|
||||
let pointsMsg: React.ReactNode = intl.formatMessage(
|
||||
{
|
||||
id: "common.pointsAmountPoints",
|
||||
defaultMessage: "{pointsAmount, number} points",
|
||||
},
|
||||
{ pointsAmount: level.required_points }
|
||||
@@ -47,6 +48,7 @@ async function LevelCard({ level }: LevelCardProps) {
|
||||
if (level.required_nights) {
|
||||
pointsMsg = intl.formatMessage(
|
||||
{
|
||||
id: "loyaltyLevelsBlock.pointsOrNights",
|
||||
defaultMessage:
|
||||
"{pointsAmount, number} points <highlight>or {nightsAmount, number} nights</highlight>",
|
||||
},
|
||||
@@ -68,6 +70,7 @@ async function LevelCard({ level }: LevelCardProps) {
|
||||
>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "common.membershipLevelWithValue",
|
||||
defaultMessage: "Level {level}",
|
||||
},
|
||||
{ level: level.user_facing_tag }
|
||||
|
||||
@@ -28,6 +28,7 @@ export function CookieConsentButton() {
|
||||
className={styles.cookieConsentButton}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "cookieConsent.manageCookiesButton",
|
||||
defaultMessage: "Manage cookies",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
|
||||
|
||||
@@ -18,27 +18,35 @@ export default async function MyPagesOverviewShortcuts() {
|
||||
|
||||
const MyPagesLinkTranslationMap: Record<MyPagesLinkKey, string> = {
|
||||
overview: intl.formatMessage({
|
||||
id: "common.overview",
|
||||
defaultMessage: "Overview",
|
||||
}),
|
||||
points: intl.formatMessage({
|
||||
id: "common.myPoints",
|
||||
defaultMessage: "My points",
|
||||
}),
|
||||
stays: intl.formatMessage({
|
||||
id: "common.myStays",
|
||||
defaultMessage: "My stays",
|
||||
}),
|
||||
benefits: intl.formatMessage({
|
||||
id: "common.myBenefits",
|
||||
defaultMessage: "My benefits",
|
||||
}),
|
||||
partnerSas: intl.formatMessage({
|
||||
id: "partnerSas.sasEuroBonus",
|
||||
defaultMessage: "SAS EuroBonus",
|
||||
}),
|
||||
teamMemberCard: intl.formatMessage({
|
||||
id: "common.teamMemberCard",
|
||||
defaultMessage: "Team Member Card",
|
||||
}),
|
||||
scandicFriends: intl.formatMessage({
|
||||
id: "common.aboutScandicFriends",
|
||||
defaultMessage: "About Scandic Friends",
|
||||
}),
|
||||
profile: intl.formatMessage({
|
||||
id: "common.myProfile",
|
||||
defaultMessage: "My profile",
|
||||
}),
|
||||
}
|
||||
@@ -82,14 +90,26 @@ export default async function MyPagesOverviewShortcuts() {
|
||||
})),
|
||||
{
|
||||
openInNewTab: false,
|
||||
text: intl.formatMessage({ defaultMessage: "Partner benefits" }),
|
||||
title: intl.formatMessage({ defaultMessage: "Partner benefits" }),
|
||||
text: intl.formatMessage({
|
||||
id: "myPagesOverviewShortcuts.partnerBenefits",
|
||||
defaultMessage: "Partner benefits",
|
||||
}),
|
||||
title: intl.formatMessage({
|
||||
id: "myPagesOverviewShortcuts.partnerBenefits",
|
||||
defaultMessage: "Partner benefits",
|
||||
}),
|
||||
url: webHrefs.partners[lang],
|
||||
},
|
||||
{
|
||||
openInNewTab: false,
|
||||
text: intl.formatMessage({ defaultMessage: "Scandic Friends FAQ" }),
|
||||
title: intl.formatMessage({ defaultMessage: "Scandic Friends FAQ" }),
|
||||
text: intl.formatMessage({
|
||||
id: "common.scandicFriendsFaq",
|
||||
defaultMessage: "Scandic Friends FAQ",
|
||||
}),
|
||||
title: intl.formatMessage({
|
||||
id: "common.scandicFriendsFaq",
|
||||
defaultMessage: "Scandic Friends FAQ",
|
||||
}),
|
||||
url: webHrefs.faq[lang],
|
||||
},
|
||||
]
|
||||
@@ -103,6 +123,7 @@ export default async function MyPagesOverviewShortcuts() {
|
||||
<div className={styles.column}>
|
||||
<SectionHeader
|
||||
title={intl.formatMessage({
|
||||
id: "myPagesOverviewShortcuts.yourMembership",
|
||||
defaultMessage: "Your membership",
|
||||
})}
|
||||
headingAs="h4"
|
||||
@@ -116,6 +137,7 @@ export default async function MyPagesOverviewShortcuts() {
|
||||
<div className={styles.column}>
|
||||
<SectionHeader
|
||||
title={intl.formatMessage({
|
||||
id: "myPagesOverviewShortcuts.scandicFriendsLinks",
|
||||
defaultMessage: "Scandic Friends Links",
|
||||
})}
|
||||
headingAs="h4"
|
||||
|
||||
@@ -18,12 +18,14 @@ export default function CopyButton({ membershipNumber }: CopyButtonProps) {
|
||||
navigator.clipboard.writeText(membershipNumber)
|
||||
toast.success(
|
||||
intl.formatMessage({
|
||||
id: "myPages.membershipIdCopied",
|
||||
defaultMessage: "Membership ID copied to clipboard",
|
||||
})
|
||||
)
|
||||
} catch {
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "errorMessage.copyFailed",
|
||||
defaultMessage: "Failed to copy",
|
||||
})
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ export default async function MembershipNumber({
|
||||
<div className={classNames}>
|
||||
<Caption color="pale">
|
||||
{intl.formatMessage({
|
||||
id: "overview.membershipNumber.label",
|
||||
defaultMessage: "Membership ID:",
|
||||
})}
|
||||
</Caption>
|
||||
@@ -29,6 +30,7 @@ export default async function MembershipNumber({
|
||||
<code data-hj-suppress>
|
||||
{membership?.membershipNumber ??
|
||||
intl.formatMessage({
|
||||
id: "common.NA",
|
||||
defaultMessage: "N/A",
|
||||
})}
|
||||
</code>
|
||||
|
||||
@@ -24,13 +24,12 @@ export default async function Friend({
|
||||
const isHighestLevel = isHighestMembership(membership.membershipLevel)
|
||||
|
||||
const lvlMessageHighest = intl.formatMessage({
|
||||
id: "overview.friend.highestLevel",
|
||||
defaultMessage: "Highest level",
|
||||
})
|
||||
|
||||
const lvlMessageLevel = intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "Level {level}",
|
||||
},
|
||||
{ id: "common.membershipLevelWithValue", defaultMessage: "Level {level}" },
|
||||
{ level: membershipLevels[membership.membershipLevel] }
|
||||
)
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ export default async function SasBoostStatus({
|
||||
|
||||
const sasBoostExpiryText = intl.formatMessage(
|
||||
{
|
||||
id: "membershipOverViewCard.sasBoostedUntilDate",
|
||||
defaultMessage: "Boosted by SAS until {date}",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ export default async function MembershipOverviewCard({
|
||||
const pointsToSpendText =
|
||||
typeof user.membership.currentPoints === "number"
|
||||
? intl.formatNumber(user.membership.currentPoints)
|
||||
: intl.formatMessage({ defaultMessage: "N/A" })
|
||||
: intl.formatMessage({ id: "common.NA", defaultMessage: "N/A" })
|
||||
|
||||
const sasMembership = user.loyalty
|
||||
? getEurobonusMembership(user.loyalty)
|
||||
@@ -53,6 +53,7 @@ export default async function MembershipOverviewCard({
|
||||
<h2 className={styles.levelText} id="membership-level">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "common.membershipLevelWithValue",
|
||||
defaultMessage: "Level {level}",
|
||||
},
|
||||
{ level: membershipLevels[user.membership.membershipLevel] }
|
||||
@@ -79,6 +80,7 @@ export default async function MembershipOverviewCard({
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<h3 className={styles.pointsLabel}>
|
||||
{intl.formatMessage({
|
||||
id: "common.pointsToSpend",
|
||||
defaultMessage: "Points to spend",
|
||||
})}
|
||||
</h3>
|
||||
|
||||
@@ -26,6 +26,7 @@ export default async function ExpiringPoints({ user }: UserProps) {
|
||||
<Body color="white" textTransform="bold" textAlign="center">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "overview.stats.expiringPoints",
|
||||
defaultMessage: "{points} spendable points expiring by {date}",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -28,9 +28,11 @@ export default async function Points({ user }: UserProps) {
|
||||
<PointsColumn
|
||||
value={membership?.currentPoints}
|
||||
title={intl.formatMessage({
|
||||
id: "stats.points.yourPointsToSpend",
|
||||
defaultMessage: "Your points to spend",
|
||||
})}
|
||||
subtitle={intl.formatMessage({
|
||||
id: "stats.points.asOfToday",
|
||||
defaultMessage: "as of today",
|
||||
})}
|
||||
/>
|
||||
@@ -38,10 +40,12 @@ export default async function Points({ user }: UserProps) {
|
||||
<PointsColumn
|
||||
value={membership?.pointsRequiredToNextlevel}
|
||||
title={intl.formatMessage({
|
||||
id: "stats.points.pointsNeededToLevelUp",
|
||||
defaultMessage: "Points needed to level up",
|
||||
})}
|
||||
subtitle={intl.formatMessage(
|
||||
{
|
||||
id: "stats.points.nextLevel",
|
||||
defaultMessage: "next level: {nextLevel}",
|
||||
},
|
||||
{ nextLevel: nextLevel.name }
|
||||
|
||||
@@ -34,6 +34,7 @@ export default async function UserBaseInfo({ user }: UserBaseInfoProps) {
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
id: "overview.membershipNumber.label",
|
||||
defaultMessage: "Membership ID:",
|
||||
})}
|
||||
</span>
|
||||
@@ -46,6 +47,7 @@ export default async function UserBaseInfo({ user }: UserBaseInfoProps) {
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<span className={styles.noMembership}>
|
||||
{intl.formatMessage({
|
||||
id: "common.NA",
|
||||
defaultMessage: "N/A",
|
||||
})}
|
||||
</span>
|
||||
|
||||
@@ -55,6 +55,7 @@ export default async function Overview({
|
||||
<>
|
||||
<MaterialIcon icon="id_card" size={24} color="CurrentColor" />
|
||||
{intl.formatMessage({
|
||||
id: "dtmc.showTeamMemberCard",
|
||||
defaultMessage: "Show Team Member Card",
|
||||
})}
|
||||
</>
|
||||
|
||||
@@ -98,10 +98,12 @@ export default function OverviewTableClient({
|
||||
/>
|
||||
<DeprecatedSelect
|
||||
aria-label={intl.formatMessage({
|
||||
id: "common.level",
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
name={`reward` + column}
|
||||
label={intl.formatMessage({
|
||||
id: "common.level",
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
items={levelOptions}
|
||||
@@ -137,10 +139,12 @@ export default function OverviewTableClient({
|
||||
return (
|
||||
<DeprecatedSelect
|
||||
aria-label={intl.formatMessage({
|
||||
id: "common.level",
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
name={`reward` + column}
|
||||
label={intl.formatMessage({
|
||||
id: "common.level",
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
items={levelOptions}
|
||||
|
||||
@@ -13,6 +13,7 @@ export default function LevelSummary({
|
||||
const pointsMsg: React.ReactNode = level.required_nights
|
||||
? intl.formatMessage(
|
||||
{
|
||||
id: "overviewTable.levelSummary.pointsOrNights",
|
||||
defaultMessage:
|
||||
"{pointsAmount, number} points or {nightsAmount, number} nights",
|
||||
},
|
||||
@@ -23,6 +24,7 @@ export default function LevelSummary({
|
||||
)
|
||||
: intl.formatMessage(
|
||||
{
|
||||
id: "common.pointsAmountPoints",
|
||||
defaultMessage: "{pointsAmount, number} points",
|
||||
},
|
||||
{ pointsAmount: level.required_points }
|
||||
|
||||
@@ -14,6 +14,7 @@ export default function YourLevel() {
|
||||
textAlign={"center"}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "overviewTable.yourLevel",
|
||||
defaultMessage: "Your level",
|
||||
})}
|
||||
</BiroScript>
|
||||
|
||||
@@ -21,6 +21,7 @@ export default function ClaimPoints() {
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "points.claimPoints.missingPreviousStay",
|
||||
defaultMessage: "Missing a previous stay?",
|
||||
})}
|
||||
</p>
|
||||
@@ -32,7 +33,10 @@ export default function ClaimPoints() {
|
||||
size="Small"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
>
|
||||
{intl.formatMessage({ defaultMessage: "Claim points" })}
|
||||
{intl.formatMessage({
|
||||
id: "points.claimPoints.cta",
|
||||
defaultMessage: "Claim points",
|
||||
})}
|
||||
<MaterialIcon icon="open_in_new" size={20} color="CurrentColor" />
|
||||
</ButtonLink>
|
||||
</div>
|
||||
|
||||
@@ -36,6 +36,7 @@ export default function AwardPoints({
|
||||
{isCalculated
|
||||
? intl.formatNumber(awardPoints)
|
||||
: intl.formatMessage({
|
||||
id: "earnAndBurn.awardPoints.pointsBeingCalculated",
|
||||
defaultMessage: "Points being calculated",
|
||||
})}
|
||||
</span>
|
||||
|
||||
@@ -25,6 +25,7 @@ export default function Row({ transaction }: RowProps) {
|
||||
|
||||
const nightsMsg = intl.formatMessage(
|
||||
{
|
||||
id: "booking.numberOfNights",
|
||||
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
|
||||
},
|
||||
{
|
||||
@@ -34,7 +35,10 @@ export default function Row({ transaction }: RowProps) {
|
||||
let description =
|
||||
transaction.confirmationNumber === "non-transactional" &&
|
||||
transaction.nights === 0
|
||||
? intl.formatMessage({ defaultMessage: "Points activity" })
|
||||
? intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.pointsActivity",
|
||||
defaultMessage: "Points activity",
|
||||
})
|
||||
: transaction.hotelName && transaction.city
|
||||
? `${transaction.hotelName}, ${transaction.city} ${nightsMsg}`
|
||||
: `${nightsMsg}`
|
||||
@@ -44,37 +48,44 @@ export default function Row({ transaction }: RowProps) {
|
||||
case Transactions.rewardType.stayAdj:
|
||||
if (transaction.hotelId === "ORS") {
|
||||
description = intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.formerScandicHotel",
|
||||
defaultMessage: "Former Scandic Hotel",
|
||||
})
|
||||
}
|
||||
if (transaction.confirmationNumber === "BALFWD") {
|
||||
description = intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.pointsEarnedPriorMay2021",
|
||||
defaultMessage: "Points earned prior to May 1, 2021",
|
||||
})
|
||||
}
|
||||
break
|
||||
case Transactions.rewardType.ancillary:
|
||||
description = intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.extrasToBooking",
|
||||
defaultMessage: "Extras to your booking",
|
||||
})
|
||||
break
|
||||
case Transactions.rewardType.enrollment:
|
||||
description = intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.signUpBonus",
|
||||
defaultMessage: "Sign up bonus",
|
||||
})
|
||||
break
|
||||
case Transactions.rewardType.mastercard_points:
|
||||
description = intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.scandicFriendsMastercard",
|
||||
defaultMessage: "Scandic Friends Mastercard",
|
||||
})
|
||||
break
|
||||
case Transactions.rewardType.tui_points:
|
||||
description = intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.tuiPoints",
|
||||
defaultMessage: "TUI Points",
|
||||
})
|
||||
|
||||
case Transactions.rewardType.pointShop:
|
||||
description = intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.pointShop",
|
||||
defaultMessage: "Scandic Friends Point Shop",
|
||||
})
|
||||
break
|
||||
|
||||
@@ -16,15 +16,19 @@ export default function ClientTable({ transactions }: ClientTableProps) {
|
||||
|
||||
const tableHeadings = [
|
||||
intl.formatMessage({
|
||||
id: "common.points",
|
||||
defaultMessage: "Points",
|
||||
}),
|
||||
intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.description",
|
||||
defaultMessage: "Description",
|
||||
}),
|
||||
intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.bookingNumberReference",
|
||||
defaultMessage: "Booking number / Reference",
|
||||
}),
|
||||
intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.date",
|
||||
defaultMessage: "Date",
|
||||
}),
|
||||
]
|
||||
@@ -55,6 +59,7 @@ export default function ClientTable({ transactions }: ClientTableProps) {
|
||||
<Table.TR className={styles.placeholder}>
|
||||
<Table.TD colSpan={tableHeadings.length}>
|
||||
{intl.formatMessage({
|
||||
id: "earnAndBurn.journeyTable.noTransactions",
|
||||
defaultMessage: "No transactions available",
|
||||
})}
|
||||
</Table.TD>
|
||||
|
||||
@@ -22,10 +22,9 @@ export default function ExpiringPointsTable({
|
||||
const expiration = dt(expirationDate).locale(lang).format("DD MMM YYYY")
|
||||
|
||||
const tableHeadings = [
|
||||
intl.formatMessage({ id: "common.points", defaultMessage: "Points" }),
|
||||
intl.formatMessage({
|
||||
defaultMessage: "Points",
|
||||
}),
|
||||
intl.formatMessage({
|
||||
id: "points.expiringPointsTable.expirationDate",
|
||||
defaultMessage: "Expiration Date",
|
||||
}),
|
||||
]
|
||||
|
||||
@@ -32,11 +32,14 @@ export default function ExpiringPointsSeeAllButton({
|
||||
typography="Body/Paragraph/mdBold"
|
||||
onPress={() => setIsOpen(true)}
|
||||
>
|
||||
{intl.formatMessage({ defaultMessage: "See all" })}
|
||||
{intl.formatMessage({ id: "common.seeAll", defaultMessage: "See all" })}
|
||||
<MaterialIcon icon="chevron_right" color="CurrentColor" />
|
||||
</Button>
|
||||
<SidePeekSelfControlled
|
||||
title={intl.formatMessage({ defaultMessage: "Expiring points" })}
|
||||
title={intl.formatMessage({
|
||||
id: "points.pointsToSpendCard.expiringPointsTitle",
|
||||
defaultMessage: "Expiring points",
|
||||
})}
|
||||
isOpen={isOpen}
|
||||
onClose={() => setIsOpen(false)}
|
||||
>
|
||||
@@ -44,6 +47,7 @@ export default function ExpiringPointsSeeAllButton({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "points.pointsToSpendCard.expiringPointsInfo",
|
||||
defaultMessage:
|
||||
"Points expire three years after they are earned, on the last day of that month. Expiring points do not affect your level.",
|
||||
})}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
.pointsLabel {
|
||||
color: var(--Text-Brand-OnPrimary-1-Heading);
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.description {
|
||||
|
||||
@@ -52,6 +52,7 @@ export default async function PointsToSpendCard({
|
||||
<Typography variant="Title/xs">
|
||||
<h2 id="points-to-spend-card-title" className={styles.title}>
|
||||
{intl.formatMessage({
|
||||
id: "common.pointsToSpend",
|
||||
defaultMessage: "Points to spend",
|
||||
})}
|
||||
</h2>
|
||||
@@ -66,6 +67,7 @@ export default async function PointsToSpendCard({
|
||||
<Typography variant="Title/Overline/sm">
|
||||
<span className={styles.pointsLabel}>
|
||||
{intl.formatMessage({
|
||||
id: "common.points",
|
||||
defaultMessage: "Points",
|
||||
})}
|
||||
</span>
|
||||
@@ -75,6 +77,7 @@ export default async function PointsToSpendCard({
|
||||
{hasPointsToSpend && (
|
||||
<ButtonLink href={spendPoints[lang]} target="_blank" variant="Text">
|
||||
{intl.formatMessage({
|
||||
id: "points.pointsToSpendCard.howToSpendCta",
|
||||
defaultMessage: "How to spend points",
|
||||
})}
|
||||
<MaterialIcon
|
||||
@@ -91,6 +94,7 @@ export default async function PointsToSpendCard({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p className={styles.descriptionText}>
|
||||
{intl.formatMessage({
|
||||
id: "points.pointsToSpendCard.description",
|
||||
defaultMessage:
|
||||
"Earn points by staying at Scandic. Turn your points into free nights and memorable experiences.",
|
||||
})}
|
||||
@@ -108,6 +112,7 @@ export default async function PointsToSpendCard({
|
||||
<p className={styles.expiringPoints}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "points.pointsToSpendCard.expiringPointsText",
|
||||
defaultMessage: "{expiringPoints} points expiring",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -24,6 +24,7 @@ export function getExpiryLabel(
|
||||
if (daysUntilExpiry <= DAYS_UNTIL_EXPIRY_WARNING) {
|
||||
return intl.formatMessage(
|
||||
{
|
||||
id: "points.pointsToSpendCard.inDays",
|
||||
defaultMessage: "In {days} days",
|
||||
},
|
||||
{
|
||||
@@ -33,6 +34,7 @@ export function getExpiryLabel(
|
||||
} else {
|
||||
return intl.formatMessage(
|
||||
{
|
||||
id: "points.pointsToSpendCard.onDate",
|
||||
defaultMessage: "on {expiryDate}",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -50,6 +50,7 @@ export default async function NextLevelRewardsBlock({
|
||||
<Chip>
|
||||
<Lock height={16} />
|
||||
{intl.formatMessage({
|
||||
id: "rewards.nextLevel.levelUpToUnlock",
|
||||
defaultMessage: "Level up to unlock",
|
||||
})}
|
||||
</Chip>
|
||||
@@ -57,6 +58,7 @@ export default async function NextLevelRewardsBlock({
|
||||
<Body color="peach50" textAlign="center">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "rewards.nextLevel.asOurLevel",
|
||||
defaultMessage: "As our {level}",
|
||||
},
|
||||
{ level: nextLevelRewards.level?.name }
|
||||
|
||||
@@ -27,6 +27,7 @@ export default function ActiveRedeemedBadge() {
|
||||
</motion.div>
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
id: "rewards.active",
|
||||
defaultMessage: "Active",
|
||||
})}
|
||||
</Caption>
|
||||
|
||||
@@ -17,16 +17,19 @@ export function ConfirmClose({ close }: { close: () => void }) {
|
||||
<div className={styles.modalContent}>
|
||||
<Title level="h3" textAlign="center" textTransform="regular">
|
||||
{intl.formatMessage({
|
||||
id: "redeem.confirmClose.title",
|
||||
defaultMessage: "If you close this your benefit will be removed",
|
||||
})}
|
||||
</Title>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "redeem.confirmClose.question",
|
||||
defaultMessage: "Have you showed this benefit to the hotel staff?",
|
||||
})}
|
||||
</Body>
|
||||
<Body>
|
||||
{intl.formatMessage({
|
||||
id: "redeem.confirmClose.info",
|
||||
defaultMessage:
|
||||
"If not, please go back and do so before you close this. Once you close this your benefit will be void and removed from My Benefits.",
|
||||
})}
|
||||
@@ -39,11 +42,13 @@ export function ConfirmClose({ close }: { close: () => void }) {
|
||||
theme="base"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "redeem.confirmClose.goBack",
|
||||
defaultMessage: "No, go back",
|
||||
})}
|
||||
</Button>
|
||||
<Button onClick={close} intent="secondary" theme="base">
|
||||
{intl.formatMessage({
|
||||
id: "redeem.confirmClose.confirm",
|
||||
defaultMessage: "Yes, close and remove benefit",
|
||||
})}
|
||||
</Button>
|
||||
|
||||
@@ -29,6 +29,7 @@ export default function Campaign({ reward }: { reward: Campaign }) {
|
||||
<div className={styles.rewardBadge}>
|
||||
<Caption textAlign="center" color="uiTextHighContrast" type="bold">
|
||||
{intl.formatMessage({
|
||||
id: "redeemFlow.promoCode",
|
||||
defaultMessage: "Promo code",
|
||||
})}
|
||||
</Caption>
|
||||
@@ -44,12 +45,14 @@ export default function Campaign({ reward }: { reward: Campaign }) {
|
||||
navigator.clipboard.writeText(reward.operaRewardId)
|
||||
toast.success(
|
||||
intl.formatMessage({
|
||||
id: "redeemFlow.copiedToClipboard",
|
||||
defaultMessage: "Copied to clipboard",
|
||||
})
|
||||
)
|
||||
} catch {
|
||||
toast.error(
|
||||
intl.formatMessage({
|
||||
id: "errorMessage.copyFailed",
|
||||
defaultMessage: "Failed to copy",
|
||||
})
|
||||
)
|
||||
@@ -63,6 +66,7 @@ export default function Campaign({ reward }: { reward: Campaign }) {
|
||||
>
|
||||
<MaterialIcon icon="content_copy" color="CurrentColor" />
|
||||
{intl.formatMessage({
|
||||
id: "redeemFlow.copyPromotionCode",
|
||||
defaultMessage: "Copy promotion code",
|
||||
})}
|
||||
</Button>
|
||||
|
||||
@@ -88,6 +88,7 @@ export default function Tier({
|
||||
theme="base"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "redeemFlow.redeemBenefit",
|
||||
defaultMessage: "Redeem benefit",
|
||||
})}
|
||||
</Button>
|
||||
@@ -103,6 +104,7 @@ export default function Tier({
|
||||
theme="base"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "redeemFlow.yesRedeem",
|
||||
defaultMessage: "Yes, redeem",
|
||||
})}
|
||||
</Button>
|
||||
@@ -112,6 +114,7 @@ export default function Tier({
|
||||
theme="base"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "common.goBack",
|
||||
defaultMessage: "Go back",
|
||||
})}
|
||||
</Button>
|
||||
|
||||
@@ -16,6 +16,7 @@ export default function MembershipNumberBadge({
|
||||
<Caption textAlign="center" color="uiTextHighContrast">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "rewards.membershipId",
|
||||
defaultMessage: "Membership ID: {id}",
|
||||
},
|
||||
{ id: membershipNumber }
|
||||
|
||||
@@ -23,6 +23,7 @@ export default function TimedRedeemedBadge() {
|
||||
<MaterialIcon icon="check_circle" color="Icon/Feedback/Success" />
|
||||
<Caption>
|
||||
{intl.formatMessage({
|
||||
id: "rewards.redeemed.validThrough",
|
||||
defaultMessage: "Redeemed & valid through:",
|
||||
})}
|
||||
</Caption>
|
||||
|
||||
@@ -78,9 +78,11 @@ export default function Redeem({ reward, membershipNumber }: RedeemProps) {
|
||||
>
|
||||
{reward.redeemLocation === "Non-redeemable"
|
||||
? intl.formatMessage({
|
||||
id: "rewards.howToUse",
|
||||
defaultMessage: "How to use",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
id: "common.open",
|
||||
defaultMessage: "Open",
|
||||
})}
|
||||
</Button>
|
||||
|
||||
@@ -23,14 +23,17 @@ export default function ScriptedRewardText({
|
||||
}
|
||||
case "Campaign":
|
||||
return intl.formatMessage({
|
||||
id: "booking.campaign",
|
||||
defaultMessage: "Campaign",
|
||||
})
|
||||
case "Surprise":
|
||||
return intl.formatMessage({
|
||||
id: "rewards.surprise",
|
||||
defaultMessage: "Surprise!",
|
||||
})
|
||||
case "Member-voucher":
|
||||
return intl.formatMessage({
|
||||
id: "rewards.voucher",
|
||||
defaultMessage: "Voucher",
|
||||
})
|
||||
default:
|
||||
|
||||
@@ -28,12 +28,14 @@ export default async function SASLinkAccountBanner(
|
||||
}
|
||||
|
||||
const headingText = intl.formatMessage({
|
||||
id: "sas.linkAccountBanner.earnFlightsWithNights",
|
||||
defaultMessage: "Earn flights with nights",
|
||||
})
|
||||
|
||||
const buttonText =
|
||||
props.link?.text ||
|
||||
intl.formatMessage({
|
||||
id: "sas.linkAccountBanner.readMoreAndLinkAccounts",
|
||||
defaultMessage: "Read more and link accounts",
|
||||
})
|
||||
|
||||
@@ -41,6 +43,7 @@ export default async function SASLinkAccountBanner(
|
||||
return (
|
||||
<span key="scandic-friends" className={styles.brandName}>
|
||||
{intl.formatMessage({
|
||||
id: "common.scandicFriends",
|
||||
defaultMessage: "Scandic Friends",
|
||||
})}
|
||||
</span>
|
||||
@@ -51,6 +54,7 @@ export default async function SASLinkAccountBanner(
|
||||
return (
|
||||
<span key="sas-eurobonus" className={styles.brandName}>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.sasEuroBonus",
|
||||
defaultMessage: "SAS EuroBonus",
|
||||
})}
|
||||
</span>
|
||||
@@ -59,6 +63,7 @@ export default async function SASLinkAccountBanner(
|
||||
|
||||
const descriptionText = intl.formatMessage(
|
||||
{
|
||||
id: "sas.linkAccountBanner.description",
|
||||
defaultMessage:
|
||||
"Link your <scandicFriends></scandicFriends> and <sasEuroBonus></sasEuroBonus> accounts to earn, use and exchange points between memberships",
|
||||
},
|
||||
|
||||
@@ -17,22 +17,27 @@ export function UnlinkSAS() {
|
||||
return (
|
||||
<Dialog
|
||||
titleText={intl.formatMessage({
|
||||
id: "partnerSas.unlinkAccount",
|
||||
defaultMessage: "Are you sure you want to unlink your account?",
|
||||
})}
|
||||
bodyText={intl.formatMessage({
|
||||
id: "partnerSas.unlinkAccountWarning",
|
||||
defaultMessage:
|
||||
"This will remove any membership level upgrades gained from the linking. You can re-link your accounts again in 30 days.",
|
||||
})}
|
||||
cancelButtonText={intl.formatMessage({
|
||||
id: "common.goBack",
|
||||
defaultMessage: "Go back",
|
||||
})}
|
||||
proceedText={intl.formatMessage({
|
||||
id: "partnerSas.yesUnlinkAccount",
|
||||
defaultMessage: "Yes, unlink my accounts",
|
||||
})}
|
||||
proceedHref={`/${params.lang}/sas-x-scandic/login?intent=unlink`}
|
||||
trigger={
|
||||
<Button intent="text" theme="base">
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.unlinkAccounts",
|
||||
defaultMessage: "Unlink accounts",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||
|
||||
@@ -52,6 +52,7 @@ export default async function SASLinkedAccount({
|
||||
<p className={styles.caption}>
|
||||
<MaterialIcon icon="info" size={20} />
|
||||
{intl.formatMessage({
|
||||
id: "sas.linkedAccounts.changeDelayInfo",
|
||||
defaultMessage:
|
||||
"Changes in your level match can take up to 24 hours to be displayed.",
|
||||
})}
|
||||
@@ -96,12 +97,14 @@ async function MatchedAccountInfo() {
|
||||
<div className={styles.stack}>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
id: "sas.linkedAccounts.linkedAccount",
|
||||
defaultMessage: "Linked account",
|
||||
})}
|
||||
</Label>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.sasEuroBonus",
|
||||
defaultMessage: "SAS EuroBonus",
|
||||
})}
|
||||
</p>
|
||||
@@ -110,6 +113,7 @@ async function MatchedAccountInfo() {
|
||||
<div className={styles.stack}>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
id: "common.level",
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
</Label>
|
||||
@@ -120,6 +124,7 @@ async function MatchedAccountInfo() {
|
||||
<div className={cx(styles.stack, styles.accountMemberNumber)}>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
id: "common.membershipId",
|
||||
defaultMessage: "Membership ID",
|
||||
})}
|
||||
</Label>
|
||||
@@ -154,12 +159,14 @@ async function MatchedAccountInfoSkeleton() {
|
||||
<div className={styles.stack}>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
id: "sas.linkedAccounts.linkedAccount",
|
||||
defaultMessage: "Linked account",
|
||||
})}
|
||||
</Label>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.sasEuroBonus",
|
||||
defaultMessage: "SAS EuroBonus",
|
||||
})}
|
||||
</p>
|
||||
@@ -168,6 +175,7 @@ async function MatchedAccountInfoSkeleton() {
|
||||
<div className={styles.stack}>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
id: "common.level",
|
||||
defaultMessage: "Level",
|
||||
})}
|
||||
</Label>
|
||||
@@ -176,6 +184,7 @@ async function MatchedAccountInfoSkeleton() {
|
||||
<div className={cx(styles.stack, styles.accountMemberNumber)}>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
id: "common.membershipId",
|
||||
defaultMessage: "Membership ID",
|
||||
})}
|
||||
</Label>
|
||||
@@ -219,6 +228,7 @@ async function TierMatchMessage({
|
||||
const messageMap: Record<MatchState, ReactNode> = {
|
||||
boostedBySAS: intl.formatMessage(
|
||||
{
|
||||
id: "sas.linkedAccounts.euroBonusSasUpgradedText",
|
||||
defaultMessage:
|
||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> has upgraded your Scandic Friends level to <scandicMark>{scandicLevelName}</scandicMark>.",
|
||||
},
|
||||
@@ -226,6 +236,7 @@ async function TierMatchMessage({
|
||||
),
|
||||
boostedByScandic: intl.formatMessage(
|
||||
{
|
||||
id: "sas.linkedAccounts.scandicFriendsUpgradedText",
|
||||
defaultMessage:
|
||||
"Your Scandic Friends level <scandicMark>{scandicLevelName}</scandicMark> has upgraded you to <sasMark>EuroBonus {sasLevelName}</sasMark>.",
|
||||
},
|
||||
@@ -233,6 +244,7 @@ async function TierMatchMessage({
|
||||
),
|
||||
noBoost: intl.formatMessage(
|
||||
{
|
||||
id: "sas.linkedAccounts.euroBonusSasText",
|
||||
defaultMessage:
|
||||
"<sasMark>EuroBonus {sasLevelName}</sasMark> and <scandicMark>{scandicLevelName}</scandicMark> are equally matched. Level up in one of your memberships to qualify for an upgrade!",
|
||||
},
|
||||
@@ -250,6 +262,7 @@ async function TierMatchMessage({
|
||||
<div className={styles.stack}>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
id: "sas.linkedAccounts.levelMatchStatus",
|
||||
defaultMessage: "Level match status",
|
||||
})}
|
||||
</Label>
|
||||
@@ -270,6 +283,7 @@ async function TierMatchMessageSkeleton() {
|
||||
<div className={styles.stack}>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
id: "sas.linkedAccounts.levelMatchStatus",
|
||||
defaultMessage: "Level match status",
|
||||
})}
|
||||
</Label>
|
||||
@@ -307,6 +321,7 @@ async function TierMatchExpiration({
|
||||
<div className={cx(styles.stack, styles.textRight)}>
|
||||
<Label>
|
||||
{intl.formatMessage({
|
||||
id: "sas.linkedAccounts.upgradeValidUntil",
|
||||
defaultMessage: "Upgrade valid until",
|
||||
})}
|
||||
</Label>
|
||||
|
||||
@@ -80,6 +80,7 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Tag/sm">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.exchangeFrom",
|
||||
defaultMessage: "Exchange from",
|
||||
})}
|
||||
</p>
|
||||
@@ -89,6 +90,7 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.sasEuroBonus",
|
||||
defaultMessage: "SAS EuroBonus",
|
||||
})}
|
||||
</p>
|
||||
@@ -98,6 +100,7 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Tag/sm">
|
||||
<p className={styles.balanceLabel}>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.balance",
|
||||
defaultMessage: "Balance",
|
||||
})}
|
||||
</p>
|
||||
@@ -113,6 +116,7 @@ async function TransferPointsFormContent({
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "partnerSas.pointsWithValue",
|
||||
defaultMessage: "{points, number} p",
|
||||
},
|
||||
{ points: sasPoints }
|
||||
@@ -127,6 +131,7 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.noPointsToTransfer",
|
||||
defaultMessage: "You have no points to transfer.",
|
||||
})}
|
||||
</p>
|
||||
@@ -140,6 +145,7 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Tag/sm">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.exchangeTo",
|
||||
defaultMessage: "Exchange to",
|
||||
})}
|
||||
</p>
|
||||
@@ -148,6 +154,7 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "common.scandicFriends",
|
||||
defaultMessage: "Scandic Friends",
|
||||
})}
|
||||
</p>
|
||||
@@ -157,6 +164,7 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Tag/sm">
|
||||
<p className={styles.balanceLabel}>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.balance",
|
||||
defaultMessage: "Balance",
|
||||
})}
|
||||
</p>
|
||||
@@ -172,6 +180,7 @@ async function TransferPointsFormContent({
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "partnerSas.pointsWithValue",
|
||||
defaultMessage: "{points, number} p",
|
||||
},
|
||||
{ points: scandicPoints }
|
||||
@@ -191,6 +200,7 @@ async function TransferPointsFormContent({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p style={{ color: "var(--Text-Tertiary)" }}>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.exchangedPointsNotLevelQualifying",
|
||||
defaultMessage: "Exchanged points will not be level-qualifying.",
|
||||
})}
|
||||
</p>
|
||||
|
||||
@@ -67,6 +67,7 @@ export function TransferPointsFormClient({
|
||||
// Set max value to 1 if sasPoints is 0 since slider requires a range
|
||||
maxValue={hasNoSasPoints ? 1 : sasPoints}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "partnerSas.ebPointsToExchange",
|
||||
defaultMessage: "EB points to exchange",
|
||||
})}
|
||||
formatOptions={{
|
||||
@@ -88,6 +89,7 @@ export function TransferPointsFormClient({
|
||||
<TextField type="number" isDisabled={disabled}>
|
||||
<Input
|
||||
label={intl.formatMessage({
|
||||
id: "partnerSas.ebPointsToExchange",
|
||||
defaultMessage: "EB points to exchange",
|
||||
})}
|
||||
type="number"
|
||||
@@ -109,6 +111,7 @@ export function TransferPointsFormClient({
|
||||
<p className={styles.conversionRate}>
|
||||
{/* TODO maybe dynamic string based on exchange rate */}
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.conversionRateInfo",
|
||||
defaultMessage: "1 EuroBonus point = 2 Scandic Friends points",
|
||||
})}
|
||||
</p>
|
||||
@@ -117,6 +120,7 @@ export function TransferPointsFormClient({
|
||||
<Typography variant="Label/xsRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.sfPointsToReceive",
|
||||
defaultMessage: "SF points to receive",
|
||||
})}
|
||||
</p>
|
||||
@@ -183,6 +187,7 @@ function ConfirmModal({
|
||||
disabled={disabled}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.exchangePoints",
|
||||
defaultMessage: "Exchange points",
|
||||
})}
|
||||
</Button>
|
||||
@@ -197,6 +202,7 @@ function ConfirmModal({
|
||||
<Typography variant="Title/Subtitle/lg">
|
||||
<h3>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.proceedWithPointExchange",
|
||||
defaultMessage: "Proceed with point exchange?",
|
||||
})}
|
||||
</h3>
|
||||
@@ -205,6 +211,7 @@ function ConfirmModal({
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.youAreAboutToExchange",
|
||||
defaultMessage: "You are about to exchange:",
|
||||
})}
|
||||
</p>
|
||||
@@ -213,6 +220,7 @@ function ConfirmModal({
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "partnerSas.exchangePointsDetails",
|
||||
defaultMessage:
|
||||
"<bold>{sasPoints, number} EuroBonus points</bold> to <bold>{scandicPoints, number} Scandic Friends points</bold>",
|
||||
},
|
||||
@@ -232,6 +240,7 @@ function ConfirmModal({
|
||||
<Typography variant="Body/Supporting text (caption)/smRegular">
|
||||
<p className={styles.expiryText}>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.exchangePointsExpiry",
|
||||
defaultMessage:
|
||||
"Your exchanged points will retain their original expiry date with a maximum validity of 12 months.",
|
||||
})}
|
||||
@@ -245,6 +254,7 @@ function ConfirmModal({
|
||||
color="none"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "partnerSas.yesIWantToExchangeMyPoints",
|
||||
defaultMessage: "Yes, I want to exchange my points",
|
||||
})}
|
||||
</Link>
|
||||
@@ -256,6 +266,7 @@ function ConfirmModal({
|
||||
onClick={() => handleToggle(false)}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "common.cancel",
|
||||
defaultMessage: "Cancel",
|
||||
})}
|
||||
</Button>
|
||||
|
||||
@@ -24,10 +24,12 @@ export default async function EmptyUpcomingStaysBlock() {
|
||||
textAlign="center"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "stays.noUpcomingStays",
|
||||
defaultMessage: "You have no upcoming stays.",
|
||||
})}
|
||||
<span className={styles.burgundyTitle}>
|
||||
{intl.formatMessage({
|
||||
id: "stays.whereToGoNext",
|
||||
defaultMessage: "Where should you go next?",
|
||||
})}
|
||||
</span>
|
||||
@@ -39,6 +41,7 @@ export default async function EmptyUpcomingStaysBlock() {
|
||||
color="Text/Interactive/Secondary"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "stays.getInspired",
|
||||
defaultMessage: "Get inspired",
|
||||
})}
|
||||
<MaterialIcon icon="arrow_forward" color="CurrentColor" />
|
||||
|
||||
@@ -30,6 +30,7 @@ export default function ShowMoreButton({
|
||||
color="CurrentColor"
|
||||
/>
|
||||
{intl.formatMessage({
|
||||
id: "common.showMore",
|
||||
defaultMessage: "Show more",
|
||||
})}
|
||||
</Button>
|
||||
|
||||
@@ -27,6 +27,7 @@ export default async function HotelListingItem({
|
||||
url: hotelData.meetingUrl,
|
||||
openInNewTab: true,
|
||||
text: intl.formatMessage({
|
||||
id: "meetingPackage.bookAMeeting",
|
||||
defaultMessage: "Book a meeting",
|
||||
}),
|
||||
}
|
||||
@@ -34,6 +35,7 @@ export default async function HotelListingItem({
|
||||
url: hotelData.url,
|
||||
openInNewTab: false,
|
||||
text: intl.formatMessage({
|
||||
id: "destination.seeHotelDetails",
|
||||
defaultMessage: "See hotel details",
|
||||
}),
|
||||
}
|
||||
@@ -61,6 +63,7 @@ export default async function HotelListingItem({
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "common.kmToCityCenter",
|
||||
defaultMessage: "{number} km to city center",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@ export function CarouselPrevious({ className }: CarouselButtonProps) {
|
||||
style="Elevated"
|
||||
onPress={scrollPrev}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "carousel.previousSlide",
|
||||
defaultMessage: "Previous slide",
|
||||
})}
|
||||
>
|
||||
@@ -49,6 +50,7 @@ export function CarouselNext({ className }: CarouselButtonProps) {
|
||||
style="Elevated"
|
||||
onPress={scrollNext}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "carousel.nextSlide",
|
||||
defaultMessage: "Next slide",
|
||||
})}
|
||||
>
|
||||
|
||||
@@ -18,7 +18,10 @@ export default async function TopCampaign({ topCampaign }: TopCampaignProps) {
|
||||
const intl = await getIntl()
|
||||
const { campaign, heading } = topCampaign
|
||||
const buttonData = {
|
||||
cta: intl.formatMessage({ defaultMessage: "Explore the offer" }),
|
||||
cta: intl.formatMessage({
|
||||
id: "campaign.exploreTheOffer",
|
||||
defaultMessage: "Explore the offer",
|
||||
}),
|
||||
url: `/${lang}${campaign.url}`,
|
||||
}
|
||||
|
||||
@@ -34,6 +37,7 @@ export default async function TopCampaign({ topCampaign }: TopCampaignProps) {
|
||||
heading={
|
||||
campaign.hotel_listing.heading ||
|
||||
intl.formatMessage({
|
||||
id: "campaignPage.hotelsIncludedInOffer",
|
||||
defaultMessage: "Hotels included in this offer",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -26,9 +26,11 @@ export default function HotelListContent({
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({
|
||||
id: "filter.noMatchingHotelsFound",
|
||||
defaultMessage: "No matching hotels found",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "filter.noMatchingHotelsFoundDescription",
|
||||
defaultMessage:
|
||||
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.",
|
||||
})}
|
||||
|
||||
@@ -73,6 +73,7 @@ export default function HotelList() {
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "destinationPage.hotelsCount",
|
||||
defaultMessage: "{count} hotels",
|
||||
},
|
||||
{ count: visibleHotels.length }
|
||||
|
||||
@@ -73,6 +73,7 @@ export default function HotelListItem({ hotel, url }: HotelListItemProps) {
|
||||
sizes="(min-width: 768px) 700px, 100vw"
|
||||
title={intl.formatMessage(
|
||||
{
|
||||
id: "common.imageGalleryWithTitle",
|
||||
defaultMessage: "{title} - Image gallery",
|
||||
},
|
||||
{ title: hotel.name }
|
||||
@@ -111,6 +112,7 @@ export default function HotelListItem({ hotel, url }: HotelListItemProps) {
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "common.kmToCityCenter",
|
||||
defaultMessage: "{number} km to city center",
|
||||
},
|
||||
{
|
||||
@@ -149,6 +151,7 @@ export default function HotelListItem({ hotel, url }: HotelListItemProps) {
|
||||
typography="Body/Paragraph/mdBold"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "destination.seeHotelDetails",
|
||||
defaultMessage: "See hotel details",
|
||||
})}
|
||||
</ButtonLink>
|
||||
|
||||
@@ -69,7 +69,10 @@ export default function CityMap({
|
||||
>
|
||||
<MaterialIcon icon="arrow_back" color="CurrentColor" size={24} />
|
||||
<span>
|
||||
{intl.formatMessage({ defaultMessage: "Back to cities" })}
|
||||
{intl.formatMessage({
|
||||
id: "destination.backToCities",
|
||||
defaultMessage: "Back to cities",
|
||||
})}
|
||||
</span>
|
||||
</Button>
|
||||
) : null}
|
||||
|
||||
@@ -69,6 +69,7 @@ export default async function DestinationCityPage({
|
||||
const sortItems: HotelSortItem[] = [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: "filter.distanceToCityCenter",
|
||||
defaultMessage: "Distance to city center",
|
||||
}),
|
||||
value: HotelSortOption.Distance,
|
||||
@@ -76,13 +77,15 @@ export default async function DestinationCityPage({
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: "common.name",
|
||||
defaultMessage: "Name",
|
||||
}),
|
||||
value: HotelSortOption.Name,
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Tripadvisor rating",
|
||||
id: "common.tripAdvisorRating",
|
||||
defaultMessage: "TripAdvisor rating",
|
||||
}),
|
||||
value: HotelSortOption.TripAdvisorRating,
|
||||
},
|
||||
|
||||
@@ -51,6 +51,7 @@ export default function CityMapCard({
|
||||
className={styles.closeButton}
|
||||
onPress={handleClose}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "common.close",
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
>
|
||||
@@ -90,6 +91,7 @@ export default function CityMapCard({
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "destinationPage.seeHotelsOnMap",
|
||||
defaultMessage: "See hotels on map",
|
||||
})}
|
||||
</p>
|
||||
@@ -103,6 +105,7 @@ export default function CityMapCard({
|
||||
textDecoration="underline"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "destination.exploreCity",
|
||||
defaultMessage: "Explore city",
|
||||
})}
|
||||
</Link>
|
||||
|
||||
@@ -21,9 +21,11 @@ export function CityListContent() {
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({
|
||||
id: "destination.noLocationsFound",
|
||||
defaultMessage: "No matching locations found",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "destination.noLocationsFoundLong",
|
||||
defaultMessage:
|
||||
"It looks like no location match your filters. Try adjusting your search to find the perfect stay.",
|
||||
})}
|
||||
|
||||
@@ -29,6 +29,7 @@ export default function CityList() {
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "destination.city.count",
|
||||
defaultMessage: "{count} destinations",
|
||||
},
|
||||
{ count: activeCities.length }
|
||||
|
||||
@@ -111,6 +111,7 @@ export function CityListItem({
|
||||
textDecoration="underline"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "destination.exploreCity",
|
||||
defaultMessage: "Explore city",
|
||||
})}
|
||||
</Link>
|
||||
@@ -119,6 +120,7 @@ export function CityListItem({
|
||||
<button
|
||||
onClick={handleClickCard}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "destination.seeOnMap",
|
||||
defaultMessage: "See on map",
|
||||
})}
|
||||
className={styles.right}
|
||||
|
||||
@@ -73,6 +73,7 @@ export default async function DestinationCountryPage({
|
||||
const sortItems: HotelSortItem[] = [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: "destination.country.sort.recommended",
|
||||
defaultMessage: "Recommended",
|
||||
}),
|
||||
value: HotelSortOption.Recommended,
|
||||
@@ -80,6 +81,7 @@ export default async function DestinationCountryPage({
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
id: "common.name",
|
||||
defaultMessage: "Name",
|
||||
}),
|
||||
value: HotelSortOption.Name,
|
||||
|
||||
@@ -33,6 +33,7 @@ export default function CityListingItem({ city }: CityListingItemProps) {
|
||||
fill
|
||||
title={intl.formatMessage(
|
||||
{
|
||||
id: "common.imageGalleryWithTitle",
|
||||
defaultMessage: "{title} - Image gallery",
|
||||
},
|
||||
{ title: city.cityName }
|
||||
@@ -61,6 +62,7 @@ export default function CityListingItem({ city }: CityListingItemProps) {
|
||||
<Link href={city.url}>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "destination.cityList.exploreCity",
|
||||
defaultMessage: "Explore {city}",
|
||||
},
|
||||
{ city: city.cityName }
|
||||
|
||||
@@ -40,6 +40,7 @@ export default function CityListing() {
|
||||
<h2>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "destination.cityList.count",
|
||||
defaultMessage:
|
||||
"{count, plural, one {# destination} other {# destinations}}",
|
||||
},
|
||||
@@ -53,9 +54,11 @@ export default function CityListing() {
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({
|
||||
id: "destination.noLocationsFound",
|
||||
defaultMessage: "No matching locations found",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "destination.noLocationsFoundLong",
|
||||
defaultMessage:
|
||||
"It looks like no location match your filters. Try adjusting your search to find the perfect stay.",
|
||||
})}
|
||||
@@ -74,6 +77,7 @@ export default function CityListing() {
|
||||
position="right"
|
||||
onClick={scrollToTop}
|
||||
label={intl.formatMessage({
|
||||
id: "common.backToTop",
|
||||
defaultMessage: "Back to top",
|
||||
})}
|
||||
/>
|
||||
|
||||
@@ -47,6 +47,7 @@ export default function HotelListingItem({
|
||||
sizes="(min-width: 768px) 700px, 100vw"
|
||||
title={intl.formatMessage(
|
||||
{
|
||||
id: "common.imageGalleryWithTitle",
|
||||
defaultMessage: "{title} - Image gallery",
|
||||
},
|
||||
{ title: hotel.name }
|
||||
@@ -77,6 +78,7 @@ export default function HotelListingItem({
|
||||
href={mapUrl}
|
||||
className={styles.addressLink}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "destination.seeOnMap",
|
||||
defaultMessage: "See on map",
|
||||
})}
|
||||
>
|
||||
@@ -89,6 +91,7 @@ export default function HotelListingItem({
|
||||
<p>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "common.kmToCityCenter",
|
||||
defaultMessage: "{number} km to city center",
|
||||
},
|
||||
{
|
||||
@@ -134,6 +137,7 @@ export default function HotelListingItem({
|
||||
onClick={() => setActiveMarker(hotel.id)}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "destination.seeOnMap",
|
||||
defaultMessage: "See on map",
|
||||
})}
|
||||
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
|
||||
@@ -152,6 +156,7 @@ export default function HotelListingItem({
|
||||
typography="Body/Paragraph/mdBold"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "destination.seeHotelDetails",
|
||||
defaultMessage: "See hotel details",
|
||||
})}
|
||||
</ButtonLink>
|
||||
|
||||
@@ -40,6 +40,7 @@ export default function HotelListing() {
|
||||
<h2>
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "destination.hotelList.count",
|
||||
defaultMessage:
|
||||
"{count, plural, one {# hotel} other {# hotels}}",
|
||||
},
|
||||
@@ -53,9 +54,11 @@ export default function HotelListing() {
|
||||
<Alert
|
||||
type={AlertTypeEnum.Info}
|
||||
heading={intl.formatMessage({
|
||||
id: "filter.noMatchingHotelsFound",
|
||||
defaultMessage: "No matching hotels found",
|
||||
})}
|
||||
text={intl.formatMessage({
|
||||
id: "filter.noMatchingHotelsFoundDescription",
|
||||
defaultMessage:
|
||||
"It looks like no hotels match your filters. Try adjusting your search to find the perfect stay.",
|
||||
})}
|
||||
@@ -74,6 +77,7 @@ export default function HotelListing() {
|
||||
position="right"
|
||||
onClick={scrollToTop}
|
||||
label={intl.formatMessage({
|
||||
id: "common.backToTop",
|
||||
defaultMessage: "Back to top",
|
||||
})}
|
||||
/>
|
||||
|
||||
@@ -54,7 +54,10 @@ export function DestinationSearchForm({
|
||||
)
|
||||
toast.error(
|
||||
intl.formatMessage(
|
||||
{ defaultMessage: "Unable to open page for {locationName}" },
|
||||
{
|
||||
id: "destination.search.unableToOpenPage",
|
||||
defaultMessage: "Unable to open page for {locationName}",
|
||||
},
|
||||
{ locationName: item.name }
|
||||
)
|
||||
)
|
||||
|
||||
@@ -29,6 +29,7 @@ export function DestinationSearch() {
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<span className={styles.whereTo}>
|
||||
{intl.formatMessage({
|
||||
id: "bookingWidget.label.whereTo",
|
||||
defaultMessage: "Where to?",
|
||||
})}
|
||||
</span>
|
||||
@@ -36,6 +37,7 @@ export function DestinationSearch() {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<span className={styles.displayAsPlaceholder}>
|
||||
{intl.formatMessage({
|
||||
id: "booking.hotelsAndDestinations",
|
||||
defaultMessage: "Hotels & Destinations",
|
||||
})}
|
||||
</span>
|
||||
|
||||
@@ -24,6 +24,7 @@ export default async function Destination({
|
||||
const intl = await getIntl()
|
||||
const accordionSubtitle = intl.formatMessage(
|
||||
{
|
||||
id: "common.numberOfHotels",
|
||||
defaultMessage: "{amount, plural, one {# hotel} other {# hotels}}",
|
||||
},
|
||||
{ amount: numberOfHotels }
|
||||
@@ -54,6 +55,7 @@ export default async function Destination({
|
||||
<Link href={countryUrl} variant="icon" weight="bold">
|
||||
{intl.formatMessage(
|
||||
{
|
||||
id: "destination.overview.viewAllHotelsInCountry",
|
||||
defaultMessage: "View all hotels in {country}",
|
||||
},
|
||||
{ country: country }
|
||||
|
||||
@@ -21,6 +21,7 @@ export default async function HotelsSection() {
|
||||
<Typography variant="Title/md">
|
||||
<h4 className={styles.heading}>
|
||||
{intl.formatMessage({
|
||||
id: "destination.overview.exploreAllHotels",
|
||||
defaultMessage: "Explore all our hotels",
|
||||
})}
|
||||
</h4>
|
||||
|
||||
@@ -18,6 +18,7 @@ export function mapExperiencesToListData(
|
||||
<MaterialIcon icon="hiking" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({
|
||||
id: "destination.experience.hiking",
|
||||
defaultMessage: "Hiking",
|
||||
}),
|
||||
}
|
||||
@@ -27,6 +28,7 @@ export function mapExperiencesToListData(
|
||||
<MaterialIcon icon="kayaking" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({
|
||||
id: "destination.experience.kayaking",
|
||||
defaultMessage: "Kayaking",
|
||||
}),
|
||||
}
|
||||
@@ -36,6 +38,7 @@ export function mapExperiencesToListData(
|
||||
<MaterialIcon icon="pedal_bike" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({
|
||||
id: "destination.experience.bikeFriendly",
|
||||
defaultMessage: "Bike friendly",
|
||||
}),
|
||||
}
|
||||
@@ -45,6 +48,7 @@ export function mapExperiencesToListData(
|
||||
<MaterialIcon icon="museum" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({
|
||||
id: "destination.experience.museums",
|
||||
defaultMessage: "Museums",
|
||||
}),
|
||||
}
|
||||
@@ -54,6 +58,7 @@ export function mapExperiencesToListData(
|
||||
<MaterialIcon icon="family_restroom" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({
|
||||
id: "destination.experience.familyFriendly",
|
||||
defaultMessage: "Family friendly",
|
||||
}),
|
||||
}
|
||||
@@ -63,6 +68,7 @@ export function mapExperiencesToListData(
|
||||
<MaterialIcon icon="location_city" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({
|
||||
id: "destination.experience.cityPulse",
|
||||
defaultMessage: "City pulse",
|
||||
}),
|
||||
}
|
||||
@@ -72,6 +78,7 @@ export function mapExperiencesToListData(
|
||||
<MaterialIcon icon="nightlife" {...props} />
|
||||
),
|
||||
name: intl.formatMessage({
|
||||
id: "destination.experience.nightLife",
|
||||
defaultMessage: "Nightlife",
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ export default function HotelMapCard({
|
||||
className={styles.closeButton}
|
||||
onPress={handleClose}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "common.close",
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
>
|
||||
@@ -121,6 +122,7 @@ export default function HotelMapCard({
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<p>
|
||||
{intl.formatMessage({
|
||||
id: "destination.seeHotelDetails",
|
||||
defaultMessage: "See hotel details",
|
||||
})}
|
||||
</p>
|
||||
|
||||
@@ -116,6 +116,7 @@ export default function DynamicMap({
|
||||
fallback={
|
||||
<h2>
|
||||
{intl.formatMessage({
|
||||
id: "destination.map.error.unableToDisplayMap",
|
||||
defaultMessage: "Unable to display map",
|
||||
})}
|
||||
</h2>
|
||||
@@ -136,6 +137,7 @@ export default function DynamicMap({
|
||||
<MaterialIcon icon="format_list_bulleted" color="CurrentColor" />
|
||||
<span>
|
||||
{intl.formatMessage({
|
||||
id: "destination.map.seeAsList",
|
||||
defaultMessage: "See as list",
|
||||
})}
|
||||
</span>
|
||||
@@ -148,6 +150,7 @@ export default function DynamicMap({
|
||||
className={styles.zoomButton}
|
||||
onClick={zoomIn}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "map.zoomIn",
|
||||
defaultMessage: "Zoom in",
|
||||
})}
|
||||
isDisabled={isMaxZoom}
|
||||
@@ -160,6 +163,7 @@ export default function DynamicMap({
|
||||
className={styles.zoomButton}
|
||||
onClick={zoomOut}
|
||||
aria-label={intl.formatMessage({
|
||||
id: "map.zoomOut",
|
||||
defaultMessage: "Zoom out",
|
||||
})}
|
||||
isDisabled={isMinZoom}
|
||||
|
||||
@@ -181,9 +181,11 @@ export default function Map({
|
||||
/>
|
||||
{fromCountryPage
|
||||
? intl.formatMessage({
|
||||
id: "destination.backToCities",
|
||||
defaultMessage: "Back to cities",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
id: "destination.map.backToList",
|
||||
defaultMessage: "Back to list",
|
||||
})}
|
||||
</Button>
|
||||
@@ -198,6 +200,7 @@ export default function Map({
|
||||
position="left"
|
||||
onClick={scrollToTop}
|
||||
label={intl.formatMessage({
|
||||
id: "common.backToTop",
|
||||
defaultMessage: "Back to top",
|
||||
})}
|
||||
/>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user