fix(i18n): prepare for Lokalise

This commit is contained in:
Michael Zetterberg
2025-01-03 14:54:46 +01:00
parent cbc17e2c5b
commit d2ce9c0d7c
120 changed files with 1703 additions and 1042 deletions

View File

@@ -6,7 +6,6 @@ import BiroScript from "@/components/TempDesignSystem/Text/BiroScript"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import Title from "@/components/TempDesignSystem/Text/Title"
import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext"
import SectionWrapper from "../SectionWrapper"
@@ -35,9 +34,25 @@ export default async function LoyaltyLevels({
}
async function LevelCard({ level }: LevelCardProps) {
const lang = getLang()
const intl = await getIntl()
const pointsString = `${level.required_points.toLocaleString(lang)} ${intl.formatMessage({ id: "points" })} `
let pointsMsg: React.ReactNode = intl.formatMessage(
{ id: "{pointsAmount, number} points" },
{ pointsAmount: level.required_points }
)
if (level.required_nights) {
pointsMsg = intl.formatMessage<React.ReactNode>(
{
id: "{pointsAmount, number} points <highlight>or {nightsAmount, number} nights</highlight>",
},
{
pointsAmount: level.required_points,
nightsAmount: level.required_nights,
highlight: (str) => <span className={styles.redText}>{str}</span>,
}
)
}
return (
<article className={styles.card}>
@@ -47,18 +62,15 @@ async function LevelCard({ level }: LevelCardProps) {
color="primaryLightOnSurfaceAccent"
tilted="large"
>
{intl.formatMessage({ id: "Level" })} {level.user_facing_tag}
{intl.formatMessage(
{ id: "Level {level}" },
{ level: level.user_facing_tag }
)}
</BiroScript>
<MembershipLevelIcon level={level.level_id} color="red" />
</header>
<Title textAlign="center" level="h5">
{pointsString}
{level.required_nights ? (
<span className={styles.redText}>
{intl.formatMessage({ id: "or" })} {level.required_nights}{" "}
{intl.formatMessage({ id: "nights" })}
</span>
) : null}
{pointsMsg}
</Title>
<div className={styles.textContainer}>
{level.rewards.map((reward) => (

View File

@@ -19,14 +19,15 @@ export default async function MembershipNumber({
return (
<div className={classNames}>
<Caption color="pale">
{intl.formatMessage({ id: "Membership ID" })}
{": "}
{intl.formatMessage({ id: "Membership ID: " })}
</Caption>
<span className={styles.icon}>
<Caption className={styles.icon} color="pale" asChild>
<code>{membership?.membershipNumber ?? "N/A"}</code>
<code>
{membership?.membershipNumber ?? intl.formatMessage({ id: "N/A" })}
</code>
</Caption>
{membership && (
{membership?.membershipNumber && (
<CopyButton membershipNumber={membership.membershipNumber} />
)}
</span>

View File

@@ -24,15 +24,18 @@ export default async function Friend({
}
const isHighestLevel = isHighestMembership(membership.membershipLevel)
const lvlMessageHighest = intl.formatMessage({ id: "Highest level" })
const lvlMessageLevel = intl.formatMessage(
{ id: "Level {level}" },
{ level: membershipLevels[membership.membershipLevel] }
)
return (
<section className={styles.friend}>
<header className={styles.header}>
<Body color="white" textTransform="bold" textAlign="center">
{intl.formatMessage(
isHighestLevel
? { id: "Highest floor" }
: { id: `Level ${membershipLevels[membership.membershipLevel]}` }
)}
{isHighestLevel ? lvlMessageHighest : lvlMessageLevel}
</Body>
<MembershipLevelIcon
level={MembershipLevelEnum[membership.membershipLevel]}

View File

@@ -24,7 +24,7 @@ export default async function ExpiringPoints({ user }: UserProps) {
<section>
<Body color="white" textTransform="bold" textAlign="center">
{intl.formatMessage(
{ id: "spendable points expiring by" },
{ id: "{points} spendable points expiring by {date}" },
{
points: intl.formatNumber(membership.pointsToExpire),
date: d.format(dateFormat),

View File

@@ -1,7 +1,5 @@
import { useIntl } from "react-intl"
import useLang from "@/hooks/useLang"
import styles from "./levelSummary.module.css"
import type { LevelSummaryProps } from "@/types/components/overviewTable"
@@ -10,17 +8,29 @@ export default function LevelSummary({
level,
showDescription = true,
}: LevelSummaryProps) {
const lang = useLang()
const intl = useIntl()
let pointsMsg: React.ReactNode = intl.formatMessage(
{ id: "{pointsAmount, number} points" },
{ pointsAmount: level.required_points }
)
if (level.required_nights) {
pointsMsg = intl.formatMessage<React.ReactNode>(
{
id: "{pointsAmount, number} points or {nightsAmount, number} nights",
},
{
pointsAmount: level.required_points,
nightsAmount: level.required_nights,
highlight: (str) => <span className={styles.redText}>{str}</span>,
}
)
}
return (
<div className={styles.levelSummary}>
<span className={styles.levelRequirements}>
{level.required_points.toLocaleString(lang)}
{"p "}
{level.required_nights
? `${intl.formatMessage({ id: "or" })} ${level.required_nights} ${intl.formatMessage({ id: "nights" })}`
: ""}
</span>
<span className={styles.levelRequirements}>{pointsMsg}</span>
{showDescription && (
<p className={styles.levelSummaryText}>{level.description}</p>
)}

View File

@@ -22,12 +22,19 @@ export default function Row({ transaction }: RowProps) {
const pathName = usePathname()
const isWebview = webviews.includes(pathName)
const nightString = `${transaction.nights} ${transaction.nights === 1 ? intl.formatMessage({ id: "night" }) : intl.formatMessage({ id: "nights" })}`
const nightsMsg = intl.formatMessage(
{
id: "{nightsAmount, plural, one {# night} other {# nights}}",
},
{
nightsAmount: transaction.nights,
}
)
let description =
transaction.hotelName && transaction.city
? `${transaction.hotelName}, ${transaction.city} ${nightString}`
: `${nightString}`
? `${transaction.hotelName}, ${transaction.city} ${nightsMsg}`
: `${nightsMsg}`
switch (transaction.type) {
case Transactions.rewardType.stay:

View File

@@ -11,16 +11,16 @@ import styles from "./clientTable.module.css"
import type { ClientTableProps } from "@/types/components/myPages/myPage/earnAndBurn"
const tableHeadings = [
"Points",
"Description",
"Booking number",
"Arrival date",
]
export default function ClientTable({ transactions }: ClientTableProps) {
const intl = useIntl()
const tableHeadings = [
intl.formatMessage({ id: "Points" }),
intl.formatMessage({ id: "Description" }),
intl.formatMessage({ id: "Booking number" }),
intl.formatMessage({ id: "Arrival date" }),
]
return (
<div className={styles.container}>
<Table>
@@ -28,9 +28,7 @@ export default function ClientTable({ transactions }: ClientTableProps) {
<Table.TR>
{tableHeadings.map((heading) => (
<Table.TH key={heading}>
<Body textTransform="bold">
{intl.formatMessage({ id: heading })}
</Body>
<Body textTransform="bold">{heading}</Body>
</Table.TH>
))}
</Table.TR>

View File

@@ -10,8 +10,6 @@ import useLang from "@/hooks/useLang"
import AwardPoints from "../../EarnAndBurn/AwardPoints"
const tableHeadings = ["Points", "Expiration Date"]
export default function ExpiringPointsTable({
points,
expirationDate,
@@ -23,15 +21,18 @@ export default function ExpiringPointsTable({
const lang = useLang()
const expiration = dt(expirationDate).locale(lang).format("DD MMM YYYY")
const tableHeadings = [
intl.formatMessage({ id: "Points" }),
intl.formatMessage({ id: "Expiration Date" }),
]
return (
<Table>
<Table.THead>
<Table.TR>
{tableHeadings.map((heading) => (
<Table.TH key={heading}>
<Body textTransform="bold">
{intl.formatMessage({ id: heading })}
</Body>
<Body textTransform="bold">{heading}</Body>
</Table.TH>
))}
</Table.TR>

View File

@@ -52,7 +52,7 @@ export default async function NextLevelRewardsBlock({
<div className={styles.textContainer}>
<Body color="peach50" textAlign="center">
{intl.formatMessage(
{ id: "As our" },
{ id: "As our {level}" },
{ level: nextLevelRewards.level?.name }
)}
</Body>

View File

@@ -14,7 +14,10 @@ export default function MembershipNumberBadge({
return (
<div className={styles.rewardBadge}>
<Caption textAlign="center" color="uiTextHighContrast">
{intl.formatMessage({ id: "Membership ID" })}: {membershipNumber}
{intl.formatMessage(
{ id: "Membership ID: {id}" },
{ id: membershipNumber }
)}
</Caption>
</div>
)

View File

@@ -1,6 +1,7 @@
"use client"
import { useState } from "react"
import { useIntl } from "react-intl"
import { dt } from "@/lib/dt"
@@ -18,6 +19,7 @@ import type { StayCardProps } from "@/types/components/myPages/stays/stayCard"
export default function StayCard({ stay }: StayCardProps) {
const lang = useLang()
const intl = useIntl()
// TODO: Temporary loading. Remove when current web is deleted.
const [loading, setLoading] = useState(false)
@@ -55,7 +57,7 @@ export default function StayCard({ stay }: StayCardProps) {
<Caption asChild>
<time dateTime={arrivalDateTime}>{arrivalDate}</time>
</Caption>
{" - "}
{intl.formatMessage({ id: " - " })}
<Caption asChild>
<time dateTime={departDateTime}>{departDate}</time>
</Caption>