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:
Joakim Jäderberg
2025-10-22 11:00:03 +00:00
parent bdfe2ab213
commit aafad9781f
499 changed files with 93363 additions and 99164 deletions

View File

@@ -111,7 +111,7 @@ export default defineConfig([
"formatjs/no-multiple-whitespaces": ["error"],
"formatjs/no-multiple-plurals": ["error"],
"formatjs/no-invalid-icu": ["error"],
"formatjs/no-id": ["error"],
"formatjs/enforce-id": ["error"],
"formatjs/no-complex-selectors": ["error"],
"formatjs/no-useless-message": ["error"],
"formatjs/prefer-pound-in-plural": ["error"],

View File

@@ -38,6 +38,7 @@ export function AddToCalendar({
logger.error("ICS Error:", error)
toast.error(
intl.formatMessage({
id: "errorMessage.failedToAddToCalendar",
defaultMessage: "Failed to add to calendar",
})
)
@@ -58,6 +59,7 @@ export function AddToCalendar({
logger.error("Download error:", error)
toast.error(
intl.formatMessage({
id: "errorMessage.failedToAddToCalendar",
defaultMessage: "Failed to add to calendar",
})
)

View File

@@ -10,6 +10,7 @@ export function AlternativeHotelsPageTitle({
const intl = useIntl()
const title = intl.formatMessage(
{
id: "alternativeHotels.title",
defaultMessage: "Alternatives for {value}",
},
{

View File

@@ -39,12 +39,14 @@ export default function BookingCodeFilter() {
const bookingCodeFilterItems = [
{
label: intl.formatMessage({
id: "bookingCodeFilter.bookingCodeRates",
defaultMessage: "Booking code rates",
}),
value: BookingCodeFilterEnum.Discounted,
},
{
label: intl.formatMessage({
id: "bookingCodeFilter.allRates",
defaultMessage: "All rates",
}),
value: BookingCodeFilterEnum.All,
@@ -87,6 +89,7 @@ export default function BookingCodeFilter() {
<Typography variant="Body/Paragraph/mdRegular">
<RadioGroup
aria-label={intl.formatMessage({
id: "bookingCodeFilter.bookingCodeFilter",
defaultMessage: "Booking Code Filter",
})}
onChange={handleChangeFilterValue}
@@ -126,6 +129,7 @@ export default function BookingCodeFilter() {
<Typography variant="Title/Subtitle/md">
<h3>
{intl.formatMessage({
id: "bookingCodeFilter.roomRates",
defaultMessage: "Room rates",
})}
</h3>
@@ -147,6 +151,7 @@ export default function BookingCodeFilter() {
<Typography variant="Body/Paragraph/mdRegular">
<RadioGroup
aria-label={intl.formatMessage({
id: "bookingCodeFilter.bookingCodeFilter",
defaultMessage: "Booking Code Filter",
})}
onChange={handleChangeFilterValue}

View File

@@ -19,6 +19,7 @@ export function AddToCalendarButton({ onPress }: { onPress: () => void }) {
<MaterialIcon size={20} icon="calendar_add_on" color="CurrentColor" />
{intl.formatMessage({
id: "common.addToCalendar",
defaultMessage: "Add to calendar",
})}
</Button>

View File

@@ -26,6 +26,7 @@ export default function DownloadInvoice({ mainRef }: DownloadInvoiceProps) {
>
<MaterialIcon icon="download" color="CurrentColor" />
{intl.formatMessage({
id: "bookingConfirmation.downloadInvoice",
defaultMessage: "Download invoice",
})}
</Button>

View File

@@ -46,6 +46,7 @@ export default function ManageBooking({ booking }: ManageBookingProps) {
>
<MaterialIcon size={20} icon="edit_square" color="CurrentColor" />
{intl.formatMessage({
id: "bookingConfirmation.manageBooking",
defaultMessage: "Manage booking",
})}
</ButtonLink>

View File

@@ -30,6 +30,7 @@ export function Header({
const intl = useIntl()
const text = intl.formatMessage({
id: "bookingConfirmation.thankYouMessage",
defaultMessage:
"Thank you for your booking! We look forward to welcoming you and hope you have a pleasant stay.",
})
@@ -59,6 +60,7 @@ export function Header({
<Typography variant={"Title/md"}>
<h2 className={styles.confirmTitle}>
{intl.formatMessage({
id: "bookingConfirmation.title",
defaultMessage: "Booking confirmation",
})}
</h2>

View File

@@ -21,6 +21,7 @@ export function HotelDetails({
<Typography variant={"Title/Subtitle/md"}>
<h3>
{intl.formatMessage({
id: "bookingConfirmation.hotelDetails",
defaultMessage: "Hotel details",
})}
</h3>
@@ -31,6 +32,7 @@ export function HotelDetails({
<p>
{intl.formatMessage(
{
id: "bookingConfirmation.hotel.address",
defaultMessage: "{streetAddress}, {zipCode} {city}",
},
{

View File

@@ -25,6 +25,7 @@ export function PaymentDetails() {
<Typography variant={"Title/Subtitle/md"}>
<h2>
{intl.formatMessage({
id: "bookingConfirmation.paymentDetails",
defaultMessage: "Payment details",
})}
</h2>
@@ -35,6 +36,7 @@ export function PaymentDetails() {
<p>
{intl.formatMessage(
{
id: "bookingConfirmation.totalCost",
defaultMessage: "Total cost: {amount}",
},
{

View File

@@ -37,27 +37,33 @@ export function Promos({ booking }: PromosProps) {
<div className={styles.promos}>
<Promo
buttonText={intl.formatMessage({
defaultMessage: "View and buy extras",
id: "bookingConfirmation.promos.buyAddonsButtonText",
defaultMessage: "View and buy add-ons",
})}
href={myStayURL}
text={intl.formatMessage({
id: "bookingConfirmation.promos.buyAddonsDescription",
defaultMessage:
"Discover the little extra touches to make your upcoming stay even more unforgettable.",
})}
title={intl.formatMessage({
id: "bookingConfirmation.promos.buyAddonsTitle",
defaultMessage: "Spice things up",
})}
/>
<Promo
buttonText={intl.formatMessage({
id: "bookingConfirmation.promos.bookAnotherStayButtonText",
defaultMessage: "Book another stay",
})}
href={`/${lang}?hotel=${hotelId}`}
text={intl.formatMessage({
id: "booking.bookAnotherStayDescription",
defaultMessage:
"Get inspired and start dreaming beyond your next trip. Explore more Scandic destinations.",
})}
title={intl.formatMessage({
id: "booking.bookNextStay.title",
defaultMessage: "Book your next stay",
})}
/>

View File

@@ -22,13 +22,17 @@ export default function Breakfast({
const intl = useIntl()
const breakfastBuffet = intl.formatMessage({
id: "common.breakfastBuffet",
defaultMessage: "Breakfast buffet",
})
if (breakfastIncluded || breakfast) {
const price = breakfast
? formatPrice(intl, breakfast.totalPrice, breakfast.currency)
: intl.formatMessage({ defaultMessage: "Included" })
: intl.formatMessage({
id: "common.included",
defaultMessage: "Included",
})
return (
<div className={styles.entry}>
<div>
@@ -47,7 +51,10 @@ export default function Breakfast({
}
if (breakfast === false) {
const noBreakfast = intl.formatMessage({ defaultMessage: "No breakfast" })
const noBreakfast = intl.formatMessage({
id: "common.noBreakfast",
defaultMessage: "No breakfast",
})
return (
<div className={styles.entry}>
<Typography variant="Body/Paragraph/mdRegular">

View File

@@ -54,6 +54,7 @@ export function ReceiptRoom({
const adultsMsg = intl.formatMessage(
{
id: "common.numberOfAdults",
defaultMessage: "{totalAdults, plural, one {# adult} other {# adults}}",
},
{ totalAdults: room.adults }
@@ -63,6 +64,7 @@ export function ReceiptRoom({
if (room.childrenAges?.length) {
const childrenMsg = intl.formatMessage(
{
id: "common.numberOfChildren",
defaultMessage:
"{totalChildren, plural, one {# child} other {# children}}",
},
@@ -83,6 +85,7 @@ export function ReceiptRoom({
<p className={styles.roomTitle}>
{intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{
@@ -128,6 +131,7 @@ export function ReceiptRoom({
wrapping={false}
>
{intl.formatMessage({
id: "bookingConfirmation.receipt.reservationPolicy",
defaultMessage: "Reservation policy",
})}
<MaterialIcon
@@ -146,9 +150,11 @@ export function ReceiptRoom({
room.rateDefinition.cancellationRule ===
CancellationRuleEnum.CancellableBefore6PM
? intl.formatMessage({
id: "booking.payLater",
defaultMessage: "Pay later",
})
: intl.formatMessage({
id: "booking.payNow",
defaultMessage: "Pay now",
})
}
@@ -218,6 +224,7 @@ export function ReceiptRoom({
<p>
{intl.formatMessage(
{
id: "booking.numberOfCribs",
defaultMessage: "Crib (child) × {count}",
},
{ count: childBedCrib.quantity }
@@ -226,6 +233,7 @@ export function ReceiptRoom({
<Typography variant="Body/Supporting text (caption)/smRegular">
<p className={styles.uiTextHighContrast}>
{intl.formatMessage({
id: "booking.subjectToAvailability",
defaultMessage: "Subject to availability",
})}
</p>
@@ -246,6 +254,7 @@ export function ReceiptRoom({
<p>
{intl.formatMessage(
{
id: "booking.extraBedsCount",
defaultMessage: "Extra bed (child) × {count}",
},
{

View File

@@ -38,6 +38,7 @@ export default function TotalPrice() {
<p>
{intl.formatMessage(
{
id: "booking.totalPriceInclVat",
defaultMessage: "<b>Total price</b> (incl VAT)",
},
{

View File

@@ -28,6 +28,7 @@ export function Receipt() {
const nights = intl.formatMessage(
{
id: "booking.numberOfNights",
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
},
{ totalNights }
@@ -43,6 +44,7 @@ export function Receipt() {
<Typography variant="Title/Subtitle/md">
<h3 className={styles.heading}>
{intl.formatMessage({
id: "booking.bookingSummary",
defaultMessage: "Booking summary",
})}
</h3>

View File

@@ -18,6 +18,7 @@ export default function Retry({ handleRefetch }: RetryProps) {
<Typography variant={"Body/Paragraph/mdRegular"}>
<p>
{intl.formatMessage({
id: "errorMessage.somethingWentWrong",
defaultMessage: "Something went wrong!",
})}
</p>
@@ -25,6 +26,7 @@ export default function Retry({ handleRefetch }: RetryProps) {
<Button size={"Small"} onPress={handleRefetch}>
{intl.formatMessage({
id: "bookingConfirmation.linkedReservation.tryAgain",
defaultMessage: "Try again",
})}
</Button>

View File

@@ -60,6 +60,7 @@ export function Room({
<h2>
{intl.formatMessage(
{
id: "bookingConfirmation.rooms.bookingNumber",
defaultMessage: "Booking number {value}",
},
{ value: booking.confirmationNumber }
@@ -77,6 +78,7 @@ export function Room({
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{intl.formatMessage({
id: "bookingConfirmation.rooms.benefitsApplied",
defaultMessage: "Membership benefits applied",
})}
</p>
@@ -97,6 +99,7 @@ export function Room({
>
<p>
{intl.formatMessage({
id: "bookingConfirmation.rooms.guaranteeTitle",
defaultMessage: "Booking guaranteed.",
})}
</p>
@@ -106,6 +109,7 @@ export function Room({
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{intl.formatMessage({
id: "bookingConfirmation.rooms.guaranteeDetails",
defaultMessage:
"Your room will remain available for check-in even after 18:00.",
})}
@@ -141,6 +145,7 @@ export function Room({
roomTypeCode={booking.roomTypeCode}
buttonVariant="primary"
triggerLabel={intl.formatMessage({
id: "hotel.seeRoomDetails",
defaultMessage: "See room details",
})}
wrapping={false}
@@ -152,12 +157,14 @@ export function Room({
<li className={styles.listItem}>
<p className={styles.label}>
{intl.formatMessage({
id: "common.checkIn",
defaultMessage: "Check-in",
})}
</p>
<p>
{intl.formatMessage(
{
id: "bookingConfirmation.rooms.checkInDetails",
defaultMessage: "{checkInDate} from {checkInTime}",
},
{
@@ -170,6 +177,7 @@ export function Room({
<li className={styles.listItem}>
<p className={styles.label}>
{intl.formatMessage({
id: "common.checkOut",
defaultMessage: "Check-out",
})}
</p>
@@ -181,6 +189,7 @@ export function Room({
<li className={styles.listItem}>
<p className={styles.label}>
{intl.formatMessage({
id: "bookingConfirmation.rooms.cancellationPolicy",
defaultMessage: "Cancellation policy",
})}
</p>
@@ -190,12 +199,14 @@ export function Room({
<li className={styles.listItem}>
<p className={styles.label}>
{intl.formatMessage({
id: "booking.changeOrCancel",
defaultMessage: "Change or cancel",
})}
</p>
<p>
{intl.formatMessage(
{
id: "common.untilWithTimeAndDate",
defaultMessage: "Until {time}, {date}",
},
{
@@ -212,6 +223,7 @@ export function Room({
<Typography variant="Body/Paragraph/mdRegular">
<p className={styles.label}>
{intl.formatMessage({
id: "bookingConfirmation.rooms.guestLabel",
defaultMessage: "Guest",
})}
</p>
@@ -224,6 +236,7 @@ export function Room({
<p data-hj-suppress>
{intl.formatMessage(
{
id: "bookingConfirmation.rooms.friendNumber",
defaultMessage: "Friend no. {value}",
},
{

View File

@@ -37,6 +37,7 @@ export function Rooms({
<h2 className={styles.roomTitle}>
{intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{ roomIndex: 1 }
@@ -59,6 +60,7 @@ export function Rooms({
<h2 className={styles.roomTitle}>
{intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{ roomIndex: idx + 2 }

View File

@@ -66,9 +66,11 @@ export async function BookingConfirmation({
<Alert
type={AlertTypeEnum.Info}
heading={intl.formatMessage({
id: "bookingConfirmation.membershipVerificationFailed",
defaultMessage: "Failed to verify membership",
})}
text={intl.formatMessage({
id: "bookingConfirmation.bookingConfirmedMembershipFailedInfo",
defaultMessage:
"Your booking(s) is confirmed but we could not verify your membership. If you have booked with a member discount, you'll either need to present your existing membership number upon check-in, become a member or pay the price difference at the hotel. Signing up is preferably done online before the stay.",
})}

View File

@@ -19,126 +19,153 @@ export function getErrorMessage(
switch (errorCode) {
case bookingWidgetErrors.BOOKING_CODE_INVALID:
return intl.formatMessage({
id: "error.bookingCodeInvalid",
defaultMessage: "Booking code is invalid",
})
case bookingWidgetErrors.AGE_REQUIRED:
return intl.formatMessage({
id: "error.ageRequired",
defaultMessage: "Age is required",
})
case bookingWidgetErrors.BED_CHOICE_REQUIRED:
return intl.formatMessage({
id: "error.bedChoiceRequired",
defaultMessage: "Bed choice is required",
})
case bookingWidgetErrors.CHILDREN_EXCEEDS_ADULTS:
return intl.formatMessage({
id: "error.childrenExceedsAdults",
defaultMessage:
"You cannot have more children in adults bed than adults in the room",
})
case bookingWidgetErrors.REQUIRED:
return intl.formatMessage({
id: "error.required",
defaultMessage: "Required",
})
case bookingWidgetErrors.DESTINATION_REQUIRED:
return intl.formatMessage({
id: "error.destinationRequired",
defaultMessage: "Destination required",
})
case bookingWidgetErrors.MULTIROOM_BOOKING_CODE_UNAVAILABLE:
return intl.formatMessage({
id: "error.multiroomBookingCodeUnavailable",
defaultMessage:
"Multi-room booking is not available with this booking code.",
})
case bookingWidgetErrors.MULTIROOM_REWARD_NIGHT_UNAVAILABLE:
return variant === "partner-sas"
? intl.formatMessage({
id: "partnerSas.error.multiroomRewardNightUnavailable",
defaultMessage:
"Multi-room bookings are not available with EuroBonus points.",
})
: intl.formatMessage({
id: "error.multiroomRewardNightUnavailable",
defaultMessage:
"Multi-room booking is not available with reward night.",
})
case bookingWidgetErrors.CODE_VOUCHER_REWARD_NIGHT_UNAVAILABLE:
return intl.formatMessage({
id: "error.codeVoucherRewardNightUnavailable",
defaultMessage:
"Reward nights can't be combined with codes or vouchers.",
})
case phoneErrors.PHONE_NUMBER_TOO_SHORT:
return intl.formatMessage({
id: "error.phoneNumberTooShort",
defaultMessage: "The number you have entered is too short",
})
case multiroomErrors.FIRST_NAME_REQUIRED:
case roomOneErrors.FIRST_NAME_REQUIRED:
return intl.formatMessage({
id: "error.firstNameRequired",
defaultMessage: "First name is required",
})
case multiroomErrors.FIRST_NAME_SPECIAL_CHARACTERS:
case roomOneErrors.FIRST_NAME_SPECIAL_CHARACTERS:
return intl.formatMessage({
id: "error.firstNameSpecialCharacters",
defaultMessage: "First name can't contain any special characters",
})
case multiroomErrors.LAST_NAME_REQUIRED:
case roomOneErrors.LAST_NAME_REQUIRED:
return intl.formatMessage({
id: "error.lastNameRequired",
defaultMessage: "Last name is required",
})
case multiroomErrors.LAST_NAME_SPECIAL_CHARACTERS:
case roomOneErrors.LAST_NAME_SPECIAL_CHARACTERS:
return intl.formatMessage({
id: "error.lastNameSpecialCharacters",
defaultMessage: "Last name can't contain any special characters",
})
case multiroomErrors.FIRST_AND_LAST_NAME_UNIQUE:
return intl.formatMessage({
id: "error.firstAndLastNameUnique",
defaultMessage:
"First and last name can't be the same in two different rooms",
})
case multiroomErrors.EMAIL_REQUIRED:
case roomOneErrors.EMAIL_REQUIRED:
return intl.formatMessage({
id: "error.emailRequired",
defaultMessage: "Email address is required",
})
case multiroomErrors.COUNTRY_REQUIRED:
case roomOneErrors.COUNTRY_REQUIRED:
return intl.formatMessage({
id: "error.countryRequired",
defaultMessage: "Country is required",
})
case multiroomErrors.PHONE_REQUIRED:
case roomOneErrors.PHONE_REQUIRED:
return intl.formatMessage({
id: "error.phoneRequired",
defaultMessage: "Phone is required",
})
case multiroomErrors.PHONE_REQUESTED:
case roomOneErrors.PHONE_REQUESTED:
return intl.formatMessage({
id: "error.phoneRequested",
defaultMessage: "Please enter a valid phone number",
})
case roomOneErrors.BIRTH_DATE_REQUIRED:
return intl.formatMessage({
id: "error.birthDateRequired",
defaultMessage: "Date of birth is required",
})
case roomOneErrors.BIRTH_DATE_AGE_18:
return intl.formatMessage({
id: "error.atleast18YearsOld",
defaultMessage: "Must be at least 18 years of age to continue",
})
case roomOneErrors.ZIP_CODE_INVALID:
return intl.formatMessage({
id: "error.zipCodeInvalid",
defaultMessage: "The postal code can only contain numbers and letters",
})
case roomOneErrors.ZIP_CODE_REQUIRED:
return intl.formatMessage({
id: "error.zipCodeRequired",
defaultMessage: "Zip code is required",
})
case multiroomErrors.MEMBERSHIP_NO_ONLY_DIGITS:
case roomOneErrors.MEMBERSHIP_NO_ONLY_DIGITS:
return intl.formatMessage({
id: "error.membershipNoOnlyDigits",
defaultMessage: "Only digits are allowed",
})
case multiroomErrors.MEMBERSHIP_NO_INVALID:
case roomOneErrors.MEMBERSHIP_NO_INVALID:
return intl.formatMessage({
id: "error.membershipNoInvalid",
defaultMessage: "Invalid membership number format",
})
case multiroomErrors.MEMBERSHIP_NO_UNIQUE:
return intl.formatMessage({
id: "error.membershipNotUniqueForMultipleRooms",
defaultMessage:
"Membership number can't be the same for two different rooms",
})

View File

@@ -44,13 +44,16 @@ export default function BookingCode() {
const [showRememberMobile, setShowRememberMobile] = useState(false)
const codeError = errors["bookingCode"]?.value
const codeVoucher = intl.formatMessage({
id: "booking.codeVoucher",
defaultMessage: "Code / Voucher",
})
const addCode = intl.formatMessage({
id: "bookingWidget.bookingCode.add",
defaultMessage: "Add code",
})
const ref = useRef<HTMLDivElement | null>(null)
const removeExtraRoomsText = intl.formatMessage({
id: "booking.removeExtraRooms",
defaultMessage: "Remove extra rooms",
})
@@ -195,6 +198,7 @@ export default function BookingCode() {
>
<span>
{intl.formatMessage({
id: "bookingWidget.bookingCode.remember",
defaultMessage: "Remember code",
})}
</span>
@@ -216,9 +220,11 @@ type CodeRememberProps = {
function CodeRulesModal() {
const intl = useIntl()
const codeVoucher = intl.formatMessage({
id: "booking.codeVoucher",
defaultMessage: "Code / Voucher",
})
const bookingCodeTooltipText = intl.formatMessage({
id: "bookingWidget.bookingCode.tooltip",
defaultMessage:
"If you're booking a promotional offer or a Corporate negotiated rate you'll need a special booking code. Don't use any special characters such as (.) (,) (-) (:). If you would like to make a booking with code VOF, please call us +46 8 517 517 20.Save your booking code for the next time you visit the page by ticking the box “Remember”. Don't tick the box if you're using a public computer to avoid unauthorized access to your booking code.",
})
@@ -252,6 +258,7 @@ function CodeRemember({ bookingCodeValue, onApplyClick }: CodeRememberProps) {
<Typography variant={"Body/Supporting text (caption)/smRegular"}>
<span>
{intl.formatMessage({
id: "bookingWidget.bookingCode.remember",
defaultMessage: "Remember code",
})}
</span>
@@ -266,6 +273,7 @@ function CodeRemember({ bookingCodeValue, onApplyClick }: CodeRememberProps) {
onClick={onApplyClick}
>
{intl.formatMessage({
id: "common.apply",
defaultMessage: "Apply",
})}
</Button>
@@ -326,6 +334,7 @@ function TabletBookingCode({
} = useFormContext<BookingWidgetSchema>()
const codeError = errors["bookingCode"]?.value
const codeVoucher = intl.formatMessage({
id: "booking.codeVoucher",
defaultMessage: "Code / Voucher",
})
@@ -381,6 +390,7 @@ function TabletBookingCode({
<div className={styles.popover}>
<BookingFlowInput
label={intl.formatMessage({
id: "bookingWidget.bookingCode.add",
defaultMessage: "Add code",
})}
{...register("bookingCode.value", {

View File

@@ -29,6 +29,7 @@ export function RemoveExtraRooms({ ...props }: ButtonProps) {
{...props}
>
{intl.formatMessage({
id: "booking.removeExtraRooms",
defaultMessage: "Remove extra rooms",
})}
</Button>

View File

@@ -155,10 +155,12 @@ function getRewardMessage(config: BookingFlowConfig, intl: IntlShape): string {
switch (config.variant) {
case "partner-sas":
return intl.formatMessage({
id: "partnerSas.bookingWidget.reward.eurobonus",
defaultMessage: "EuroBonus points",
})
case "scandic":
return intl.formatMessage({
id: "bookingWidget.reward.rewardNight",
defaultMessage: "Reward Night",
})
}
@@ -175,11 +177,13 @@ function getRewardNightTooltipMessage(
switch (config.variant) {
case "partner-sas":
return intl.formatMessage({
id: "partnerSas.bookingWidget.reward.toolTip",
defaultMessage:
"To book with EuroBonus points, make sure you're logged into your SAS EuroBonus account.",
})
case "scandic":
return intl.formatMessage({
id: "bookingWidget.reward.toolTip",
defaultMessage:
"To book a reward night, make sure you're logged in to your Scandic Friends account.",
})

View File

@@ -44,6 +44,7 @@ export default function ClearSearchButton({
<Caption color="burgundy" type="bold" asChild>
<span>
{intl.formatMessage({
id: "bookingWidget.search.clearSearches",
defaultMessage: "Clear searches",
})}
</span>

View File

@@ -102,9 +102,11 @@ export default function SearchList({
<SearchListError
getMenuProps={getMenuProps}
caption={intl.formatMessage({
id: "bookingWidget.validationError.destination",
defaultMessage: "Enter destination or hotel",
})}
body={intl.formatMessage({
id: "bookingWidget.validationError.destinationDesc",
defaultMessage:
"A destination or hotel name is needed to be able to search for a hotel room.",
})}
@@ -117,9 +119,11 @@ export default function SearchList({
<SearchListError
getMenuProps={getMenuProps}
caption={intl.formatMessage({
id: "bookingWidget.searchList.noResults",
defaultMessage: "No results",
})}
body={intl.formatMessage({
id: "bookingWidget.searchList.noResultsDesc",
defaultMessage:
"We couldn't find a matching location for your search.",
})}
@@ -133,9 +137,11 @@ export default function SearchList({
<SearchListError
getMenuProps={getMenuProps}
caption={intl.formatMessage({
id: "bookingWidget.searchList.unableToSearch",
defaultMessage: "Unable to search",
})}
body={intl.formatMessage({
id: "bookingWidget.searchList.unableToSearchDesc",
defaultMessage:
"An error occurred while searching, please try again.",
})}
@@ -168,11 +174,13 @@ export default function SearchList({
<Dialog getMenuProps={getMenuProps} variant="error">
<Body className={styles.text} textTransform="bold">
{intl.formatMessage({
id: "bookingWidget.searchList.noResults",
defaultMessage: "No results",
})}
</Body>
<Body className={styles.text} color="uiTextPlaceholder">
{intl.formatMessage({
id: "bookingWidget.searchList.noResultsDesc",
defaultMessage:
"We couldn't find a matching location for your search.",
})}
@@ -186,6 +194,7 @@ export default function SearchList({
textTransform="uppercase"
>
{intl.formatMessage({
id: "bookingWidget.searchList.latestSearches",
defaultMessage: "Latest searches",
})}
</Footnote>
@@ -215,6 +224,7 @@ export default function SearchList({
<Dialog getMenuProps={getMenuProps}>
<Footnote color="uiTextPlaceholder" textTransform="uppercase">
{intl.formatMessage({
id: "bookingWidget.searchList.latestSearches",
defaultMessage: "Latest searches",
})}
</Footnote>
@@ -244,6 +254,7 @@ export default function SearchList({
getItemProps={getItemProps}
highlightedIndex={highlightedIndex}
label={intl.formatMessage({
id: "bookingWidget.searchList.countries",
defaultMessage: "Countries",
})}
locations={autocompleteData?.hits.countries ?? []}
@@ -253,6 +264,7 @@ export default function SearchList({
highlightedIndex={highlightedIndex}
initialIndex={autocompleteData?.hits.countries.length ?? 0}
label={intl.formatMessage({
id: "bookingWidget.searchList.cities",
defaultMessage: "Cities",
})}
locations={autocompleteData?.hits.cities ?? []}
@@ -265,6 +277,7 @@ export default function SearchList({
(autocompleteData?.hits.cities.length ?? 0)
}
label={intl.formatMessage({
id: "bookingWidget.searchList.hotels",
defaultMessage: "Hotels",
})}
locations={autocompleteData?.hits.hotels ?? []}

View File

@@ -128,7 +128,10 @@ export function Search({
>
<Typography variant="Body/Supporting text (caption)/smBold">
<span>
{intl.formatMessage({ defaultMessage: "Where to?" })}
{intl.formatMessage({
id: "bookingWidget.label.whereTo",
defaultMessage: "Where to?",
})}
</span>
</Typography>
<div
@@ -146,6 +149,7 @@ export function Search({
openMenu()
},
placeholder: intl.formatMessage({
id: "booking.hotelsAndDestinations",
defaultMessage: "Hotels & Destinations",
}),
value: searchTerm,
@@ -175,7 +179,10 @@ export function Search({
<Button
variant="Text"
size="Small"
aria-label={intl.formatMessage({ defaultMessage: "Clear" })}
aria-label={intl.formatMessage({
id: "common.clear",
defaultMessage: "Clear",
})}
onPress={() => {
setValue(SEARCH_TERM_NAME, "")
}}
@@ -207,7 +214,10 @@ export function Search({
<Typography variant="Body/Supporting text (caption)/smBold">
<span>
<MaterialIcon icon="search" color="CurrentColor" />
{intl.formatMessage({ defaultMessage: "Search" })}
{intl.formatMessage({
id: "bookingWidget.button.search",
defaultMessage: "Search",
})}
</span>
</Typography>
</Button>
@@ -237,7 +247,12 @@ export function SearchSkeleton() {
<div className={styles.container}>
<div className={`${styles.label} ${styles.red}`}>
<Typography variant="Body/Supporting text (caption)/smBold">
<span>{intl.formatMessage({ defaultMessage: "Where to?" })}</span>
<span>
{intl.formatMessage({
id: "bookingWidget.label.whereTo",
defaultMessage: "Where to?",
})}
</span>
</Typography>
</div>
<div>

View File

@@ -17,11 +17,13 @@ export default function ValidationError() {
size={20}
/>
{intl.formatMessage({
id: "bookingWidget.validationError.destination",
defaultMessage: "Enter destination or hotel",
})}
</Caption>
<Caption className={styles.message} type="regular">
{intl.formatMessage({
id: "bookingWidget.validationError.destinationDesc",
defaultMessage:
"A destination or hotel name is needed to be able to search for a hotel room.",
})}

View File

@@ -31,10 +31,12 @@ export function VoucherSkeleton() {
const config = useBookingFlowConfig()
const vouchers = intl.formatMessage({
id: "booking.codeVoucher",
defaultMessage: "Code / Voucher",
})
const reward = intl.formatMessage({
defaultMessage: "Reward Night",
id: "booking.rewardNight",
defaultMessage: "Reward night",
})
return (

View File

@@ -72,12 +72,14 @@ export default function FormContent({
{nights > 0
? intl.formatMessage(
{
id: "booking.numberOfNights",
defaultMessage:
"{totalNights, plural, one {# night} other {# nights}}",
},
{ totalNights: nights }
)
: intl.formatMessage({
id: "bookingWidget.label.checkIn",
defaultMessage: "Check in",
})}
</label>
@@ -91,6 +93,7 @@ export default function FormContent({
>
<label id="rooms-and-guests">
{intl.formatMessage({
id: "bookingWidget.label.roomsAndGuests",
defaultMessage: "Rooms & Guests",
})}
</label>
@@ -135,8 +138,14 @@ export default function FormContent({
>
<span>
{isDirty && isBookingFlow
? intl.formatMessage({ defaultMessage: "Update" })
: intl.formatMessage({ defaultMessage: "Search" })}
? intl.formatMessage({
id: "bookingWidget.button.update",
defaultMessage: "Update",
})
: intl.formatMessage({
id: "bookingWidget.button.search",
defaultMessage: "Search",
})}
</span>
</Typography>
<span className={styles.icon}>
@@ -165,6 +174,7 @@ export function BookingWidgetFormContentSkeleton() {
<label>
{intl.formatMessage(
{
id: "booking.numberOfNights",
defaultMessage:
"{totalNights, plural, one {# night} other {# nights}}",
},
@@ -181,6 +191,7 @@ export function BookingWidgetFormContentSkeleton() {
>
<label id="rooms-and-guests">
{intl.formatMessage({
id: "bookingWidget.label.roomsAndGuests",
defaultMessage: "Rooms & Guests",
})}
</label>
@@ -212,6 +223,7 @@ export function BookingWidgetFormContentSkeleton() {
>
<span>
{intl.formatMessage({
id: "bookingWidget.button.search",
defaultMessage: "Search",
})}
</span>

View File

@@ -121,6 +121,7 @@ export default function DatePickerRangeDesktop({
<Caption color="white" type="bold" asChild>
<span>
{intl.formatMessage({
id: "datePicker.selectDates",
defaultMessage: "Select dates",
})}
</span>

View File

@@ -140,6 +140,7 @@ export default function DatePickerRangeMobile({
<Body color="white" textTransform="bold" asChild>
<span>
{intl.formatMessage({
id: "datePicker.selectDates",
defaultMessage: "Select dates",
})}
</span>

View File

@@ -153,6 +153,7 @@ export default function DatePickerForm({ name = "date" }: DatePickerFormProps) {
<span>
{intl.formatMessage(
{
id: "booking.selectedDateRange",
defaultMessage: "{selectedFromDate} {selectedToDate}",
},
{

View File

@@ -20,6 +20,7 @@ export default function AdultSelector({
const name = `rooms.${roomIndex}.adults`
const intl = useIntl()
const adultsLabel = intl.formatMessage({
id: "common.adults",
defaultMessage: "Adults",
})
const { setValue } = useFormContext()

View File

@@ -42,12 +42,15 @@ export default function ChildInfoSelector({
const bedFieldName = `rooms.${roomIndex}.childrenInRoom.${index}.bed`
const intl = useIntl()
const ageLabel = intl.formatMessage({
id: "bookingWidget.child.age",
defaultMessage: "Age",
})
const bedLabel = intl.formatMessage({
id: "booking.bedPreference",
defaultMessage: "Bed preference",
})
const errorMessage = intl.formatMessage({
id: "bookingWidget.child.ageRequiredError",
defaultMessage: "Child age is required",
})
const { setValue, formState } = useFormContext()
@@ -65,18 +68,21 @@ export default function ChildInfoSelector({
const allBedTypes: ChildBed[] = [
{
label: intl.formatMessage({
id: "bookingWidget.child.inAdultsBed",
defaultMessage: "In adult's bed",
}),
value: ChildBedMapEnum.IN_ADULTS_BED,
},
{
label: intl.formatMessage({
id: "bookingWidget.child.inCrib",
defaultMessage: "In crib",
}),
value: ChildBedMapEnum.IN_CRIB,
},
{
label: intl.formatMessage({
id: "bookingWidget.child.inExtraBed",
defaultMessage: "In extra bed",
}),
value: ChildBedMapEnum.IN_EXTRA_BED,

View File

@@ -26,6 +26,7 @@ export default function ChildSelector({
}: ChildSelectorProps) {
const intl = useIntl()
const childrenLabel = intl.formatMessage({
id: "common.children",
defaultMessage: "Children",
})
const { setValue } = useFormContext()

View File

@@ -35,24 +35,29 @@ export default function GuestsRoomsPickerDialog({
useFormContext<BookingWidgetSchema>()
const roomsValue = useWatch<BookingWidgetSchema, "rooms">({ name: "rooms" })
const addRoomLabel = intl.formatMessage({
id: "bookingWidget.roomsPicker.addRoom",
defaultMessage: "Add room",
})
const doneLabel = intl.formatMessage({
id: "bookingWidget.roomsPicker.done",
defaultMessage: "Done",
})
// Disable add room if booking code is either voucher or corporate cheque, or reward night is enabled
const addRoomDisabledTextForSpecialRate = getValues(SEARCH_TYPE_REDEMPTION)
? config.variant === "partner-sas"
? intl.formatMessage({
id: "partnerSas.bookingWidget.roomsPicker.disabled",
defaultMessage:
"Multi-room booking is not available with EuroBonus points.",
})
: intl.formatMessage({
id: "error.multiroomRewardNightUnavailable",
defaultMessage:
"Multi-room booking is not available with reward night.",
})
: getValues("bookingCode.value")?.toLowerCase().startsWith("vo") &&
intl.formatMessage({
id: "error.multiroomBookingCodeUnavailable",
defaultMessage:
"Multi-room booking is not available with this booking code.",
})

View File

@@ -25,6 +25,7 @@ export function GuestsRoom({
const intl = useIntl()
const roomLabel = intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{
@@ -61,6 +62,7 @@ export function GuestsRoom({
>
<MaterialIcon icon="delete" color="CurrentColor" />
{intl.formatMessage({
id: "bookingWidget.roomsPicker.removeRoom",
defaultMessage: "Remove room",
})}
</Button>

View File

@@ -146,15 +146,17 @@ function Trigger({
const parts = [
intl.formatMessage(
{
id: "booking.numberOfRooms",
defaultMessage: "{totalRooms, plural, one {# room} other {# rooms}}",
},
{ totalRooms: rooms.length }
),
intl.formatMessage(
{
defaultMessage: "{totalAdults, plural, one {# adult} other {# adults}}",
id: "booking.numberOfAdults",
defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
},
{ totalAdults: rooms.reduce((acc, room) => acc + room.adults, 0) }
{ adults: rooms.reduce((acc, room) => acc + room.adults, 0) }
),
]
@@ -162,11 +164,12 @@ function Trigger({
parts.push(
intl.formatMessage(
{
id: "booking.numberOfChildren",
defaultMessage:
"{totalChildren, plural, one {# child} other {# children}}",
"{children, plural, one {# child} other {# children}}",
},
{
totalChildren: rooms.reduce(
children: rooms.reduce(
(acc, room) => acc + room.childrenInRoom.length,
0
),

View File

@@ -58,6 +58,7 @@ export default function MobileToggleButton({
const totalNightsMsg = intl.formatMessage(
{
id: "booking.numberOfNights",
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
},
{ totalNights }
@@ -65,21 +66,23 @@ export default function MobileToggleButton({
const totalAdultsMsg = intl.formatMessage(
{
defaultMessage: "{totalAdults, plural, one {# adult} other {# adults}}",
id: "booking.numberOfAdults",
defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
},
{ totalAdults }
{ adults: totalAdults }
)
const totalChildrenMsg = intl.formatMessage(
{
defaultMessage:
"{totalChildren, plural, one {# child} other {# children}}",
id: "booking.numberOfChildren",
defaultMessage: "{children, plural, one {# child} other {# children}}",
},
{ totalChildren }
{ children: totalChildren }
)
const totalRoomsMsg = intl.formatMessage(
{
id: "booking.numberOfRooms",
defaultMessage: "{totalRooms, plural, one {# room} other {# rooms}}",
},
{ totalRooms }
@@ -102,6 +105,7 @@ export default function MobileToggleButton({
<Typography variant={"Body/Supporting text (caption)/smBold"}>
<span className={styles.blockLabel}>
{intl.formatMessage({
id: "bookingWidget.label.whereTo",
defaultMessage: "Where to?",
})}
</span>
@@ -111,6 +115,7 @@ export default function MobileToggleButton({
{searchTerm
? searchTerm
: intl.formatMessage({
id: "bookingWidget.label.destination",
defaultMessage: "Destination",
})}
</span>
@@ -126,6 +131,7 @@ export default function MobileToggleButton({
<span className={styles.placeholder}>
{intl.formatMessage(
{
id: "booking.selectedDateRange",
defaultMessage: "{selectedFromDate} {selectedToDate}",
},
{
@@ -152,6 +158,7 @@ export default function MobileToggleButton({
<span className={styles.locationAndDate}>
{intl.formatMessage(
{
id: "bookingWidget.mobile.selectedSummary",
defaultMessage:
"{selectedFromDate} {selectedToDate} ({totalNights}) {details}",
},
@@ -183,6 +190,7 @@ export function MobileToggleButtonSkeleton() {
<Typography variant={"Body/Supporting text (caption)/smBold"}>
<span className={styles.blockLabel}>
{intl.formatMessage({
id: "bookingWidget.label.whereTo",
defaultMessage: "Where to?",
})}
</span>
@@ -195,6 +203,7 @@ export function MobileToggleButtonSkeleton() {
<span className={styles.blockLabel}>
{intl.formatMessage(
{
id: "booking.numberOfNights",
defaultMessage:
"{totalNights, plural, one {# night} other {# nights}}",
},

View File

@@ -33,6 +33,7 @@ export default function Contact({ hotel }: ContactProps) {
<Typography variant="Body/Paragraph/mdBold">
<p>
{intl.formatMessage({
id: "common.address",
defaultMessage: "Address",
})}
</p>
@@ -49,6 +50,7 @@ export default function Contact({ hotel }: ContactProps) {
<Typography variant="Body/Paragraph/mdBold">
<p>
{intl.formatMessage({
id: "common.drivingDirections",
defaultMessage: "Driving directions",
})}
</p>
@@ -61,6 +63,7 @@ export default function Contact({ hotel }: ContactProps) {
<Typography variant="Body/Underline/md">
<p>
{intl.formatMessage({
id: "common.googleMaps",
defaultMessage: "Google Maps",
})}
</p>
@@ -71,6 +74,7 @@ export default function Contact({ hotel }: ContactProps) {
<Typography variant="Body/Paragraph/mdBold">
<p>
{intl.formatMessage({
id: "common.contactUs",
defaultMessage: "Contact us",
})}
</p>
@@ -87,6 +91,7 @@ export default function Contact({ hotel }: ContactProps) {
<Typography variant="Body/Paragraph/mdBold">
<p>
{intl.formatMessage({
id: "common.followUs",
defaultMessage: "Follow us",
})}
</p>
@@ -110,6 +115,7 @@ export default function Contact({ hotel }: ContactProps) {
<Typography variant="Body/Paragraph/mdBold">
<p>
{intl.formatMessage({
id: "common.email",
defaultMessage: "Email",
})}
</p>
@@ -129,6 +135,7 @@ export default function Contact({ hotel }: ContactProps) {
height={38}
width={38}
alt={intl.formatMessage({
id: "common.nordicSwanEcolabel",
defaultMessage: "Nordic Swan Ecolabel",
})}
src={`/_static/img/icons/swan-eco/swan_eco_dark_${lang}.png`}
@@ -137,6 +144,7 @@ export default function Contact({ hotel }: ContactProps) {
<div className={styles.ecoLabelText}>
<span>
{intl.formatMessage({
id: "common.nordicSwanEcolabel",
defaultMessage: "Nordic Swan Ecolabel",
})}
</span>

View File

@@ -79,6 +79,7 @@ export default function Breakfast() {
{hasChildrenInRoom ? (
<Body>
{intl.formatMessage({
id: "enterDetails.breakfast.childrenFreeInfo",
defaultMessage:
"Children's breakfast is always free as part of the adult's breakfast.",
})}
@@ -92,26 +93,31 @@ export default function Breakfast() {
value={pkg.code}
Icon={BreakfastBuffetIcon}
title={intl.formatMessage({
id: "common.breakfastBuffet",
defaultMessage: "Breakfast buffet",
})}
subtitle={
pkg.code === BreakfastPackageEnum.FREE_MEMBER_BREAKFAST
? intl.formatMessage({
id: "common.included",
defaultMessage: "Included",
})
: `+ ${formatPrice(intl, pkg.localPrice.price, pkg.localPrice.currency ?? "")}`
}
subtitleSecondary={intl.formatMessage({
id: "common.perAdultNight",
defaultMessage: "Per adult/night",
})}
description={
hasChildrenInRoom
? intl.formatMessage({
id: "enterDetails.breakfast.freeForKidsUnder12",
defaultMessage: "Free for kids aged 12 and under.",
})
: undefined
}
descriptionSecondary={intl.formatMessage({
id: "enterDetails.breakfast.dietaryOptions",
defaultMessage:
"Includes vegan, gluten-free, and other allergy-friendly options.",
})}
@@ -122,16 +128,19 @@ export default function Breakfast() {
value="false"
Icon={NoBreakfastBuffetIcon}
title={intl.formatMessage({
id: "common.noBreakfast",
defaultMessage: "No breakfast",
})}
subtitle={`+ ${formatPrice(intl, totalPriceForNoBreakfast, packages?.[0].localPrice.currency ?? "")}`}
descriptionSecondary={
hasChildrenInRoom
? intl.formatMessage({
id: "enterDetails.breakfast.addAfterBookingChildren",
defaultMessage:
"Breakfast can be added after booking for an extra cost for adults and kids ages 4 and up.",
})
: intl.formatMessage({
id: "enterDetails.breakfast.addAfterBookingNoChilren",
defaultMessage:
"Breakfast can be added after booking for an additional fee.",
})

View File

@@ -39,6 +39,7 @@ export default function Guarantee({ savedCreditCards }: GuaranteeProps) {
<Typography variant="Body/Supporting text (caption)/smRegular">
<span>
{intl.formatMessage({
id: "enterDetails.confirmBooking.guaranteeLabel",
defaultMessage:
"I may arrive later than 18:00 and want to guarantee my booking.",
})}
@@ -53,7 +54,10 @@ export default function Guarantee({ savedCreditCards }: GuaranteeProps) {
>
<MaterialIcon icon="info" size={20} color="CurrentColor" />
<span className={styles.btnText}>
{intl.formatMessage({ defaultMessage: "How it works" })}
{intl.formatMessage({
id: "common.howItWorks",
defaultMessage: "How it works",
})}
</span>
</Button>
<ModalOverlay className={styles.overlay} isDismissable>
@@ -64,6 +68,7 @@ export default function Guarantee({ savedCreditCards }: GuaranteeProps) {
<Typography variant="Title/Subtitle/lg">
<h3>
{intl.formatMessage({
id: "enterDetails.confirmBooking.guaranteeInfoModalTitle",
defaultMessage: "Guarantee for late arrival",
})}
</h3>
@@ -71,6 +76,7 @@ export default function Guarantee({ savedCreditCards }: GuaranteeProps) {
<Typography variant="Body/Lead text">
<p className={styles.text}>
{intl.formatMessage({
id: "enterDetails.confirmBooking.guaranteeInfoModalDescription",
defaultMessage:
"When guaranteeing your booking with a credit card, we will hold the booking until 07:00 the day after check-in.",
})}
@@ -79,6 +85,7 @@ export default function Guarantee({ savedCreditCards }: GuaranteeProps) {
<Typography variant="Body/Paragraph/mdRegular">
<p className={styles.text}>
{intl.formatMessage({
id: "enterDetails.confirmBooking.guaranteeInfoModalNoShowInfo",
defaultMessage:
"In case of a no-show, your credit card will be charged for the first night.",
})}
@@ -92,6 +99,7 @@ export default function Guarantee({ savedCreditCards }: GuaranteeProps) {
variant="Secondary"
>
{intl.formatMessage({
id: "common.close",
defaultMessage: "Close",
})}
</Button>
@@ -121,15 +129,19 @@ export default function Guarantee({ savedCreditCards }: GuaranteeProps) {
name="paymentMethod"
label={
savedCreditCards?.length
? intl.formatMessage({
defaultMessage: "OTHER",
})
? intl
.formatMessage({
id: "common.other",
defaultMessage: "Other",
})
.toUpperCase()
: undefined
}
>
<PaymentOption
value={PaymentMethodEnum.card}
label={intl.formatMessage({
id: "common.creditCard",
defaultMessage: "Credit card",
})}
/>

View File

@@ -29,6 +29,7 @@ export default function ConfirmBooking({
<Typography variant="Body/Supporting text (caption)/smRegular">
<span>
{intl.formatMessage({
id: "booking.smsConfirmationLabel",
defaultMessage:
"I would like to get my booking confirmation via sms",
})}
@@ -52,6 +53,7 @@ export function ConfirmBookingRedemption() {
<Typography variant="Body/Supporting text (caption)/smRegular">
<span>
{intl.formatMessage({
id: "booking.smsConfirmationLabel",
defaultMessage:
"I would like to get my booking confirmation via sms",
})}
@@ -63,6 +65,7 @@ export function ConfirmBookingRedemption() {
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{intl.formatMessage({
id: "enterDetails.confirmBooking.redemptionGuaranteeInfo",
defaultMessage:
"When you confirm the booking the room will be guaranteed for late arrival. If you fail to arrive without cancelling in advance or if you cancel after 18:00 local time, you will be charged for one reward night.",
})}

View File

@@ -58,6 +58,7 @@ export default function MemberPriceModal() {
<MagicWandIcon width="265px" />
<Title as="h3" level="h1" textTransform="regular">
{intl.formatMessage({
id: "enterDetails.memberPriceModal.title",
defaultMessage: "Member room price activated",
})}
</Title>
@@ -66,6 +67,7 @@ export default function MemberPriceModal() {
<span className={styles.newPrice}>
<Body>
{intl.formatMessage({
id: "enterDetails.memberPriceModal.newPriceLabel",
defaultMessage: "The new price is",
})}
</Body>
@@ -81,6 +83,7 @@ export default function MemberPriceModal() {
</div>
<Button intent="primary" theme="base" onClick={() => setIsOpen(false)}>
{intl.formatMessage({
id: "enterDetails.memberPriceModal.okButtonLabel",
defaultMessage: "OK",
})}
</Button>

View File

@@ -44,12 +44,14 @@ export default function JoinScandicFriendsCard({
<span>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${intl.formatMessage({
id: "enterDetails.joinScandicFriendsCard.title",
defaultMessage: "Get the member room price",
})}: `}
</span>
<span className={styles.price}>
{intl.formatMessage(
{
id: "enterDetails.joinScandicFriendsCard.priceForRoom",
defaultMessage: "{amount} for room {roomNr}",
},
{
@@ -73,6 +75,7 @@ export default function JoinScandicFriendsCard({
<Typography variant="Body/Paragraph/mdRegular">
<div>
{intl.formatMessage({
id: "enterDetails.joinScandicFriendsCard.joinBeforeCheckinCheckboxLabel",
defaultMessage: "Join Scandic Friends before check-in",
})}
</div>
@@ -83,6 +86,7 @@ export default function JoinScandicFriendsCard({
<Footnote color="uiTextPlaceholder">
{intl.formatMessage(
{
id: "enterDetails.joinScandicFriendsCard.terms",
defaultMessage:
"By joining you accept the <termsAndConditionsLink>Terms and Conditions</termsAndConditionsLink>. The Scandic Friends Membership is valid until further notice, but can at any time be terminated by contacting Scandic Customer Service.",
},

View File

@@ -49,6 +49,7 @@ export function PartnerSASJoinScandicFriendsCard({
<h2 className={styles.priceContainer}>
<span>
{intl.formatMessage({
id: "enterDetails.joinScandicFriendsCard.title",
defaultMessage: "Get the member room price",
})}
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
@@ -57,6 +58,7 @@ export function PartnerSASJoinScandicFriendsCard({
<span className={styles.price}>
{intl.formatMessage(
{
id: "enterDetails.joinScandicFriendsCard.priceForRoom",
defaultMessage: "{amount} for room {roomNr}",
},
{
@@ -77,6 +79,7 @@ export function PartnerSASJoinScandicFriendsCard({
<Typography variant="Body/Paragraph/mdRegular">
<div>
{intl.formatMessage({
id: "enterDetails.joinScandicFriendsCard.joinBeforeCheckinCheckboxLabel",
defaultMessage: "Join Scandic Friends before check-in",
})}
</div>
@@ -88,6 +91,7 @@ export function PartnerSASJoinScandicFriendsCard({
registerOptions={{ onBlur: updateDetailsStore }}
disabled={Boolean(joinValue)}
label={intl.formatMessage({
id: "enterDetails.joinScandicFriendsCard.membershipIdLabel",
defaultMessage: "Already a member? Membership ID",
})}
/>
@@ -97,6 +101,7 @@ export function PartnerSASJoinScandicFriendsCard({
<Footnote color="uiTextPlaceholder">
{intl.formatMessage(
{
id: "enterDetails.joinScandicFriendsCard.terms",
defaultMessage:
"By joining you accept the <termsAndConditionsLink>Terms and Conditions</termsAndConditionsLink>. The Scandic Friends Membership is valid until further notice, but can at any time be terminated by contacting Scandic Customer Service.",
},

View File

@@ -184,11 +184,13 @@ export default function Details() {
className={styles.fullWidth}
>
{intl.formatMessage({
id: "enterDetails.roomInfo.title",
defaultMessage: "Guest information",
})}
</Footnote>
<BookingFlowInput
label={intl.formatMessage({
id: "common.firstName",
defaultMessage: "First name",
})}
maxLength={30}
@@ -201,6 +203,7 @@ export default function Details() {
/>
<BookingFlowInput
label={intl.formatMessage({
id: "common.lastName",
defaultMessage: "Last name",
})}
maxLength={30}
@@ -220,6 +223,7 @@ export default function Details() {
errors.countryCode?.message
)}
label={intl.formatMessage({
id: "common.country",
defaultMessage: "Country",
})}
lang={lang}
@@ -229,6 +233,7 @@ export default function Details() {
<BookingFlowInput
className={styles.fullWidth}
label={intl.formatMessage({
id: "common.emailAddress",
defaultMessage: "Email address",
})}
name="email"
@@ -236,6 +241,7 @@ export default function Details() {
/>
<Phone
countryLabel={intl.formatMessage({
id: "common.countryCode",
defaultMessage: "Country code",
})}
countriesWithTranslatedName={getFormattedCountryList(intl)}
@@ -247,6 +253,7 @@ export default function Details() {
)}
className={styles.fullWidth}
label={intl.formatMessage({
id: "common.phoneNumber",
defaultMessage: "Phone number",
})}
name="phoneNumber"
@@ -256,6 +263,7 @@ export default function Details() {
<BookingFlowInput
className={styles.fullWidth}
label={intl.formatMessage({
id: "common.membershipId",
defaultMessage: "Membership ID",
})}
name="membershipNo"

View File

@@ -45,6 +45,7 @@ export function JoinScandicFriendsCard({ name = "join" }: Props) {
<span>
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{`${intl.formatMessage({
id: "enterDetails.joinScandicFriendsCard.title",
defaultMessage: "Get the member room price",
})}: `}
</span>
@@ -65,6 +66,7 @@ export function JoinScandicFriendsCard({ name = "join" }: Props) {
<Typography variant="Body/Paragraph/mdRegular">
<div>
{intl.formatMessage({
id: "enterDetails.joinScandicFriendsCard.joinCheckboxLabel",
defaultMessage: "Join Scandic Friends now",
})}
</div>
@@ -83,6 +85,7 @@ export function JoinScandicFriendsCard({ name = "join" }: Props) {
redirectTo={loginPathname}
>
{intl.formatMessage({
id: "enterDetails.joinScandicFriendsCard.loginButtonText",
defaultMessage: "Log in",
})}
</LoginButton>
@@ -92,6 +95,7 @@ export function JoinScandicFriendsCard({ name = "join" }: Props) {
<Footnote color="uiTextPlaceholder">
{intl.formatMessage(
{
id: "enterDetails.joinScandicFriendsCard.terms",
defaultMessage:
"By joining you accept the <termsAndConditionsLink>Terms and Conditions</termsAndConditionsLink>. The Scandic Friends Membership is valid until further notice, but can at any time be terminated by contacting Scandic Customer Service.",
},

View File

@@ -55,6 +55,7 @@ export function PartnerSASJoinScandicFriendsCard({
<h2 className={styles.priceContainer}>
<span>
{intl.formatMessage({
id: "enterDetails.joinScandicFriendsCard.title",
defaultMessage: "Get the member room price",
})}
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
@@ -74,6 +75,7 @@ export function PartnerSASJoinScandicFriendsCard({
<Typography variant="Body/Paragraph/mdRegular">
<div>
{intl.formatMessage({
id: "enterDetails.joinScandicFriendsCard.joinCheckboxLabel",
defaultMessage: "Join Scandic Friends now",
})}
</div>
@@ -85,6 +87,7 @@ export function PartnerSASJoinScandicFriendsCard({
registerOptions={{ onBlur: updateDetailsStore }}
disabled={Boolean(joinValue)}
label={intl.formatMessage({
id: "enterDetails.joinScandicFriendsCard.membershipIdLabel",
defaultMessage: "Already a member? Membership ID",
})}
/>
@@ -94,6 +97,7 @@ export function PartnerSASJoinScandicFriendsCard({
<Footnote color="uiTextPlaceholder">
{intl.formatMessage(
{
id: "enterDetails.joinScandicFriendsCard.terms",
defaultMessage:
"By joining you accept the <termsAndConditionsLink>Terms and Conditions</termsAndConditionsLink>. The Scandic Friends Membership is valid until further notice, but can at any time be terminated by contacting Scandic Customer Service.",
},

View File

@@ -22,6 +22,7 @@ export function MembershipNumberInput({
label={
label ||
intl.formatMessage({
id: "common.membershipId",
defaultMessage: "Membership ID",
})
}

View File

@@ -48,6 +48,7 @@ export default function Signup({
<BookingFlowInput
name="zipCode"
label={intl.formatMessage({
id: "common.zipCode",
defaultMessage: "Zip code",
})}
registerOptions={{ required: true, ...registerOptions }}
@@ -57,6 +58,7 @@ export default function Signup({
<Caption type="bold">
<span className={styles.required}>
{intl.formatMessage({
id: "common.birthDate",
defaultMessage: "Birth date",
})}
</span>
@@ -64,9 +66,18 @@ export default function Signup({
</header>
<DateSelect
labels={{
day: intl.formatMessage({ defaultMessage: "Day" }),
month: intl.formatMessage({ defaultMessage: "Month" }),
year: intl.formatMessage({ defaultMessage: "Year" }),
day: intl.formatMessage({
id: "common.day",
defaultMessage: "Day",
}),
month: intl.formatMessage({
id: "common.month",
defaultMessage: "Month",
}),
year: intl.formatMessage({
id: "common.year",
defaultMessage: "Year",
}),
errorMessage: getErrorMessage(
intl,
config.variant,

View File

@@ -170,12 +170,14 @@ export default function Details({ user }: DetailsProps) {
className={styles.fullWidth}
>
{intl.formatMessage({
id: "enterDetails.roomInfo.title",
defaultMessage: "Guest information",
})}
</Footnote>
<BookingFlowInput
autoComplete="given-name"
label={intl.formatMessage({
id: "common.firstName",
defaultMessage: "First name",
})}
maxLength={30}
@@ -186,6 +188,7 @@ export default function Details({ user }: DetailsProps) {
<BookingFlowInput
autoComplete="family-name"
label={intl.formatMessage({
id: "common.lastName",
defaultMessage: "Last name",
})}
maxLength={30}
@@ -196,6 +199,7 @@ export default function Details({ user }: DetailsProps) {
<CountrySelect
className={styles.fullWidth}
label={intl.formatMessage({
id: "common.country",
defaultMessage: "Country",
})}
lang={lang}
@@ -213,6 +217,7 @@ export default function Details({ user }: DetailsProps) {
autoComplete="email"
className={styles.fullWidth}
label={intl.formatMessage({
id: "common.emailAddress",
defaultMessage: "Email address",
})}
name="email"
@@ -222,6 +227,7 @@ export default function Details({ user }: DetailsProps) {
<Phone
className={styles.fullWidth}
countryLabel={intl.formatMessage({
id: "common.countryCode",
defaultMessage: "Country code",
})}
countriesWithTranslatedName={getFormattedCountryList(intl)}
@@ -232,6 +238,7 @@ export default function Details({ user }: DetailsProps) {
formState.errors.phoneNumber?.message
)}
label={intl.formatMessage({
id: "common.phoneNumber",
defaultMessage: "Phone number",
})}
name="phoneNumber"

View File

@@ -19,6 +19,7 @@ export function SpecialRequests({
<Typography variant="Title/Overline/sm">
<p className={styles.heading}>
{intl.formatMessage({
id: "enterDetails.specialRequests.heading",
defaultMessage: "Special requests (optional)",
})}
</p>
@@ -64,6 +65,7 @@ export function SpecialRequests({
/> */}
<TextArea
label={intl.formatMessage({
id: "enterDetails.specialRequests.commentLabel",
defaultMessage:
"Is there anything else you would like us to know before your arrival?",
})}

View File

@@ -63,6 +63,7 @@ export default function HotelHeader({
restaurants={restaurants}
additionalHotelData={additionalData}
triggerLabel={intl.formatMessage({
id: "destination.seeHotelDetails",
defaultMessage: "See hotel details",
})}
buttonVariant={"secondary"}

View File

@@ -47,16 +47,19 @@ function useBookingErrorAlert() {
switch (errorCode) {
case BookingErrorCodeEnum.TransactionCancelled:
return intl.formatMessage({
id: "enterDetails.bookingAlert.transactionCancelled",
defaultMessage: "You have now cancelled your payment.",
})
case BookingErrorCodeEnum.AvailabilityError:
case BookingErrorCodeEnum.NoAvailabilityForRateAndRoomType:
return intl.formatMessage({
id: "error.availabilityErrorMessage",
defaultMessage:
"Unfortunately, one of the rooms you selected is sold out. Please choose another room to proceed.",
})
default:
return intl.formatMessage({
id: "enterDetails.bookingAlert.genericError",
defaultMessage:
"We had an issue processing your booking. Please try again. No charges have been made.",
})
@@ -151,6 +154,7 @@ export default function BookingAlert({ isVisible = false }: BookingAlertProps) {
isAvailabilityError
? {
title: intl.formatMessage({
id: "enterDetails.bookingAlert.changeRoomLink",
defaultMessage: "Change room",
}),
url: selectRateReturnUrl,

View File

@@ -13,6 +13,7 @@ export default function GuaranteeDetails() {
<Caption color="burgundy" type="bold" asChild>
<summary className={styles.summary}>
{intl.formatMessage({
id: "common.howItWorks",
defaultMessage: "How it works",
})}
<MaterialIcon
@@ -25,12 +26,14 @@ export default function GuaranteeDetails() {
<section className={styles.content}>
<Body>
{intl.formatMessage({
id: "enterDetails.payment.guaranteeInfoDescription",
defaultMessage:
"When guaranteeing your booking, we will hold the booking until 07:00 until the day after check-in. This will provide you as a guest with added flexibility for check-in times.",
})}
</Body>
<Body>
{intl.formatMessage({
id: "enterDetails.payment.guaranteeInfoWhatToDo",
defaultMessage: "What you have to do to guarantee booking:",
})}
</Body>
@@ -38,6 +41,7 @@ export default function GuaranteeDetails() {
<Body asChild>
<li>
{intl.formatMessage({
id: "enterDetails.payment.guaranteeInfoCompleteBooking",
defaultMessage: "Complete the booking",
})}
</li>
@@ -45,6 +49,7 @@ export default function GuaranteeDetails() {
<Body asChild>
<li>
{intl.formatMessage({
id: "enterDetails.payment.guaranteeInfoProvideCard",
defaultMessage: "Provide a payment card in the next step",
})}
</li>
@@ -52,6 +57,7 @@ export default function GuaranteeDetails() {
</ol>
<Body>
{intl.formatMessage({
id: "enterDetails.payment.guaranteeInfoMandatoryNote",
defaultMessage:
"Please note that this is mandatory, and that your card will only be charged in the event of a no-show.",
})}

View File

@@ -35,9 +35,11 @@ export default function MixedRatePaymentBreakdown({
}: MixedRatePaymentBreakdownProps) {
const intl = useIntl()
const payNowTitle = intl.formatMessage({
id: "booking.payNow",
defaultMessage: "Pay now",
})
const payAtCheckInTitle = intl.formatMessage({
id: "enterDetails.payment.payAtCheckInOption",
defaultMessage: "Pay at check-in",
})
@@ -125,6 +127,7 @@ function PaymentCard({
{"/ "}
{intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{

View File

@@ -22,12 +22,14 @@ export default function TimeoutSpinner() {
<LoadingSpinner />
<Subtitle className={styles.heading}>
{intl.formatMessage({
id: "enterDetails.payment.loadingTitle",
defaultMessage: "Taking longer than usual",
})}
</Subtitle>
<Body textAlign="center" className={styles.messageContainer}>
{intl.formatMessage(
{
id: "enterDetails.payment.loadingMessage",
defaultMessage:
"We are still confirming your booking. This is usually a matter of minutes and we do apologise for the wait. Please check your inbox for a booking confirmation email and if you still haven't received it by end of day, please contact our <link>customer support</link>.",
},

View File

@@ -525,8 +525,12 @@ export default function PaymentClient({
]
)
const finalStep = intl.formatMessage({ defaultMessage: "Final step" })
const finalStep = intl.formatMessage({
id: "enterDetails.payment.onlyFlexRatesTitle",
defaultMessage: "Final step",
})
const selectPayment = intl.formatMessage({
id: "enterDetails.payment.title",
defaultMessage: "Select payment method",
})
@@ -558,6 +562,7 @@ export default function PaymentClient({
<section className={styles.section}>
<Body>
{intl.formatMessage({
id: "enterDetails.payment.guaranteeInfo",
defaultMessage:
"To secure your reservation, we kindly ask you to provide your payment card details. Rest assured, no charges will be made at this time.",
})}
@@ -569,6 +574,7 @@ export default function PaymentClient({
{hasMixedRates ? (
<Body>
{intl.formatMessage({
id: "enterDetails.payment.mixedRatesInfo",
defaultMessage:
"As your booking includes rooms with different terms, we will be charging part of the booking now and the remainder will be collected by the reception at check-in.",
})}
@@ -582,6 +588,7 @@ export default function PaymentClient({
>
<Label className="sr-only">
{intl.formatMessage({
id: "enterDetails.payment.paymentMethods",
defaultMessage: "Payment methods",
})}
</Label>
@@ -591,6 +598,7 @@ export default function PaymentClient({
<Typography variant="Title/Overline/sm">
<span>
{intl.formatMessage({
id: "payment.mySavedCards",
defaultMessage: "My saved cards",
})}
</span>
@@ -612,6 +620,7 @@ export default function PaymentClient({
<Typography variant="Title/Overline/sm">
<span>
{intl.formatMessage({
id: "enterDetails.payment.otherPaymentMethods",
defaultMessage: "Other payment methods",
})}
</span>
@@ -621,6 +630,7 @@ export default function PaymentClient({
<PaymentOption
value={PaymentMethodEnum.card}
label={intl.formatMessage({
id: "common.creditCard",
defaultMessage: "Credit card",
})}
/>
@@ -650,6 +660,7 @@ export default function PaymentClient({
<Typography variant="Body/Supporting text (caption)/smRegular">
<span>
{intl.formatMessage({
id: "booking.smsConfirmationLabel",
defaultMessage:
"I would like to get my booking confirmation via sms",
})}
@@ -671,6 +682,7 @@ export default function PaymentClient({
typography="Body/Supporting text (caption)/smBold"
>
{intl.formatMessage({
id: "enterDetails.completeBooking",
defaultMessage: "Complete booking",
})}
</Button>

View File

@@ -27,6 +27,7 @@ export default function TermsAndConditions({
{isFlexBookingTerms
? intl.formatMessage(
{
id: "enterDetails.payment.flexBookingTermsAndConditions",
defaultMessage:
"I accept the terms for this booking and the general <termsAndConditionsLink>Booking & Cancellation Terms</termsAndConditionsLink>, and understand that Scandic will process my personal data for this booking in accordance with <privacyPolicyLink>Scandic's Privacy policy</privacyPolicyLink>.",
},
@@ -59,6 +60,7 @@ export default function TermsAndConditions({
)
: intl.formatMessage(
{
id: "enterDetails.payment.termsAndConditions",
defaultMessage:
"By paying with any of the payment methods available, I accept the terms for this booking and the general <termsAndConditionsLink>Booking & Cancellation Terms</termsAndConditionsLink>, and understand that Scandic will process my personal data for this booking in accordance with <privacyPolicyLink>Scandic's Privacy policy</privacyPolicyLink>. I also accept that Scandic requires a valid payment card during my visit in case anything is left unpaid.",
},
@@ -97,6 +99,7 @@ export default function TermsAndConditions({
}}
errorCodeMessages={{
[paymentError.TERMS_REQUIRED]: intl.formatMessage({
id: "common.mustAcceptTermsError",
defaultMessage: "You must accept the terms and conditions",
}),
}}
@@ -104,6 +107,7 @@ export default function TermsAndConditions({
<Typography variant="Body/Paragraph/mdBold">
<span>
{intl.formatMessage({
id: "booking.acceptBookingTerms",
defaultMessage: "I accept the booking and cancellation terms",
})}
</span>

View File

@@ -52,6 +52,7 @@ export default function PriceChangeSummary({
onClick={() => toggleOpen((isOpen) => !isOpen)}
>
{intl.formatMessage({
id: "enterDetails.priceChangeDialog.seePriceDetailsButton",
defaultMessage: "See price details",
})}
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
@@ -64,6 +65,7 @@ export default function PriceChangeSummary({
<header className={styles.header}>
<Subtitle>
{intl.formatMessage({
id: "common.priceDetails",
defaultMessage: "Price details",
})}
</Subtitle>
@@ -88,11 +90,13 @@ export default function PriceChangeSummary({
{rooms.length > 1
? intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{ roomIndex: roomNumber }
)
: intl.formatMessage({
id: "common.room",
defaultMessage: "Room",
})}
</Body>
@@ -100,6 +104,7 @@ export default function PriceChangeSummary({
<div className={styles.priceRow}>
<Caption color="uiTextMediumContrast">
{intl.formatMessage({
id: "priceDetails.roomCharge",
defaultMessage: "Room charge",
})}
</Caption>
@@ -137,6 +142,7 @@ export default function PriceChangeSummary({
<div className={styles.priceRow}>
<Caption color="uiTextMediumContrast">
{intl.formatMessage({
id: "enterDetails.priceChangeDialog.breakfastCharge",
defaultMessage: "Breakfast charge",
})}
</Caption>
@@ -181,12 +187,14 @@ export default function PriceChangeSummary({
<div className={styles.rowContainer}>
<Body>
{intl.formatMessage({
id: "common.total",
defaultMessage: "Total",
})}
</Body>
<div className={styles.priceRow}>
<Body textTransform="bold">
{intl.formatMessage({
id: "booking.priceIncludingVat",
defaultMessage: "Price including VAT",
})}
</Body>
@@ -203,11 +211,13 @@ export default function PriceChangeSummary({
<footer className={styles.footer}>
<Button intent="secondary" onClick={onCancel}>
{intl.formatMessage({
id: "enterDetails.priceChangeDialog.cancelButton",
defaultMessage: "Back to room selection",
})}
</Button>
<Button onClick={onAccept}>
{intl.formatMessage({
id: "enterDetails.priceChangeDialog.acceptButton",
defaultMessage: "Continue with new price",
})}
</Button>

View File

@@ -41,6 +41,7 @@ export default function PriceChangeDialog({
}: PriceChangeDialogProps) {
const intl = useIntl()
const title = intl.formatMessage({
id: "enterDetails.priceChangeDialog.title",
defaultMessage: "Price change",
})
const rooms = useEnterDetailsStore((state) => state.rooms)
@@ -68,6 +69,7 @@ export default function PriceChangeDialog({
const roomSelectionMsg = intl.formatMessage(
{
id: "enterDetails.priceChangeDialog.descriptionPreviousRooms",
defaultMessage: "{totalRooms, plural, one {room} other {rooms}}",
},
{
@@ -77,6 +79,7 @@ export default function PriceChangeDialog({
const newRoomSelectionMsg = intl.formatMessage(
{
id: "enterDetails.priceChangeDialog.descriptionNewRooms",
defaultMessage:
"{totalRooms, plural, one {a new room} other {new rooms}}",
},
@@ -112,6 +115,7 @@ export default function PriceChangeDialog({
<Body textAlign="center">
{intl.formatMessage(
{
id: "enterDetails.priceChangeDialog.description",
defaultMessage:
"Prices have increased since you selected your {roomSelection}.{linebreak} To continue your booking, accept the updated price,{linebreak} or go back to select {newRoomSelection}.",
},
@@ -125,6 +129,7 @@ export default function PriceChangeDialog({
<div>
<Subtitle textAlign="center" color="burgundy">
{intl.formatMessage({
id: "enterDetails.priceChangeDialog.newTotalLabel",
defaultMessage: "New total",
})}
</Subtitle>
@@ -148,11 +153,13 @@ export default function PriceChangeDialog({
<footer className={styles.footer}>
<Button intent="secondary" onClick={onCancel}>
{intl.formatMessage({
id: "enterDetails.priceChangeDialog.cancelButton",
defaultMessage: "Back to room selection",
})}
</Button>
<Button onClick={onAccept}>
{intl.formatMessage({
id: "enterDetails.priceChangeDialog.acceptButton",
defaultMessage: "Continue with new price",
})}
</Button>

View File

@@ -41,6 +41,7 @@ export default function Multiroom() {
<Title level="h2" as="h4">
{intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{
@@ -54,8 +55,14 @@ export default function Multiroom() {
{room.bedTypes.length ? (
<Section
header={intl.formatMessage({ defaultMessage: "Bed preference" })}
label={intl.formatMessage({ defaultMessage: "Preferred bed type" })}
header={intl.formatMessage({
id: "booking.bedPreference",
defaultMessage: "Bed preference",
})}
label={intl.formatMessage({
id: "enterDetails.bedPreference.description",
defaultMessage: "Preferred bed type",
})}
additionalInfo={bedTypeInfoText}
step={EnterDetailsStepEnum.selectBed}
>
@@ -66,9 +73,11 @@ export default function Multiroom() {
{showBreakfastStep ? (
<Section
header={intl.formatMessage({
id: "common.breakfast",
defaultMessage: "Breakfast",
})}
label={intl.formatMessage({
id: "enterDetails.breakfast.description",
defaultMessage: "Select breakfast options",
})}
step={EnterDetailsStepEnum.breakfast}
@@ -79,10 +88,12 @@ export default function Multiroom() {
<Section
header={intl.formatMessage({
id: "enterDetails.details.title",
defaultMessage: "Details",
})}
step={EnterDetailsStepEnum.details}
label={intl.formatMessage({
id: "enterDetails.details.description",
defaultMessage: "Contact details",
})}
>

View File

@@ -45,6 +45,7 @@ export default function RoomOne({ user }: { user: User | null }) {
<Title level="h2" as="h4">
{intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{
@@ -59,8 +60,14 @@ export default function RoomOne({ user }: { user: User | null }) {
{room.bedTypes ? (
<Section
header={intl.formatMessage({ defaultMessage: "Bed preference" })}
label={intl.formatMessage({ defaultMessage: "Preferred bed type" })}
header={intl.formatMessage({
id: "booking.bedPreference",
defaultMessage: "Bed preference",
})}
label={intl.formatMessage({
id: "enterDetails.bedPreference.description",
defaultMessage: "Preferred bed type",
})}
additionalInfo={bedTypeInfoText}
step={EnterDetailsStepEnum.selectBed}
>
@@ -71,9 +78,11 @@ export default function RoomOne({ user }: { user: User | null }) {
{showBreakfastStep ? (
<Section
header={intl.formatMessage({
id: "common.breakfast",
defaultMessage: "Breakfast",
})}
label={intl.formatMessage({
id: "enterDetails.breakfast.description",
defaultMessage: "Select breakfast options",
})}
step={EnterDetailsStepEnum.breakfast}
@@ -84,10 +93,12 @@ export default function RoomOne({ user }: { user: User | null }) {
<Section
header={intl.formatMessage({
id: "enterDetails.details.title",
defaultMessage: "Details",
})}
step={EnterDetailsStepEnum.details}
label={intl.formatMessage({
id: "enterDetails.details.description",
defaultMessage: "Contact details",
})}
>

View File

@@ -6,10 +6,12 @@ export function getBedTypeInfoText(
hasMultipleBedTypes: boolean
) {
const availabilityText = intl.formatMessage({
id: "booking.subjectToAvailability",
defaultMessage: "Subject to availability",
})
const extraBedText = intl.formatMessage({
id: "enterDetails.room.extraBedText",
defaultMessage: "Extra bed will be provided additionally",
})

View File

@@ -34,9 +34,11 @@ export default function Section({
const [title, setTitle] = useState(label)
const noBreakfastTitle = intl.formatMessage({
id: "common.noBreakfast",
defaultMessage: "No breakfast",
})
const breakfastTitle = intl.formatMessage({
id: "common.breakfastBuffet",
defaultMessage: "Breakfast buffet",
})

View File

@@ -56,6 +56,7 @@ export default function SelectedRoom() {
>
<h2>
{intl.formatMessage({
id: "common.room",
defaultMessage: "Room",
})}
</h2>
@@ -67,6 +68,7 @@ export default function SelectedRoom() {
>
{intl.formatMessage(
{
id: "enterDetails.selectedRoom.roomType.description",
defaultMessage: "{roomType} <rate>{rateDescription}</rate>",
},
{
@@ -88,6 +90,7 @@ export default function SelectedRoom() {
>
<MaterialIcon icon="edit_square" size={20} color="CurrentColor" />
{intl.formatMessage({
id: "common.change",
defaultMessage: "Change",
})}
</Button>
@@ -100,6 +103,7 @@ export default function SelectedRoom() {
room={selectedRoom}
buttonVariant="primary"
triggerLabel={intl.formatMessage({
id: "hotel.seeRoomDetails",
defaultMessage: "See room details",
})}
wrapping={false}

View File

@@ -80,6 +80,7 @@ export default function SummaryBottomSheet({
<Typography variant="Body/Supporting text (caption)/smRegular">
<span className={styles.priceLabel}>
{intl.formatMessage({
id: "common.totalPrice",
defaultMessage: "Total price",
})}
</span>
@@ -117,6 +118,7 @@ export default function SummaryBottomSheet({
<span className={styles.seeDetails}>
<span>
{intl.formatMessage({
id: "booking.seeDetails",
defaultMessage: "See details",
})}
</span>
@@ -139,6 +141,7 @@ export default function SummaryBottomSheet({
form={formId}
>
{intl.formatMessage({
id: "enterDetails.completeBooking",
defaultMessage: "Complete booking",
})}
</Button>

View File

@@ -26,6 +26,7 @@ export default function Breakfast({
const intl = useIntl()
const breakfastBuffet = intl.formatMessage({
id: "common.breakfastBuffet",
defaultMessage: "Breakfast buffet",
})
@@ -36,7 +37,10 @@ export default function Breakfast({
breakfast.localPrice.price * adults * nights,
breakfast.localPrice.currency
)
: intl.formatMessage({ defaultMessage: "Included" })
: intl.formatMessage({
id: "common.included",
defaultMessage: "Included",
})
return (
<div className={styles.entry}>
<div>
@@ -55,7 +59,10 @@ export default function Breakfast({
}
if (breakfast === false) {
const noBreakfast = intl.formatMessage({ defaultMessage: "No breakfast" })
const noBreakfast = intl.formatMessage({
id: "common.noBreakfast",
defaultMessage: "No breakfast",
})
return (
<div className={styles.entry}>
<Typography variant="Body/Paragraph/mdRegular">

View File

@@ -78,6 +78,7 @@ export default function Room({
const adultsMsg = intl.formatMessage(
{
id: "common.numberOfAdults",
defaultMessage: "{totalAdults, plural, one {# adult} other {# adults}}",
},
{ totalAdults: adults }
@@ -87,6 +88,7 @@ export default function Room({
if (childrenInRoom?.length) {
const childrenMsg = intl.formatMessage(
{
id: "common.numberOfChildren",
defaultMessage:
"{totalChildren, plural, one {# child} other {# children}}",
},
@@ -135,6 +137,7 @@ export default function Room({
<p className={styles.roomTitle}>
{intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{
@@ -189,6 +192,7 @@ export default function Room({
wrapping={false}
>
{intl.formatMessage({
id: "booking.rateDetails",
defaultMessage: "Rate details",
})}
<MaterialIcon
@@ -254,6 +258,7 @@ export default function Room({
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{intl.formatMessage({
id: "booking.subjectToAvailability",
defaultMessage: "Subject to availability",
})}
</p>
@@ -274,6 +279,7 @@ export default function Room({
<p>
{intl.formatMessage(
{
id: "booking.numberOfCribs",
defaultMessage: "Crib (child) × {count}",
},
{ count: childBedCrib }
@@ -282,6 +288,7 @@ export default function Room({
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{intl.formatMessage({
id: "booking.subjectToAvailability",
defaultMessage: "Subject to availability",
})}
</p>
@@ -303,6 +310,7 @@ export default function Room({
<p>
{intl.formatMessage(
{
id: "booking.extraBedsCount",
defaultMessage: "Extra bed (child) × {count}",
},
{
@@ -313,6 +321,7 @@ export default function Room({
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{intl.formatMessage({
id: "booking.subjectToAvailability",
defaultMessage: "Subject to availability",
})}
</p>

View File

@@ -56,6 +56,7 @@ export default function SummaryUI({
const nightsMsg = intl.formatMessage(
{
id: "booking.numberOfNights",
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
},
{ totalNights: nights }
@@ -102,6 +103,7 @@ export default function SummaryUI({
>
<Subtitle className={styles.title} type="two">
{intl.formatMessage({
id: "booking.bookingSummary",
defaultMessage: "Booking summary",
})}
</Subtitle>
@@ -144,6 +146,7 @@ export default function SummaryUI({
<p>
{intl.formatMessage(
{
id: "booking.totalPriceInclVat",
defaultMessage: "<b>Total price</b> (incl VAT)",
},
{
@@ -161,6 +164,7 @@ export default function SummaryUI({
<p className={styles.approxPrice}>
{intl.formatMessage(
{
id: "booking.approxValue",
defaultMessage: "Approx. {value}",
},
{

View File

@@ -15,6 +15,7 @@ export default function FnFNotAllowedAlert() {
<Alert
type={AlertTypeEnum.Warning}
text={intl.formatMessage({
id: "fnf.alert.text",
defaultMessage:
"The Friends & Family rate can only be booked via FUSE.",
})}

View File

@@ -24,6 +24,7 @@ export default function HotelCardDialogListing({
)
const currencyValue = isRedemption
? intl.formatMessage({
id: "common.points",
defaultMessage: "Points",
})
: undefined

View File

@@ -219,6 +219,7 @@ export default function HotelCardListing({
restaurants={hotel.restaurants}
additionalHotelData={hotel.additionalData}
triggerLabel={intl.formatMessage({
id: "destination.seeHotelDetails",
defaultMessage: "See hotel details",
})}
buttonVariant="primary"
@@ -241,6 +242,7 @@ export default function HotelCardListing({
position="right"
onClick={scrollToTop}
label={intl.formatMessage({
id: "common.backToTop",
defaultMessage: "Back to top",
})}
/>

View File

@@ -43,7 +43,10 @@ export function HotelSidePeekContent({
<div className={styles.content}>
<Typography variant="Title/Subtitle/lg">
<h3>
{intl.formatMessage({ defaultMessage: "Practical information" })}
{intl.formatMessage({
id: "common.practicalInformation",
defaultMessage: "Practical information",
})}
</h3>
</Typography>
<Contact hotel={hotel} />
@@ -71,6 +74,7 @@ export function HotelSidePeekContent({
typography="Body/Paragraph/mdBold"
>
{intl.formatMessage({
id: "hotelSidePeek.readMore.buttonText",
defaultMessage: "Read more about the hotel",
})}
</ButtonLink>
@@ -95,6 +99,7 @@ function AccessibilityAccordionItem({
return (
<AccordionItem
title={intl.formatMessage({
id: "common.accessibility",
defaultMessage: "Accessibility",
})}
iconName={IconName.Accessibility}

View File

@@ -59,6 +59,7 @@ export default function ListingHotelCardDialog({
const altText = images[0]?.altText || images[0]?.altText_En
const notEnoughPointsLabel = intl.formatMessage({
id: "booking.notEnoughPoints",
defaultMessage: "Not enough points",
})
const shouldShowNotEnoughPoints = redemptionPrice && !hasEnoughPoints
@@ -71,6 +72,7 @@ export default function ListingHotelCardDialog({
className={styles.closeButton}
onPress={handleClose}
aria-label={intl.formatMessage({
id: "common.close",
defaultMessage: "Close",
})}
>
@@ -114,12 +116,14 @@ export default function ListingHotelCardDialog({
{redemptionPrice ? (
<Caption color="uiTextHighContrast">
{intl.formatMessage({
id: "hotelCard.availableRates",
defaultMessage: "Available rates",
})}
</Caption>
) : (
<Caption color="uiTextHighContrast">
{intl.formatMessage({
id: "listingHotelCardDialog.perNightFrom",
defaultMessage: "Per night from",
})}
</Caption>
@@ -145,6 +149,7 @@ export default function ListingHotelCardDialog({
<Subtitle type="two" color="red">
{intl.formatMessage(
{
id: "common.priceCurrency",
defaultMessage: "{price} {currency}",
},
{
@@ -164,6 +169,7 @@ export default function ListingHotelCardDialog({
<Subtitle type="two">
{intl.formatMessage(
{
id: "common.priceCurrency",
defaultMessage: "{price} {currency}",
},
{
@@ -176,6 +182,7 @@ export default function ListingHotelCardDialog({
" + " +
intl.formatMessage(
{
id: "common.priceCurrency",
defaultMessage: "{price} {currency}",
},
{
@@ -189,6 +196,7 @@ export default function ListingHotelCardDialog({
<span>
/
{intl.formatMessage({
id: "common.night",
defaultMessage: "night",
})}
</span>
@@ -199,6 +207,7 @@ export default function ListingHotelCardDialog({
<Subtitle type="two">
{intl.formatMessage(
{
id: "common.priceCurrency",
defaultMessage: "{price} {currency}",
},
{
@@ -211,6 +220,7 @@ export default function ListingHotelCardDialog({
<span>
/
{intl.formatMessage({
id: "common.night",
defaultMessage: "night",
})}
</span>
@@ -238,6 +248,7 @@ export default function ListingHotelCardDialog({
keepSearchParams
>
{intl.formatMessage({
id: "common.seeRooms",
defaultMessage: "See rooms",
})}
</Link>

View File

@@ -32,11 +32,13 @@ export default function Breakfast({
const intl = useIntl()
const breakfastBuffet = intl.formatMessage({
id: "common.breakfastBuffet",
defaultMessage: "Breakfast buffet",
})
const adultsMsg = intl.formatMessage(
{
id: "priceDetails.breakfastAdultsDetails",
defaultMessage:
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}",
},
@@ -47,6 +49,7 @@ export default function Breakfast({
if (childrenInRoom?.length) {
kidsMsg = intl.formatMessage(
{
id: "priceDetails.breakfastChildrenDetails",
defaultMessage:
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
},
@@ -58,7 +61,10 @@ export default function Breakfast({
}
if (breakfastIncluded) {
const included = intl.formatMessage({ defaultMessage: "Included" })
const included = intl.formatMessage({
id: "common.included",
defaultMessage: "Included",
})
return (
<Tbody>
<RegularRow label={adultsMsg} value={included} />
@@ -115,6 +121,7 @@ export default function Breakfast({
const freeChildrenMsg = intl.formatMessage(
{
id: "priceDetails.breakfastChildrenDetails",
defaultMessage:
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
},
@@ -129,6 +136,7 @@ export default function Breakfast({
<RegularRow
label={intl.formatMessage(
{
id: "priceDetails.breakfastAdultsDetails",
defaultMessage:
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}",
},
@@ -140,6 +148,7 @@ export default function Breakfast({
<RegularRow
label={intl.formatMessage(
{
id: "priceDetails.breakfastChildrenDetails",
defaultMessage:
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
},
@@ -161,6 +170,7 @@ export default function Breakfast({
<RegularRow
label={intl.formatMessage(
{
id: "priceDetails.breakfastChildrenDetails",
defaultMessage:
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
},
@@ -179,6 +189,7 @@ export default function Breakfast({
if (breakfast === false) {
const noBreakfast = intl.formatMessage({
id: "common.noBreakfast",
defaultMessage: "No breakfast",
})
return (

View File

@@ -38,6 +38,7 @@ export default function CorporateChequePrice({
}
const averagePriceTitle = intl.formatMessage({
id: "priceDetails.averagePricePerNight",
defaultMessage: "Average price per night",
})
@@ -57,7 +58,10 @@ export default function CorporateChequePrice({
return (
<>
<BoldRow
label={intl.formatMessage({ defaultMessage: "Room charge" })}
label={intl.formatMessage({
id: "priceDetails.roomCharge",
defaultMessage: "Room charge",
})}
value={formatPrice(
intl,
price.numberOfCheques,

View File

@@ -43,6 +43,7 @@ export default function RedemptionPrice({
}
const averagePriceTitle = intl.formatMessage({
id: "priceDetails.averagePricePerNight",
defaultMessage: "Average price per night",
})
@@ -61,7 +62,10 @@ export default function RedemptionPrice({
return (
<>
<BoldRow
label={intl.formatMessage({ defaultMessage: "Room charge" })}
label={intl.formatMessage({
id: "priceDetails.roomCharge",
defaultMessage: "Room charge",
})}
value={formatPrice(
intl,
price.pointsPerStay,

View File

@@ -40,6 +40,7 @@ export default function RegularPrice({
}
const averagePriceTitle = intl.formatMessage({
id: "priceDetails.averagePricePerNight",
defaultMessage: "Average price per night",
})
@@ -62,7 +63,10 @@ export default function RegularPrice({
return (
<>
<BoldRow
label={intl.formatMessage({ defaultMessage: "Room charge" })}
label={intl.formatMessage({
id: "priceDetails.roomCharge",
defaultMessage: "Room charge",
})}
value={roomCharge}
regularValue={regularCharge}
isDiscounted={isDiscounted}

View File

@@ -37,6 +37,7 @@ export default function VoucherPrice({
}
const averagePriceTitle = intl.formatMessage({
id: "priceDetails.averagePricePerNight",
defaultMessage: "Average price per night",
})
@@ -49,7 +50,10 @@ export default function VoucherPrice({
return (
<>
<BoldRow
label={intl.formatMessage({ defaultMessage: "Room charge" })}
label={intl.formatMessage({
id: "priceDetails.roomCharge",
defaultMessage: "Room charge",
})}
value={formatPrice(intl, price.numberOfVouchers, CurrencyEnum.Voucher)}
/>
{nights > 1 ? (

View File

@@ -33,11 +33,17 @@ export default function VatRow({ totalPrice, vat }: VatProps) {
return (
<>
<RegularRow
label={intl.formatMessage({ defaultMessage: "Price excluding VAT" })}
label={intl.formatMessage({
id: "booking.priceExcludingVat",
defaultMessage: "Price excluding VAT",
})}
value={formatPrice(intl, priceExclVat, totalPrice.local.currency)}
/>
<RegularRow
label={intl.formatMessage({ defaultMessage: "VAT {vat}%" }, { vat })}
label={intl.formatMessage(
{ id: "priceDetails.VAT", defaultMessage: "VAT {vat}%" },
{ vat }
)}
value={formatPrice(intl, vatAmount, totalPrice.local.currency)}
/>
</>

View File

@@ -83,7 +83,10 @@ export default function PriceDetailsTable({
const nights = dt(toDate).diff(fromDate, "days")
const nightsMsg = intl.formatMessage(
{ defaultMessage: "{totalNights, plural, one {# night} other {# nights}}" },
{
id: "booking.numberOfNights",
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
},
{ totalNights: nights }
)
@@ -157,7 +160,10 @@ export default function PriceDetailsTable({
<Typography variant="Body/Paragraph/mdBold">
<span>
{intl.formatMessage(
{ defaultMessage: "Room {roomIndex}" },
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{ roomIndex: idx + 1 }
)}
</span>
@@ -209,13 +215,21 @@ export default function PriceDetailsTable({
)
})}
<Tbody>
<HeaderRow title={intl.formatMessage({ defaultMessage: "Total" })} />
<HeaderRow
title={intl.formatMessage({
id: "common.total",
defaultMessage: "Total",
})}
/>
<VatRow totalPrice={totalPrice} vat={vat} />
<LargeRow
allPricesIsDiscounted={allPricesIsDiscounted}
label={intl.formatMessage({ defaultMessage: "Price including VAT" })}
label={intl.formatMessage({
id: "booking.priceIncludingVat",
defaultMessage: "Price including VAT",
})}
price={totalPrice}
/>

View File

@@ -24,7 +24,10 @@ function Trigger({ title }: { title: string }) {
export default function PriceDetailsModal(props: PriceDetailsTableProps) {
const intl = useIntl()
const title = intl.formatMessage({ defaultMessage: "Price details" })
const title = intl.formatMessage({
id: "common.priceDetails",
defaultMessage: "Price details",
})
return (
<Modal title={title} trigger={<Trigger title={title} />}>
<PriceDetailsTable {...props} />

View File

@@ -30,6 +30,7 @@ export function RoomSidePeekContent({ room }: RoomSidePeekContentProps) {
<p>
{intl.formatMessage(
{
id: "roomSidePeek.maxNumberOfGuests",
defaultMessage:
"Max. {max, plural, one {{range} guest} other {{range} guests}}",
},
@@ -47,6 +48,7 @@ export function RoomSidePeekContent({ room }: RoomSidePeekContentProps) {
{roomSize.min === roomSize.max
? intl.formatMessage(
{
id: "common.roomSize",
defaultMessage: "{roomSize} m²",
},
{
@@ -55,6 +57,7 @@ export function RoomSidePeekContent({ room }: RoomSidePeekContentProps) {
)
: intl.formatMessage(
{
id: "selectRate.roomSizeMinToMax",
defaultMessage: "{roomSizeMin}{roomSizeMax} m²",
},
{
@@ -73,6 +76,7 @@ export function RoomSidePeekContent({ room }: RoomSidePeekContentProps) {
<Typography variant="Title/Subtitle/md">
<p>
{intl.formatMessage({
id: "booking.roomAmenities",
defaultMessage: "Room amenities",
})}
</p>
@@ -94,6 +98,7 @@ export function RoomSidePeekContent({ room }: RoomSidePeekContentProps) {
? facility.name
: intl.formatMessage(
{
id: "roomSidePeek.facilityAvailableInSomeRooms",
defaultMessage:
"{facility} (available in some rooms)",
},
@@ -112,6 +117,7 @@ export function RoomSidePeekContent({ room }: RoomSidePeekContentProps) {
<Typography variant="Title/Subtitle/md">
<p>
{intl.formatMessage({
id: "common.bedOptions",
defaultMessage: "Bed options",
})}
</p>
@@ -119,6 +125,7 @@ export function RoomSidePeekContent({ room }: RoomSidePeekContentProps) {
<Typography variant="Body/Paragraph/mdRegular">
<p>
{intl.formatMessage({
id: "booking.subjectToAvailability",
defaultMessage: "Subject to availability",
})}
</p>
@@ -148,6 +155,7 @@ export function RoomSidePeekContent({ room }: RoomSidePeekContentProps) {
<Typography variant="Title/Subtitle/md">
<p>
{intl.formatMessage({
id: "hotel.aboutTheHotel",
defaultMessage: "About the hotel",
})}
</p>

View File

@@ -74,25 +74,29 @@ export default function FilterAndSortModal({
const sortItems: SortItem[] = [
{
label: intl.formatMessage({
id: "filter.distanceToCityCenter",
defaultMessage: "Distance to city center",
}),
value: SortOrder.Distance,
},
{
label: intl.formatMessage({
id: "common.name",
defaultMessage: "Name",
}),
value: SortOrder.Name,
},
{
label: intl.formatMessage({
id: "common.price",
defaultMessage: "Price",
}),
value: SortOrder.Price,
},
{
label: intl.formatMessage({
defaultMessage: "Tripadvisor rating",
id: "common.tripAdvisorRating",
defaultMessage: "TripAdvisor rating",
}),
value: SortOrder.TripAdvisorRating,
},
@@ -144,6 +148,7 @@ export default function FilterAndSortModal({
<Typography variant="Body/Supporting text (caption)/smBold">
<p>
{intl.formatMessage({
id: "filter.filterAndSort",
defaultMessage: "Filter and sort",
})}
</p>
@@ -166,6 +171,7 @@ export default function FilterAndSortModal({
>
<p>
{intl.formatMessage({
id: "filter.filterAndSort",
defaultMessage: "Filter and sort",
})}
</p>
@@ -175,6 +181,7 @@ export default function FilterAndSortModal({
style="Muted"
onPress={close}
aria-label={intl.formatMessage({
id: "common.close",
defaultMessage: "Close",
})}
>
@@ -188,6 +195,7 @@ export default function FilterAndSortModal({
searchParams.get("sort") ?? DEFAULT_SORT
}
label={intl.formatMessage({
id: "filter.sortBy",
defaultMessage: "Sort by",
})}
name="sort"
@@ -224,6 +232,7 @@ export default function FilterAndSortModal({
<p>
{intl.formatMessage(
{
id: "filter.seeResultsCount",
defaultMessage: "See results ({ count })",
},
{
@@ -248,6 +257,7 @@ export default function FilterAndSortModal({
<Typography variant="Body/Paragraph/mdBold">
<p>
{intl.formatMessage({
id: "filter.clearAllFilters",
defaultMessage: "Clear all filters",
})}
</p>

View File

@@ -2,6 +2,7 @@ import { useSearchParams } from "next/navigation"
import { useEffect, useState } from "react"
import { useIntl } from "react-intl"
import Title from "@scandic-hotels/design-system/Title"
import { Typography } from "@scandic-hotels/design-system/Typography"
import {
@@ -115,17 +116,17 @@ export default function FilterContent({
return (
<aside className={`${styles.container} ${className}`}>
<div>
<Typography variant={"Title/xs"} className={styles.filterByTitle}>
<h4>
{intl.formatMessage({
defaultMessage: "Filter by",
})}
</h4>
</Typography>
<Title as="h4">
{intl.formatMessage({
id: "filter.filterBy",
defaultMessage: "Filter by",
})}
</Title>
<div className={styles.facilities}>
<Typography variant="Title/Subtitle/md">
<p>
{intl.formatMessage({
id: "filter.facilities",
defaultMessage: "Hotel facilities",
})}
</p>
@@ -139,6 +140,7 @@ export default function FilterContent({
<Typography variant="Title/Subtitle/md">
<p>
{intl.formatMessage({
id: "filter.hotelSurroundings",
defaultMessage: "Hotel surroundings",
})}
</p>

View File

@@ -15,6 +15,7 @@ export default function HotelCount() {
<span>
{intl.formatMessage(
{
id: "common.numberOfHotels",
defaultMessage: "{amount, plural, one {# hotel} other {# hotels}}",
},
{ amount: resultCount }

View File

@@ -56,25 +56,29 @@ export default function HotelSorter({ discreet }: HotelSorterProps) {
const sortItems: SortItem[] = [
{
label: intl.formatMessage({
id: "filter.distanceToCityCenter",
defaultMessage: "Distance to city center",
}),
value: SortOrder.Distance,
},
{
label: intl.formatMessage({
id: "common.name",
defaultMessage: "Name",
}),
value: SortOrder.Name,
},
{
label: intl.formatMessage({
id: "common.price",
defaultMessage: "Price",
}),
value: SortOrder.Price,
},
{
label: intl.formatMessage({
defaultMessage: "Tripadvisor rating",
id: "common.tripAdvisorRating",
defaultMessage: "TripAdvisor rating",
}),
value: SortOrder.TripAdvisorRating,
},
@@ -85,9 +89,11 @@ export default function HotelSorter({ discreet }: HotelSorterProps) {
items={sortItems}
defaultSelectedKey={searchParams.get("sort") ?? DEFAULT_SORT}
label={intl.formatMessage({
id: "filter.sortBy",
defaultMessage: "Sort by",
})}
aria-label={intl.formatMessage({
id: "filter.sortBy",
defaultMessage: "Sort by",
})}
name="sort"

View File

@@ -20,6 +20,7 @@ export function MapWithButtonWrapper({ children }: React.PropsWithChildren) {
>
<MaterialIcon icon="map" color="CurrentColor" size={20} />
{intl.formatMessage({
id: "destination.seeOnMap",
defaultMessage: "See on map",
})}
</FakeButton>

View File

@@ -45,6 +45,7 @@ export default function MobileMapButtonContainer({
>
<MaterialIcon icon="map" color="CurrentColor" />
{intl.formatMessage({
id: "destination.seeOnMap",
defaultMessage: "See on map",
})}
</Link>

View File

@@ -41,9 +41,11 @@ export default function NoAvailabilityAlert({
<Alert
type={AlertTypeEnum.Info}
heading={intl.formatMessage({
defaultMessage: "No hotels match your filters",
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.",
})}
@@ -54,6 +56,7 @@ export default function NoAvailabilityAlert({
if (bookingCode && isBookingCodeRateNotAvailable && hotelsLength > 0) {
const bookingCodeText = intl.formatMessage(
{
id: "selectHotel.noAvailabilityForBookingCode",
defaultMessage:
"We found no available rooms using this booking code ({bookingCode}). See available rates below.",
},
@@ -63,6 +66,7 @@ export default function NoAvailabilityAlert({
<Alert
type={AlertTypeEnum.Info}
heading={intl.formatMessage({
id: "booking.noAvailability",
defaultMessage: "No availability",
})}
text={bookingCodeText}
@@ -79,14 +83,17 @@ export default function NoAvailabilityAlert({
<Alert
type={AlertTypeEnum.Info}
heading={intl.formatMessage({
id: "booking.noAvailability",
defaultMessage: "No availability",
})}
text={intl.formatMessage({
id: "selectHotel.noAvailability.changeSearchText",
defaultMessage:
"Please try and change your search for this destination or see alternative hotels.",
})}
link={{
title: intl.formatMessage({
id: "booking.seeAlternativeHotels",
defaultMessage: "See alternative hotels",
}),
url: `${alternativeHotels(lang)}?hotel=${operaId}`,
@@ -100,9 +107,11 @@ export default function NoAvailabilityAlert({
<Alert
type={AlertTypeEnum.Info}
heading={intl.formatMessage({
id: "booking.noAvailability",
defaultMessage: "No availability",
})}
text={intl.formatMessage({
id: "booking.noRoomsAvailable",
defaultMessage: "There are no rooms available that match your request.",
})}
/>

View File

@@ -178,6 +178,7 @@ export function SelectHotelMapContent({
<Typography variant="Body/Supporting text (caption)/smBold">
<p>
{intl.formatMessage({
id: "selectHotel.closeMap",
defaultMessage: "Close the map",
})}
</p>
@@ -222,7 +223,12 @@ export function SelectHotelMapContent({
size={20}
/>
<Typography variant="Body/Supporting text (caption)/smBold">
<p>{intl.formatMessage({ defaultMessage: "Back" })}</p>
<p>
{intl.formatMessage({
id: "common.back",
defaultMessage: "Back",
})}
</p>
</Typography>
</Link>
</Button>
@@ -250,6 +256,7 @@ export function SelectHotelMapContent({
position="left"
onClick={scrollToTop}
label={intl.formatMessage({
id: "common.backToTop",
defaultMessage: "Back to top",
})}
/>

View File

@@ -6,6 +6,7 @@ export function AmenitiesSidePeekLabel() {
return (
<>
{intl.formatMessage({
id: "hotel.seeAllAmenities",
defaultMessage: "See all amenities",
})}
</>

View File

@@ -33,6 +33,7 @@ export default function AvailabilityError({ booking }: AvailabilityErrorProps) {
errorCode === BookingErrorCodeEnum.AvailabilityError
const errorMessage = intl.formatMessage({
id: "error.availabilityErrorMessage",
defaultMessage:
"Unfortunately, one of the rooms you selected is sold out. Please choose another room to proceed.",
})

View File

@@ -40,16 +40,18 @@ export function DesktopSummary({
const totalNights = intl.formatMessage(
{
id: "booking.numberOfNights",
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
},
{ totalNights: input.nights }
)
const totalAdults = intl.formatMessage(
{
defaultMessage: "{totalAdults, plural, one {# adult} other {# adults}}",
id: "booking.numberOfAdults",
defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
},
{
totalAdults:
adults:
input.data?.booking.rooms.reduce((acc, room) => acc + room.adults, 0) ??
0,
}
@@ -59,11 +61,11 @@ export function DesktopSummary({
)
const childrenInroom = intl.formatMessage(
{
defaultMessage:
"{totalChildren, plural, one {# child} other {# children}}",
id: "booking.numberOfChildren",
defaultMessage: "{children, plural, one {# child} other {# children}}",
},
{
totalChildren: input.data?.booking.rooms.reduce(
children: input.data?.booking.rooms.reduce(
(acc, room) => acc + (room.childrenInRoom?.length ?? 0),
0
),
@@ -73,6 +75,7 @@ export function DesktopSummary({
const totalChildren = childrenInOneOrMoreRooms ? `, ${childrenInroom}` : ""
const totalRooms = intl.formatMessage(
{
id: "booking.numberOfRooms",
defaultMessage: "{totalRooms, plural, one {# room} other {# rooms}}",
},
{ totalRooms: input.roomCount }
@@ -137,6 +140,7 @@ export function DesktopSummary({
<Body>
{intl.formatMessage(
{
id: "booking.totalPriceInclVat",
defaultMessage: "<b>Total price</b> (incl VAT)",
},
{ b: (str) => <b>{str}</b> }
@@ -175,6 +179,7 @@ export function DesktopSummary({
<Body color="uiTextMediumContrast">
{intl.formatMessage(
{
id: "booking.approxValue",
defaultMessage: "Approx. {value}",
},
{
@@ -193,6 +198,7 @@ export function DesktopSummary({
<div className={styles.summaryPriceTextMobile}>
<Caption color="uiTextHighContrast">
{intl.formatMessage({
id: "common.totalPrice",
defaultMessage: "Total price",
})}
</Caption>
@@ -219,6 +225,7 @@ export function DesktopSummary({
type="submit"
>
{intl.formatMessage({
id: "common.continue",
defaultMessage: "Continue",
})}
</Button>
@@ -246,6 +253,7 @@ function RateSummary({
<Subtitle color="uiTextPlaceholder">
{intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{ roomIndex: roomIndex + 1 }
@@ -253,6 +261,7 @@ function RateSummary({
</Subtitle>
<Body color="uiTextPlaceholder">
{intl.formatMessage({
id: "booking.selectRoom",
defaultMessage: "Select room",
})}
</Body>
@@ -266,9 +275,7 @@ function RateSummary({
<>
<Subtitle color="uiTextHighContrast">
{intl.formatMessage(
{
defaultMessage: "Room {roomIndex}",
},
{ id: "booking.roomIndex", defaultMessage: "Room {roomIndex}" },
{ roomIndex: roomIndex + 1 }
)}
</Subtitle>
@@ -292,18 +299,23 @@ function RateSummary({
function useRateDetails() {
const intl = useIntl()
const freeCancelation = intl.formatMessage({
id: "booking.freeCancellation",
defaultMessage: "Free cancellation",
})
const nonRefundable = intl.formatMessage({
id: "booking.nonRefundable",
defaultMessage: "Non-refundable",
})
const freeBooking = intl.formatMessage({
id: "booking.freeRebooking",
defaultMessage: "Free rebooking",
})
const payLater = intl.formatMessage({
id: "booking.payLater",
defaultMessage: "Pay later",
})
const payNow = intl.formatMessage({
id: "booking.payNow",
defaultMessage: "Pay now",
})

View File

@@ -41,6 +41,7 @@ export default function SummaryContent({
const nightsLabel = intl.formatMessage(
{
id: "booking.numberOfNights",
defaultMessage: "{totalNights, plural, one {# night} other {# nights}}",
},
{ totalNights: input.nights }
@@ -76,6 +77,7 @@ export default function SummaryContent({
<Typography variant="Title/Subtitle/md">
<h3 className={styles.heading}>
{intl.formatMessage({
id: "booking.bookingSummary",
defaultMessage: "Booking summary",
})}
</h3>
@@ -137,6 +139,7 @@ export default function SummaryContent({
<p>
{intl.formatMessage(
{
id: "booking.totalPriceInclVat",
defaultMessage: "<b>Total price</b> (incl VAT)",
},
{
@@ -154,6 +157,7 @@ export default function SummaryContent({
<p className={styles.approxPrice}>
{intl.formatMessage(
{
id: "booking.approxValue",
defaultMessage: "Approx. {value}",
},
{

View File

@@ -71,19 +71,20 @@ export default function Room({
const adultsMsg = intl.formatMessage(
{
defaultMessage: "{totalAdults, plural, one {# adult} other {# adults}}",
id: "booking.numberOfAdults",
defaultMessage: "{adults, plural, one {# adult} other {# adults}}",
},
{ totalAdults: adults }
{ adults }
)
const guestsParts = [adultsMsg]
if (childrenInRoom?.length) {
const childrenMsg = intl.formatMessage(
{
defaultMessage:
"{totalChildren, plural, one {# child} other {# children}}",
id: "booking.numberOfChildren",
defaultMessage: "{children, plural, one {# child} other {# children}}",
},
{ totalChildren: childrenInRoom.length }
{ children: childrenInRoom.length }
)
guestsParts.push(childrenMsg)
}
@@ -99,6 +100,7 @@ export default function Room({
<p className={styles.roomTitle}>
{intl.formatMessage(
{
id: "booking.roomIndex",
defaultMessage: "Room {roomIndex}",
},
{
@@ -158,6 +160,7 @@ export default function Room({
wrapping={false}
>
{intl.formatMessage({
id: "booking.rateDetails",
defaultMessage: "Rate details",
})}
<MaterialIcon
@@ -196,6 +199,7 @@ export default function Room({
<p>
{intl.formatMessage(
{
id: "booking.numberOfCribs",
defaultMessage: "Crib (child) × {count}",
},
{ count: childBedCrib }
@@ -204,6 +208,7 @@ export default function Room({
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{intl.formatMessage({
id: "booking.subjectToAvailability",
defaultMessage: "Subject to availability",
})}
</p>
@@ -224,6 +229,7 @@ export default function Room({
<p>
{intl.formatMessage(
{
id: "booking.extraBedsCount",
defaultMessage: "Extra bed (child) × {count}",
},
{
@@ -234,6 +240,7 @@ export default function Room({
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>
{intl.formatMessage({
id: "booking.subjectToAvailability",
defaultMessage: "Subject to availability",
})}
</p>

View File

@@ -80,6 +80,7 @@ export function MobileSummary() {
<Typography variant="Body/Supporting text (caption)/smRegular">
<span className={styles.priceLabel}>
{intl.formatMessage({
id: "common.totalPrice",
defaultMessage: "Total price",
})}
</span>
@@ -117,6 +118,7 @@ export function MobileSummary() {
<span className={styles.seeDetails}>
<span>
{intl.formatMessage({
id: "booking.seeDetails",
defaultMessage: "See details",
})}
</span>
@@ -137,6 +139,7 @@ export function MobileSummary() {
isDisabled={selectedRates.state !== "ALL_SELECTED"}
>
{intl.formatMessage({
id: "common.continue",
defaultMessage: "Continue",
})}
</Button>

View File

@@ -53,9 +53,7 @@ export function SelectedRoomPanel({ roomIndex }: { roomIndex: number }) {
<div className={styles.content}>
<Caption color="uiTextHighContrast">
{intl.formatMessage(
{
defaultMessage: "Room {roomIndex}",
},
{ id: "booking.roomIndex", defaultMessage: "Room {roomIndex}" },
{ roomIndex: roomNr }
)}
</Caption>
@@ -90,6 +88,7 @@ export function SelectedRoomPanel({ roomIndex }: { roomIndex: number }) {
icon="edit_square"
/>
{intl.formatMessage({
id: "common.change",
defaultMessage: "Change",
})}
</Chip>
@@ -112,6 +111,7 @@ function useSelectedProductTitle({ roomIndex }: { roomIndex: number }) {
const selectedRate = selectedRates.forRoom(roomIndex)
const night = intl.formatMessage({
id: "common.night",
defaultMessage: "night",
})
@@ -171,18 +171,23 @@ function useSelectedProductTitle({ roomIndex }: { roomIndex: number }) {
function useRateTitle(rate: RateEnum | undefined) {
const intl = useIntl()
const freeCancelation = intl.formatMessage({
id: "booking.freeCancellation",
defaultMessage: "Free cancellation",
})
const nonRefundable = intl.formatMessage({
id: "booking.nonRefundable",
defaultMessage: "Non-refundable",
})
const freeBooking = intl.formatMessage({
id: "booking.freeRebooking",
defaultMessage: "Free rebooking",
})
const payLater = intl.formatMessage({
id: "booking.payLater",
defaultMessage: "Pay later",
})
const payNow = intl.formatMessage({
id: "booking.payNow",
defaultMessage: "Pay now",
})

Some files were not shown because too many files have changed in this diff Show More