From e644d8873f8ec887a3fbbf39ec77ddd343c66745 Mon Sep 17 00:00:00 2001 From: "Aidar Shaikhutdin @makeweb.space" Date: Sat, 20 May 2023 07:01:54 +0600 Subject: [PATCH] feat: add translations integration --- src/components/App/index.tsx | 2 ++ src/components/App/styles.css | 5 ++- src/components/BirthdayPage/index.tsx | 6 ++-- src/components/BirthtimePage/index.tsx | 4 +-- src/components/CallToAction/index.tsx | 4 +-- src/components/Countdown/index.tsx | 2 +- src/components/CreateProfilePage/index.tsx | 8 ++--- src/components/DateTimePicker/DatePicker.tsx | 2 +- src/components/EmailEnterPage/index.tsx | 8 ++--- src/components/Footer/index.tsx | 19 ++++++++++ src/components/Footer/styles.css | 18 ++++++++++ src/components/Header/index.tsx | 2 +- src/components/NotFoundPage/index.tsx | 6 ++-- src/components/NotFoundPage/styles.css | 6 ++++ src/components/Payment/index.tsx | 4 +-- src/components/PaymentPage/index.tsx | 11 +++--- src/components/PaymentPage/styles.css | 9 ----- src/components/SubscriptionPage/index.tsx | 4 +-- src/init.tsx | 5 +-- src/locales/dev.ts | 38 ++++++++++++++++++++ src/locales/en.ts | 34 ------------------ src/locales/index.ts | 18 ++++++++-- 22 files changed, 133 insertions(+), 82 deletions(-) create mode 100644 src/components/Footer/index.tsx create mode 100644 src/components/Footer/styles.css create mode 100644 src/components/NotFoundPage/styles.css create mode 100644 src/locales/dev.ts delete mode 100644 src/locales/en.ts diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index afa7bd3..01e63ac 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -11,6 +11,7 @@ import WallpaperPage from '../WallpaperPage' import NotFoundPage from '../NotFoundPage' import Header from '../Header' import Navbar from '../Navbar' +import Footer from '../Footer' import routes, { hasNavigation } from '../../routes' import './styles.css' @@ -44,6 +45,7 @@ function Layout(): JSX.Element {
setIsMenuOpen(true)}/>
+
{ showNavbar ? setIsMenuOpen(false)} /> : null}
) diff --git a/src/components/App/styles.css b/src/components/App/styles.css index f8cdbb6..fc24bf9 100644 --- a/src/components/App/styles.css +++ b/src/components/App/styles.css @@ -8,11 +8,10 @@ } .content { - width: 100%; - height: 100vh; - position: relative; display: flex; flex-direction: column; + position: relative; + width: 100%; } .page { diff --git a/src/components/BirthdayPage/index.tsx b/src/components/BirthdayPage/index.tsx index ea77606..863b5d2 100644 --- a/src/components/BirthdayPage/index.tsx +++ b/src/components/BirthdayPage/index.tsx @@ -30,8 +30,8 @@ function BirthdayPage(): JSX.Element { return (
- {t('letsStart')} - {t('dateOfBirth')} + {t('lets_start')} + {t('date_of_birth')}
- {t('privacyText')} + {t('privacy_text')}
diff --git a/src/components/BirthtimePage/index.tsx b/src/components/BirthtimePage/index.tsx index 02e138d..cb27d3a 100644 --- a/src/components/BirthtimePage/index.tsx +++ b/src/components/BirthtimePage/index.tsx @@ -17,8 +17,8 @@ function BirthtimePage(): JSX.Element { const handleChange = (value: string) => dispatch(actions.form.addTime(value)) return (
- {t('bornTimeQuestion')} -

{t('nasaDataUsing')}

+ {t('born_time_question')} +

{t('nasa_data_using')}

{t('next')}
diff --git a/src/components/CallToAction/index.tsx b/src/components/CallToAction/index.tsx index ca62c94..13bd596 100644 --- a/src/components/CallToAction/index.tsx +++ b/src/components/CallToAction/index.tsx @@ -5,8 +5,8 @@ function CallToAction(): JSX.Element { const { t } = useTranslation() return (
-

{t('ctaTitle')}

-

{t('ctaSubtitle')}

+

{t('cta_title')}

+

{t('cta_subtitle')}

) } diff --git a/src/components/Countdown/index.tsx b/src/components/Countdown/index.tsx index 2e34313..ef8f8a7 100644 --- a/src/components/Countdown/index.tsx +++ b/src/components/Countdown/index.tsx @@ -23,7 +23,7 @@ function Countdown({ start }: CountdownProps): JSX.Element { return (
-

{t('reservedFor')}{formatTime(time)}

+

{t('reserved_for')}{formatTime(time)}

) } diff --git a/src/components/CreateProfilePage/index.tsx b/src/components/CreateProfilePage/index.tsx index 024b4eb..a2fc272 100644 --- a/src/components/CreateProfilePage/index.tsx +++ b/src/components/CreateProfilePage/index.tsx @@ -14,9 +14,9 @@ function CreateProfilePage(): JSX.Element { const navigate = useNavigate() const [progress, setProgress] = useState(0) const processItems = [ - { task: () => sleep(3300).then(() => setProgress(35)), label: t('zodiacAnalysis') }, - { task: () => sleep(2550).then(() => setProgress(61)), label: t('drawingWallpaper') }, - { task: () => sleep(3789).then(() => setProgress(98)), label: t('preparingResults') }, + { task: () => sleep(3300).then(() => setProgress(35)), label: t('zodiac_analysis') }, + { task: () => sleep(2550).then(() => setProgress(61)), label: t('drawing_wallpaper') }, + { task: () => sleep(3789).then(() => setProgress(98)), label: t('preparing_results') }, ] const handleDone = () => Promise.resolve() .then(() => setProgress(100)) @@ -25,7 +25,7 @@ function CreateProfilePage(): JSX.Element { return (
- {t('creatingProfile')} + {t('creating_profile')}
): JSX.Element { onChange={(day: string) => setDay(day)} />
- + ) } diff --git a/src/components/EmailEnterPage/index.tsx b/src/components/EmailEnterPage/index.tsx index 2ca9e6e..f61ff96 100644 --- a/src/components/EmailEnterPage/index.tsx +++ b/src/components/EmailEnterPage/index.tsx @@ -57,16 +57,16 @@ function EmailEnterPage(): JSX.Element { return (
- {t('weWillEmailYou')} + {t('we_will_email_you')} setIsDisabled(true)} /> -

{t('weDontShare')}

- {t('continueAgree')} +

{t('we_dont_share')}

+ {t('continue_agree')} {isLoading ? : t('continue')} diff --git a/src/components/Footer/index.tsx b/src/components/Footer/index.tsx new file mode 100644 index 0000000..cab13f0 --- /dev/null +++ b/src/components/Footer/index.tsx @@ -0,0 +1,19 @@ +import { useTranslation } from 'react-i18next' +import './styles.css' + +type FooterProps = { + color?: 'white' | 'black' +} + +function Footer({ color = 'white' }: FooterProps): JSX.Element { + const { t } = useTranslation() + const year = new Date().getFullYear() + const combinedClassNames = ['page-footer', `page-footer--${color}`].filter(Boolean).join(' ') + return ( +
+

© {year}, {t('company_name')}

+
+ ) +} + +export default Footer diff --git a/src/components/Footer/styles.css b/src/components/Footer/styles.css new file mode 100644 index 0000000..f83854c --- /dev/null +++ b/src/components/Footer/styles.css @@ -0,0 +1,18 @@ + +.page-footer { + font-size: 14px; + font-weight: 400; + line-height: 2; + padding: 10px 0; + color: #8e8e93; + text-align: center; +} + +.page-footer--white { + background-color: #fff; +} + +.page-footer--black { + background-color: #04040a; + color: #fff; +} diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 859bb26..aa1273d 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -41,7 +41,7 @@ function Header({ openMenu }: HeaderProps): JSX.Element {
{ showBackButton ? : null } logo - {t('appName')} + {t('app_name')} {showMenuButton ?
menu
: null} diff --git a/src/components/NotFoundPage/index.tsx b/src/components/NotFoundPage/index.tsx index e488e4d..f7b5629 100644 --- a/src/components/NotFoundPage/index.tsx +++ b/src/components/NotFoundPage/index.tsx @@ -3,10 +3,10 @@ import { useTranslation } from 'react-i18next' function NotFoundPage() { const { t } = useTranslation() return ( - <> +

{t('oops')}

-

{t('unexpectedError')}

- +

{t('unexpected_error')}

+
) } diff --git a/src/components/NotFoundPage/styles.css b/src/components/NotFoundPage/styles.css new file mode 100644 index 0000000..9fe9c93 --- /dev/null +++ b/src/components/NotFoundPage/styles.css @@ -0,0 +1,6 @@ +.not-found-page { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} \ No newline at end of file diff --git a/src/components/Payment/index.tsx b/src/components/Payment/index.tsx index 1d5c9a8..f1103f1 100644 --- a/src/components/Payment/index.tsx +++ b/src/components/Payment/index.tsx @@ -37,14 +37,14 @@ function Payment({ currency, locale, items }: PaymentProps): JSX.Element {
-
{t('totalToday')}
+
{t('total_today')}
{totalPrice.format()}
{items.map(toItem)}
-
{t('chargedOnly')}
+
{t('charged_only')}
) } diff --git a/src/components/PaymentPage/index.tsx b/src/components/PaymentPage/index.tsx index 15dea30..a57787e 100644 --- a/src/components/PaymentPage/index.tsx +++ b/src/components/PaymentPage/index.tsx @@ -24,7 +24,7 @@ const isApple = () => /Macintosh|iPhone|iPad|iPod/i.test(navigator.userAgent) function PaymentPage(): JSX.Element { const api = useApi() const { token } = useAuth() - const { i18n } = useTranslation() + const { t, i18n } = useTranslation() const locale = i18n.language const navigate = useNavigate() const email = useSelector(selectors.selectEmail) @@ -45,25 +45,22 @@ function PaymentPage(): JSX.Element { {isApple() && Guaranteed safe checkout} 100% Secure - Choose Payment Method + {t('choose_payment')} {isPending ? : ( <> {isAndroid() && Google Pay} {isApple() && Apple Pay} -
OR
+
{t('or').toUpperCase()}
Credit / Debit Card - Credit / Debit Card + {t('card')}

You will be charged only $1 for your 7-day trial. We'll email your a reminder before your trial period ends.

)}
-
-

© 20223, Wit LLC, California, US

-
) } diff --git a/src/components/PaymentPage/styles.css b/src/components/PaymentPage/styles.css index c0ad961..24d8567 100644 --- a/src/components/PaymentPage/styles.css +++ b/src/components/PaymentPage/styles.css @@ -37,12 +37,3 @@ line-height: 1.5; font-size: 15px; } - -.page-footer { - font-size: 14px; - font-weight: 400; - line-height: 2; - padding: 10px 0; - color: #8e8e93; - text-align: center; -} diff --git a/src/components/SubscriptionPage/index.tsx b/src/components/SubscriptionPage/index.tsx index 08f6ac9..3c9d706 100644 --- a/src/components/SubscriptionPage/index.tsx +++ b/src/components/SubscriptionPage/index.tsx @@ -34,8 +34,8 @@ function SubscriptionPage(): JSX.Element { - {t('getAccess')} - {t('subscriptionPolicy')} + {t('get_access')} + {t('subscription_policy')}
) diff --git a/src/init.tsx b/src/init.tsx index ecb745f..fd86e0e 100644 --- a/src/init.tsx +++ b/src/init.tsx @@ -6,14 +6,15 @@ import { Provider } from 'react-redux' import { store } from './store' import { AuthProvider } from './auth' import { ApiContext, createApi } from './api' -import resources, { getClientLocale } from './locales' +import { getClientLocale, buildResources, fallbackLng } from './locales' import App from './components/App' const init = async () => { const api = createApi() const lng = getClientLocale() + const resources = await api.getElements({ locale: lng }).then(buildResources) const i18nextInstance = i18next.createInstance() - const options = { lng, resources } + const options = { lng, resources, fallbackLng } await i18nextInstance.use(initReactI18next).init(options) return ( diff --git a/src/locales/dev.ts b/src/locales/dev.ts new file mode 100644 index 0000000..970c01a --- /dev/null +++ b/src/locales/dev.ts @@ -0,0 +1,38 @@ +export default { + translation: { + lets_start: "Let's start!", + next: "Next", + date_of_birth: "What's your date of birth?", + privacy_text: "By continuing, you agree to our EULA and Privacy Notice. Have a question? Reach our support team here", + born_time_question: "What time were you born?", + nasa_data_using: "We use NASA data to determine the exact position of the planets in the sky at the time of your birth to create wallpapers that are just right for you.", + cta_title: "Start your 7-day trial", + cta_subtitle: "No pressure. Cancel anytime.", + reserved_for: "Reserved for ", + creating_profile: "Creating your profile", + zodiac_analysis: "Zodiac data analysis", + drawing_wallpaper: "Drawing Wallpapers", + preparing_results: "Preparing results", + invalid_date: "Date not found. Please check your details and try again.", + year: "Year", + month: "Month", + day: "Day", + we_will_email_you: "We will email you a copy of your wallpaper for easy access.", + your_email: "Your email", + we_dont_share: "We don't share any personal information.", + continue_agree: 'By clicking "Continue" below, you agree to our EULA and Privacy Policy.', + continue: 'Continue', + app_name: "Aura", + unexpected_error: 'Sorry, an unexpected error has occurred.', + oops: "Oops!", + total_today: 'Total today', + charged_only: "You will be charged only $1 for your 7-day trial. We'll email you a reminder before your trial period ends. Cancel anytime.", + purposes: 'For entertaiment purposes only.', + get_access: 'Get access', + subscription_policy: 'By proceeding, you agree that if you do not cancel your subscription before the end of the 7-day trial period, you will be automatically charged nineteen US dollars zero cents every 2 weeks until you cancel the subscription in the settings. Learn more about cancellation and refund policy in Subscription policy', + company_name: 'Wit LLC, California, US', + choose_payment: 'Choose Payment Method', + or: 'OR', + card: 'Credit / Debit Card', + }, +} diff --git a/src/locales/en.ts b/src/locales/en.ts deleted file mode 100644 index dd7a3ed..0000000 --- a/src/locales/en.ts +++ /dev/null @@ -1,34 +0,0 @@ -export default { - translation: { - letsStart: "Let's start!", - next: "Next", - dateOfBirth: "What's your date of birth?", - privacyText: "By continuing, you agree to our EULA and Privacy Notice. Have a question? Reach our support team here", - bornTimeQuestion: "What time were you born?", - nasaDataUsing: "We use NASA data to determine the exact position of the planets in the sky at the time of your birth to create wallpapers that are just right for you.", - ctaTitle: "Start your 7-day trial", - ctaSubtitle: "No pressure. Cancel anytime.", - reservedFor: "Reserved for ", - creatingProfile: "Creating your profile", - zodiacAnalysis: "Zodiac data analysis", - drawingWallpaper: "Drawing Wallpapers", - preparingResults: "Preparing results", - invalidDate: "Date not found. Please check your details and try again.", - year: "Year", - month: "Month", - day: "Day", - weWillEmailYou: "We will email you a copy of your wallpaper for easy access.", - yourEmail: "Your email", - weDontShare: "We don't share any personal information.", - continueAgree: 'By clicking "Continue" below, you agree to our EULA and Privacy Policy.', - continue: 'Continue', - appName: "Aura", - unexpectedError: 'Sorry, an unexpected error has occurred.', - oops: "Oops!", - totalToday: 'Total today', - chargedOnly: "You will be charged only $1 for your 7-day trial. We'll email you a reminder before your trial period ends. Cancel anytime.", - purposes: 'For entertaiment purposes only.', - getAccess: 'Get access', - subscriptionPolicy: 'By proceeding, you agree that if you do not cancel your subscription before the end of the 7-day trial period, you will be automatically charged nineteen US dollars zero cents every 2 weeks until you cancel the subscription in the settings. Learn more about cancellation and refund policy in Subscription policy', - }, -} diff --git a/src/locales/index.ts b/src/locales/index.ts index ce7be91..e037fb7 100644 --- a/src/locales/index.ts +++ b/src/locales/index.ts @@ -1,6 +1,20 @@ -import en from './en.ts' +import { Elements } from '../api' +import dev from './dev.ts' export const getClientLocale = () => navigator.language.split('-')[0] export const getClientTimezone = () => Intl.DateTimeFormat().resolvedOptions().timeZone +export const fallbackLng = 'dev' -export default { en } +const omitKeys = ['href', 'title', 'url_slug', 'type'] +const isWeb = (group: Elements.ElementGroup) => group.name === 'web' +const cleanUp = (element: Partial = {}) => { + return Object.entries(element) + .filter(([key]) => !omitKeys.includes(key)) + .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}) +} +export const buildResources = (resp: Elements.Response) => { + const element = resp.data.groups.find(isWeb)?.items.at(0) + const translation = cleanUp(element) + const lng = getClientLocale() + return { [lng]: { translation }, dev } +}