From 7d8828a358d653bb162877a64c75028eb82678cd Mon Sep 17 00:00:00 2001 From: Amruth Pillai Date: Fri, 11 Mar 2022 08:43:20 +0100 Subject: [PATCH] fix(i18n): add missing translation keys, update lang/locale logic --- .vscode/settings.json | 24 +++++++++++++------ .../build/Center/ArtboardController.tsx | 16 ++++++------- client/components/build/Center/Header.tsx | 4 ++-- .../LeftSidebar/sections/PhotoFilters.tsx | 4 ++-- .../LeftSidebar/sections/PhotoUpload.tsx | 4 ++-- .../LeftSidebar/sections/SectionSettings.tsx | 2 +- .../build/RightSidebar/sections/Layout.tsx | 4 ++-- .../build/RightSidebar/sections/Settings.tsx | 17 ++++++------- .../build/RightSidebar/sections/Sharing.tsx | 2 +- client/components/dashboard/ResumePreview.tsx | 4 ++-- client/components/shared/ColorAvatar.tsx | 2 +- client/components/shared/Heading.tsx | 6 ++--- client/components/shared/LanguageSwitcher.tsx | 11 +++------ client/components/shared/ListItem.tsx | 15 ++++++------ client/constants/index.ts | 3 +++ client/modals/builder/sections/AwardModal.tsx | 6 ++--- .../builder/sections/CertificateModal.tsx | 6 ++--- .../modals/builder/sections/CustomModal.tsx | 6 ++--- .../builder/sections/EducationModal.tsx | 6 ++--- .../modals/builder/sections/ProfileModal.tsx | 9 ++++--- .../modals/builder/sections/ProjectModal.tsx | 6 ++--- .../builder/sections/PublicationModal.tsx | 6 ++--- .../builder/sections/VolunteerModal.tsx | 6 ++--- client/modals/builder/sections/WorkModal.tsx | 6 ++--- client/modals/dashboard/CreateResumeModal.tsx | 2 +- .../modals/dashboard/ImportExternalModal.tsx | 4 ++-- client/public/locales/en/builder.json | 10 ++++++-- client/public/locales/en/common.json | 4 +++- client/public/locales/en/modals.json | 2 +- client/public/locales/kn/common.json | 1 - client/public/locales/kn/modals.json | 10 ++++---- client/public/locales/ta/common.json | 1 - client/store/build/buildSlice.ts | 13 +--------- client/utils/getCookie.ts | 8 +++++++ client/wrappers/DateWrapper.tsx | 7 +++++- 35 files changed, 124 insertions(+), 113 deletions(-) create mode 100644 client/utils/getCookie.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 27015764..d793699d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,15 +1,25 @@ { "css.validate": false, - "scss.validate": false, "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, "editor.wordWrap": "on", - "eslint.workingDirectories": ["schema", "client", "server"], - "i18n-ally.enabledFrameworks": ["i18next"], - "i18n-ally.localesPaths": ["client/public/locales"], - "i18n-ally.sourceLanguage": "en", - "i18n-ally.keystyle": "nested" -} + "eslint.workingDirectories": [ + "schema", + "client", + "server" + ], + "i18n-ally.enabledFrameworks": [ + "react" + ], + "i18n-ally.keystyle": "nested", + "i18n-ally.localesPaths": [ + "client/public/locales" + ], + "i18n-ally.namespace": true, + "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}", + "i18n-ally.sortKeys": true, + "scss.validate": false +} \ No newline at end of file diff --git a/client/components/build/Center/ArtboardController.tsx b/client/components/build/Center/ArtboardController.tsx index f16a3b0b..b6020b3d 100644 --- a/client/components/build/Center/ArtboardController.tsx +++ b/client/components/build/Center/ArtboardController.tsx @@ -74,19 +74,19 @@ const ArtboardController: React.FC = ({ zoomIn, zoomOut, c })} >
- ('builder.controller.tooltip.zoom-in')}> + zoomIn(0.25)}> - ('builder.controller.tooltip.zoom-out')}> + zoomOut(0.25)}> - ('builder.controller.tooltip.center-artboard')}> + centerView(0.95)}> @@ -96,7 +96,7 @@ const ArtboardController: React.FC = ({ zoomIn, zoomOut, c {isDesktop && ( <> - ('builder.controller.tooltip.toggle-orientation')}> + {orientation === 'vertical' ? ( @@ -106,13 +106,13 @@ const ArtboardController: React.FC = ({ zoomIn, zoomOut, c - ('builder.controller.tooltip.toggle-page-break-line')}> + - ('builder.controller.tooltip.toggle-sidebars')}> + @@ -122,13 +122,13 @@ const ArtboardController: React.FC = ({ zoomIn, zoomOut, c )} - ('builder.controller.tooltip.copy-link')}> + - ('builder.controller.tooltip.export-pdf')}> + diff --git a/client/components/build/Center/Header.tsx b/client/components/build/Center/Header.tsx index fa4b6850..8299800b 100644 --- a/client/components/build/Center/Header.tsx +++ b/client/components/build/Center/Header.tsx @@ -184,7 +184,7 @@ const Header = () => { {t('builder.header.menu.share-link')} ) : ( - ('builder.header.menu.tooltips.share-link')}> +
@@ -196,7 +196,7 @@ const Header = () => { )} - ('builder.header.menu.tooltips.delete')}> + diff --git a/client/components/build/LeftSidebar/sections/PhotoFilters.tsx b/client/components/build/LeftSidebar/sections/PhotoFilters.tsx index c118c030..99692c6b 100644 --- a/client/components/build/LeftSidebar/sections/PhotoFilters.tsx +++ b/client/components/build/LeftSidebar/sections/PhotoFilters.tsx @@ -58,14 +58,14 @@ const PhotoFilters = () => {
('builder.leftSidebar.sections.basics.photo-filters.effects.grayscale.label')} + label={t('builder.leftSidebar.sections.basics.photo-filters.effects.grayscale.label') as string} control={ handleSetGrayscale(value)} /> } /> ('builder.leftSidebar.sections.basics.photo-filters.effects.border.label')} + label={t('builder.leftSidebar.sections.basics.photo-filters.effects.border.label') as string} control={ handleSetBorder(value)} />} />
diff --git a/client/components/build/LeftSidebar/sections/PhotoUpload.tsx b/client/components/build/LeftSidebar/sections/PhotoUpload.tsx index c5f7f816..52b3e268 100644 --- a/client/components/build/LeftSidebar/sections/PhotoUpload.tsx +++ b/client/components/build/LeftSidebar/sections/PhotoUpload.tsx @@ -67,8 +67,8 @@ const PhotoUpload: React.FC = () => { ('builder.leftSidebar.sections.basics.photo-upload.tooltip.upload') - : t('builder.leftSidebar.sections.basics.photo-upload.tooltip.remove') + ? (t('builder.leftSidebar.sections.basics.photo-upload.tooltip.upload') as string) + : (t('builder.leftSidebar.sections.basics.photo-upload.tooltip.remove') as string) } > diff --git a/client/components/build/LeftSidebar/sections/SectionSettings.tsx b/client/components/build/LeftSidebar/sections/SectionSettings.tsx index da50db34..813b5a17 100644 --- a/client/components/build/LeftSidebar/sections/SectionSettings.tsx +++ b/client/components/build/LeftSidebar/sections/SectionSettings.tsx @@ -32,7 +32,7 @@ const SectionSettings: React.FC = ({ path }) => { return (
- ('builder.common.columns.tooltip')}> + {columns} diff --git a/client/components/build/RightSidebar/sections/Layout.tsx b/client/components/build/RightSidebar/sections/Layout.tsx index 4ba4fb97..dd172b79 100644 --- a/client/components/build/RightSidebar/sections/Layout.tsx +++ b/client/components/build/RightSidebar/sections/Layout.tsx @@ -62,7 +62,7 @@ const Layout = () => { path="metadata.layout" name={t('builder.rightSidebar.sections.layout.heading')} action={ - ('builder.rightSidebar.sections.layout.tooltip.reset-layout')}> + @@ -81,7 +81,7 @@ const Layout = () => {
('builder.common.actions.delete', { token: t('builder.common.glossary.page') })} + title={t('builder.common.actions.delete', { token: t('builder.common.glossary.page') }) as string} > handleDeletePage(pageIndex)}> diff --git a/client/components/build/RightSidebar/sections/Settings.tsx b/client/components/build/RightSidebar/sections/Settings.tsx index 9d59cdf3..11362f02 100644 --- a/client/components/build/RightSidebar/sections/Settings.tsx +++ b/client/components/build/RightSidebar/sections/Settings.tsx @@ -20,25 +20,24 @@ import { useMutation } from 'react-query'; import Heading from '@/components/shared/Heading'; import ThemeSwitch from '@/components/shared/ThemeSwitch'; -import { Language, languages } from '@/config/languages'; +import { Language, languageMap, languages } from '@/config/languages'; import { ServerError } from '@/services/axios'; import queryClient from '@/services/react-query'; import { loadSampleData, LoadSampleDataParams, resetResume, ResetResumeParams } from '@/services/resume'; -import { setLanguage, setTheme, togglePageBreakLine, togglePageOrientation } from '@/store/build/buildSlice'; +import { setTheme, togglePageBreakLine, togglePageOrientation } from '@/store/build/buildSlice'; import { useAppDispatch, useAppSelector } from '@/store/hooks'; import { setResumeState } from '@/store/resume/resumeSlice'; import { dateFormatOptions } from '@/utils/date'; const Settings = () => { - const router = useRouter(); - const { t } = useTranslation(); const dispatch = useAppDispatch(); + const { locale, ...router } = useRouter(); + const resume = useAppSelector((state) => state.resume); const theme = useAppSelector((state) => state.build.theme); - const language = useAppSelector((state) => state.build.language); const breakLine = useAppSelector((state) => state.build.page.breakLine); const orientation = useAppSelector((state) => state.build.page.orientation); @@ -62,14 +61,12 @@ const Settings = () => { dispatch(setResumeState({ path: 'metadata.date.format', value })); const handleChangeLanguage = (value: Language | null) => { - const { pathname, asPath, query } = router; + const { pathname, asPath, query, push } = router; const code = value?.code || 'en'; - dayjs.locale(code); - dispatch(setLanguage({ language: code })); document.cookie = `NEXT_LOCALE=${code}; path=/; expires=2147483647`; - router.push({ pathname, query }, asPath, { locale: code }); + push({ pathname, query }, asPath, { locale: code }); }; const handleLoadSampleData = async () => { @@ -132,7 +129,7 @@ const Settings = () => { disableClearable className="my-2 w-full" options={languages} - value={language} + value={languageMap[locale ?? 'en']} isOptionEqualToValue={(a, b) => a.code === b.code} onChange={(_, value) => handleChangeLanguage(value)} renderInput={(params) => } diff --git a/client/components/build/RightSidebar/sections/Sharing.tsx b/client/components/build/RightSidebar/sections/Sharing.tsx index 18135718..e4e1d840 100644 --- a/client/components/build/RightSidebar/sections/Sharing.tsx +++ b/client/components/build/RightSidebar/sections/Sharing.tsx @@ -63,7 +63,7 @@ const Sharing = () => {
('builder.rightSidebar.sections.sharing.short-url.label')} + label={t('builder.rightSidebar.sections.sharing.short-url.label') as string} control={ setShowShortUrl(value)} /> } diff --git a/client/components/dashboard/ResumePreview.tsx b/client/components/dashboard/ResumePreview.tsx index e5c5be8f..994a9e06 100644 --- a/client/components/dashboard/ResumePreview.tsx +++ b/client/components/dashboard/ResumePreview.tsx @@ -161,7 +161,7 @@ const ResumePreview: React.FC = ({ resume }) => { {t('dashboard.resume.menu.share-link')} ) : ( - ('dashboard.resume.menu.tooltips.share-link')}> +
@@ -173,7 +173,7 @@ const ResumePreview: React.FC = ({ resume }) => { )} - ('dashboard.resume.menu.tooltips.delete')}> + diff --git a/client/components/shared/ColorAvatar.tsx b/client/components/shared/ColorAvatar.tsx index 9782a0a4..f2d2e28b 100644 --- a/client/components/shared/ColorAvatar.tsx +++ b/client/components/shared/ColorAvatar.tsx @@ -12,7 +12,7 @@ const ColorAvatar: React.FC = ({ color, size = 20, onClick }) => { return ( - +   ); }; diff --git a/client/components/shared/Heading.tsx b/client/components/shared/Heading.tsx index 7c9db164..311f4cfa 100644 --- a/client/components/shared/Heading.tsx +++ b/client/components/shared/Heading.tsx @@ -72,19 +72,19 @@ const Heading: React.FC = ({ })} > {isEditable && ( - ('builder.common.tooltip.rename-section')}> + {editMode ? : } )} {isHideable && ( - ('builder.common.tooltip.toggle-visibility')}> + {visibility ? : } )} {isDeletable && ( - ('builder.common.tooltip.delete-section')}> + diff --git a/client/components/shared/LanguageSwitcher.tsx b/client/components/shared/LanguageSwitcher.tsx index 711832b6..012c0307 100644 --- a/client/components/shared/LanguageSwitcher.tsx +++ b/client/components/shared/LanguageSwitcher.tsx @@ -1,19 +1,17 @@ import { Language } from '@mui/icons-material'; import { IconButton, Popover } from '@mui/material'; -import dayjs from 'dayjs'; import { useRouter } from 'next/router'; +import { useTranslation } from 'next-i18next'; import { MouseEvent, useState } from 'react'; import { languages } from '@/config/languages'; -import { setLanguage } from '@/store/build/buildSlice'; -import { useAppDispatch } from '@/store/hooks'; import styles from './LanguageSwitcher.module.scss'; const LanguageSwitcher = () => { const router = useRouter(); - const dispatch = useAppDispatch(); + const { t } = useTranslation(); const [anchorEl, setAnchorEl] = useState(null); @@ -24,10 +22,7 @@ const LanguageSwitcher = () => { const handleChangeLanguage = (locale: string) => { const { pathname, asPath, query } = router; - dayjs.locale(locale); - dispatch(setLanguage({ language: locale })); document.cookie = `NEXT_LOCALE=${locale}; path=/; expires=2147483647`; - router.push({ pathname, query }, asPath, { locale }); }; @@ -59,7 +54,7 @@ const LanguageSwitcher = () => { ))} - Missing your language? + {t('common.footer.language.missing')}
diff --git a/client/components/shared/ListItem.tsx b/client/components/shared/ListItem.tsx index e3a7ee4b..6e8167c7 100644 --- a/client/components/shared/ListItem.tsx +++ b/client/components/shared/ListItem.tsx @@ -3,6 +3,7 @@ import { Divider, IconButton, ListItemIcon, ListItemText, Menu, MenuItem, Toolti import { ListItem as ListItemType } from '@reactive-resume/schema'; import clsx from 'clsx'; import isFunction from 'lodash/isFunction'; +import { useTranslation } from 'next-i18next'; import React, { useRef, useState } from 'react'; import { DropTargetMonitor, useDrag, useDrop, XYCoord } from 'react-dnd'; @@ -26,6 +27,8 @@ type Props = { }; const ListItem: React.FC = ({ item, index, title, subtitle, onMove, onEdit, onDelete, onDuplicate }) => { + const { t } = useTranslation(); + const ref = useRef(null); const [anchorEl, setAnchorEl] = useState(null); @@ -122,29 +125,25 @@ const ListItem: React.FC = ({ item, index, title, subtitle, onMove, onEdi - Edit + {t('builder.common.list.actions.edit')} handleDuplicate(item)}> - Duplicate + {t('builder.common.list.actions.duplicate')} - +
handleDelete(item)}> - Delete + {t('builder.common.list.actions.delete')}
diff --git a/client/constants/index.ts b/client/constants/index.ts index d9b9c768..94a9a709 100644 --- a/client/constants/index.ts +++ b/client/constants/index.ts @@ -2,6 +2,9 @@ export const FONTS_QUERY = 'fonts'; export const RESUMES_QUERY = 'resumes'; +// Regular Expressions +export const VALID_URL_REGEX = /[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/; + // Date Formats export const FILENAME_TIMESTAMP = 'DDMMYYYYHHmmss'; diff --git a/client/modals/builder/sections/AwardModal.tsx b/client/modals/builder/sections/AwardModal.tsx index 87b7500d..111b0fa3 100644 --- a/client/modals/builder/sections/AwardModal.tsx +++ b/client/modals/builder/sections/AwardModal.tsx @@ -13,6 +13,7 @@ import { Controller, useForm } from 'react-hook-form'; import BaseModal from '@/components/shared/BaseModal'; import MarkdownSupported from '@/components/shared/MarkdownSupported'; +import { VALID_URL_REGEX } from '@/constants/index'; import { useAppDispatch, useAppSelector } from '@/store/hooks'; import { setModalState } from '@/store/modal/modalSlice'; import { addItem, editItem } from '@/store/resume/resumeSlice'; @@ -34,9 +35,7 @@ const schema = Joi.object().keys({ title: Joi.string().required(), awarder: Joi.string().required(), date: Joi.string().allow(''), - url: Joi.string() - .pattern(/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/, { name: 'valid URL' }) - .allow(''), + url: Joi.string().pattern(VALID_URL_REGEX, { name: 'valid URL' }).allow(''), summary: Joi.string().allow(''), }); @@ -154,6 +153,7 @@ const AwardModal: React.FC = () => { render={({ field, fieldState }) => ( ().keys({ name: Joi.string().required(), issuer: Joi.string().required(), date: Joi.string().allow(''), - url: Joi.string() - .pattern(/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/, { name: 'valid URL' }) - .allow(''), + url: Joi.string().pattern(VALID_URL_REGEX, { name: 'valid URL' }).allow(''), summary: Joi.string().allow(''), }); @@ -154,6 +153,7 @@ const CertificateModal: React.FC = () => { render={({ field, fieldState }) => ( ().keys({ start: Joi.string().allow(''), end: Joi.string().allow(''), }), - url: Joi.string() - .pattern(/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/, { name: 'valid URL' }) - .allow(''), + url: Joi.string().pattern(VALID_URL_REGEX, { name: 'valid URL' }).allow(''), level: Joi.string().allow(''), levelNum: Joi.number().min(0).max(10), summary: Joi.string().allow(''), @@ -194,6 +193,7 @@ const CustomModal: React.FC = () => { render={({ field, fieldState }) => ( ().keys({ start: Joi.string().allow(''), end: Joi.string().allow(''), }), - url: Joi.string() - .pattern(/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/, { name: 'valid URL' }) - .allow(''), + url: Joi.string().pattern(VALID_URL_REGEX, { name: 'valid URL' }).allow(''), summary: Joi.string().allow(''), courses: Joi.array().items(Joi.string().optional()), }); @@ -217,6 +216,7 @@ const EducationModal: React.FC = () => { render={({ field, fieldState }) => ( ({ id: Joi.string(), network: Joi.string().required(), username: Joi.string().required(), - url: Joi.string() - .pattern(/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/, { name: 'valid URL' }) - .default('https://') - .allow(''), + url: Joi.string().pattern(VALID_URL_REGEX, { name: 'valid URL' }).allow(''), }); const ProfileModal: React.FC = () => { @@ -131,6 +129,7 @@ const ProfileModal: React.FC = () => { ().keys({ start: Joi.string().allow(''), end: Joi.string().allow(''), }), - url: Joi.string() - .pattern(/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/, { name: 'valid URL' }) - .allow(''), + url: Joi.string().pattern(VALID_URL_REGEX, { name: 'valid URL' }).allow(''), summary: Joi.string().allow(''), keywords: Joi.array().items(Joi.string().optional()), }); @@ -187,6 +186,7 @@ const ProjectModal: React.FC = () => { render={({ field, fieldState }) => ( ().keys({ name: Joi.string().required(), publisher: Joi.string().required(), date: Joi.string().allow(''), - url: Joi.string() - .pattern(/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/, { name: 'valid URL' }) - .allow(''), + url: Joi.string().pattern(VALID_URL_REGEX, { name: 'valid URL' }).allow(''), summary: Joi.string().allow(''), }); @@ -154,6 +153,7 @@ const PublicationModal: React.FC = () => { render={({ field, fieldState }) => ( ().keys({ start: Joi.string().allow(''), end: Joi.string().allow(''), }), - url: Joi.string() - .pattern(/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/, { name: 'valid URL' }) - .allow(''), + url: Joi.string().pattern(VALID_URL_REGEX, { name: 'valid URL' }).allow(''), summary: Joi.string().allow(''), }); @@ -184,6 +183,7 @@ const VolunteerModal: React.FC = () => { render={({ field, fieldState }) => ( ().keys({ start: Joi.string().allow(''), end: Joi.string().allow(''), }), - url: Joi.string() - .pattern(/[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/, { name: 'valid URL' }) - .allow(''), + url: Joi.string().pattern(VALID_URL_REGEX, { name: 'valid URL' }).allow(''), summary: Joi.string().allow(''), }); @@ -184,6 +183,7 @@ const WorkModal: React.FC = () => { render={({ field, fieldState }) => ( { ('modals.dashboard.create-resume.form.public.label')} + label={t('modals.dashboard.create-resume.form.public.label') as string} control={ {

You can save time by exporting your data from LinkedIn and using it to auto-fill fields on Reactive Resume. - Head on over to the + Head over to the { > Data Privacy - section on LinkedIn and request an archive of your data. Once it is available, upload the ZIP archive below. + section on LinkedIn and request an archive of your data. Once it is available, upload the ZIP file below.

diff --git a/client/public/locales/en/builder.json b/client/public/locales/en/builder.json index 6dc884cb..e379acfa 100644 --- a/client/public/locales/en/builder.json +++ b/client/public/locales/en/builder.json @@ -61,12 +61,18 @@ "page": "Page" }, "list": { - "empty-text": "This list is empty." + "empty-text": "This list is empty.", + "actions": { + "edit": "Edit", + "duplicate": "Duplicate", + "delete": "Delete" + } }, "tooltip": { "delete-section": "Delete Section", "rename-section": "Rename Section", - "toggle-visibility": "Toggle Visibility" + "toggle-visibility": "Toggle Visibility", + "delete-item": "Are you sure you want to delete this item? This is an irreversible action." } }, "controller": { diff --git a/client/public/locales/en/common.json b/client/public/locales/en/common.json index fe911ca0..ce92c58f 100644 --- a/client/public/locales/en/common.json +++ b/client/public/locales/en/common.json @@ -5,9 +5,11 @@ "logout": "Logout" } }, - "description": "Reactive Resume is a free and open source resume builder that's built to make the mundane tasks of creating, updating and sharing your resume as easy as 1, 2, 3.", "footer": { "credit": "A passion project by <1>Amruth Pillai", + "language": { + "missing": "Missing your language?" + }, "license": "By the community, for the community." }, "markdown": { diff --git a/client/public/locales/en/modals.json b/client/public/locales/en/modals.json index 7b2c9424..129302fd 100644 --- a/client/public/locales/en/modals.json +++ b/client/public/locales/en/modals.json @@ -106,7 +106,7 @@ "actions": { "upload-archive": "Upload ZIP Archive" }, - "body": "You can save time by exporting your data from LinkedIn and using it to auto-fill fields on Reactive Resume. Head on over to the <1>Data Privacy section on LinkedIn and request an archive of your data. Once it is available, upload the ZIP archive below.", + "body": "You can save time by exporting your data from LinkedIn and using it to auto-fill fields on Reactive Resume. Head over to the <1>Data Privacy section on LinkedIn and request an archive of your data. Once it is available, upload the ZIP file below.", "heading": "Import From LinkedIn" }, "reactive-resume": { diff --git a/client/public/locales/kn/common.json b/client/public/locales/kn/common.json index a8211f8b..da21e650 100644 --- a/client/public/locales/kn/common.json +++ b/client/public/locales/kn/common.json @@ -5,7 +5,6 @@ "logout": "ಲಾಗ್ ಔಟ್" } }, - "description": "ಪ್ರತಿಕ್ರಿಯಾತ್ಮಕ ರೇಸುಮೆವು ಉಚಿತ ಮತ್ತು ಮುಕ್ತ ಮೂಲ ರೇಸುಮೆ ಬಿಲ್ಡರ್ ಆಗಿದ್ದು, ನಿಮ್ಮ ರೇಸುಮೆ ಅನ್ನು 1, 2, 3 ರಂತೆ ಸುಲಭವಾಗಿ ರಚಿಸುವ, ನವೀಕರಿಸುವ ಮತ್ತು ಹಂಚಿಕೊಳ್ಳುವ ಪ್ರಾಪಂಚಿಕ ಕಾರ್ಯಗಳನ್ನು ಮಾಡಲು ನಿರ್ಮಿಸಲಾಗಿದೆ.", "footer": { "credit": "<1>ಅಮೃತ್ ಪಿಳ್ಳೈ ಅವರು ಉತ್ಸಾಹದಿಂದ ಮಾಡಿರುವ ಪ್ರಾಜೆಕ್ಟ್", "license": "ಸಮುದಾಯದಿಂದ, ಸಮುದಾಯಕ್ಕಾಗಿ." diff --git a/client/public/locales/kn/modals.json b/client/public/locales/kn/modals.json index 820e43e2..8ce54b30 100644 --- a/client/public/locales/kn/modals.json +++ b/client/public/locales/kn/modals.json @@ -11,7 +11,7 @@ } }, "heading": "ನಿಮ್ಮ ಪಾಸ್ವರ್ಡ್ ಮರೆತಿರುವಿರಾ?", - "help-text": "%1 ರ ಜೊತೆ ಜೋಡಣೆಯಾಗಿರುವ ಖಾತೆ ಇದ್ದಲ್ಲಿ, ನೀವು ನಿಮ್ಮ ಗುಪ್ತಪದ ಮರುಹೊಂದಿಕೆ ಕೊಂಡಿಯನ್ನು ಹೊಂದಿರುವ ಮಿಂಚೆಯನ್ನು ಪಡೆಯುವಿರಿ." + "help-text": "ಖಾತೆಯು ಅಸ್ತಿತ್ವದಲ್ಲಿದ್ದರೆ, ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರುಹೊಂದಿಸಲು ಲಿಂಕ್‌ನೊಂದಿಗೆ ಇಮೇಲ್ ಅನ್ನು ನೀವು ಸ್ವೀಕರಿಸುತ್ತೀರಿ." }, "login": { "actions": { @@ -104,16 +104,16 @@ }, "linkedin": { "actions": { - "upload-archive": "ಜಿಪ್ (ZIP) ಆರ್ಕೈವ್ ಅನ್ನು ಅಪ್‌ಲೋಡ್ ಮಾಡಿ" + "upload-archive": "ಜಿಪ್ ಆರ್ಕೈವ್ ಅನ್ನು ಅಪ್‌ಲೋಡ್ ಮಾಡಿ" }, - "body": "ಲಿಂಕ್ಡ್‌ಇನ್‌ನಿಂದ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ರಫ್ತು ಮಾಡುವ ಮೂಲಕ ಮತ್ತು ರಿಯಾಕ್ಟಿವ್ ರೆಸ್ಯೂಮ್‌ನಲ್ಲಿ ಕ್ಷೇತ್ರಗಳನ್ನು ಸ್ವಯಂ ತುಂಬಲು ಅದನ್ನು ಬಳಸುವ ಮೂಲಕ ನೀವು ಸಮಯವನ್ನು ಉಳಿಸಬಹುದು. <1>ಡೇಟಾ ಗೌಪ್ಯತೆಗೆ ಹೋಗಿ ಲಿಂಕ್ಡ್‌ಇನ್‌ನಲ್ಲಿ ವಿಭಾಗ ಮತ್ತು ನಿಮ್ಮ ಡೇಟಾದ ಆರ್ಕೈವ್ ಅನ್ನು ವಿನಂತಿಸಿ. ಒಮ್ಮೆ ಅದು ಲಭ್ಯವಾದ ನಂತರ, ಕೆಳಗಿನ ಜಿಪ್ (ZIP) ಆರ್ಕೈವ್ ಅನ್ನು ಅಪ್‌ಲೋಡ್ ಮಾಡಿ.", - "heading": "ಲಿಂಕ್ಡಿನ್(LinkedIn) ನಿಂದ ಆಮದು ಮಾಡಿಕೊಳ್ಳಿ" + "body": "ಲಿಂಕ್ಡ್‌ಇನ್‌ನಿಂದ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ರಫ್ತು ಮಾಡುವ ಮೂಲಕ ಮತ್ತು ರಿಯಾಕ್ಟಿವ್ ರೆಸ್ಯೂಮ್‌ನಲ್ಲಿ ಕ್ಷೇತ್ರಗಳನ್ನು ಸ್ವಯಂ ತುಂಬಲು ಅದನ್ನು ಬಳಸುವ ಮೂಲಕ ನೀವು ಸಮಯವನ್ನು ಉಳಿಸಬಹುದು. <1>ಡೇಟಾ ಗೌಪ್ಯತೆಗೆ ಹೋಗಿ ಲಿಂಕ್ಡ್‌ಇನ್‌ನಲ್ಲಿ ವಿಭಾಗ ಮತ್ತು ನಿಮ್ಮ ಡೇಟಾದ ಆರ್ಕೈವ್ ಅನ್ನು ವಿನಂತಿಸಿ. ಒಮ್ಮೆ ಅದು ಲಭ್ಯವಾದ ನಂತರ, ಕೆಳಗಿನ ಜಿಪ್ ಆರ್ಕೈವ್ ಅನ್ನು ಅಪ್‌ಲೋಡ್ ಮಾಡಿ.", + "heading": "ಲಿಂಕ್ಡಿನ್ ನಿಂದ ಆಮದು ಮಾಡಿಕೊಳ್ಳಿ" }, "reactive-resume": { "actions": { "upload-json": "ಜೆಸನ್ ಅನ್ನು ಅಪ್‌ಲೋಡ್ ಮಾಡಿ" }, - "body": "ನೀವು ರಿಯಾಕ್ಟಿವ್ ರೆಸ್ಯೂಮ್‌ನ ಪ್ರಸ್ತುತ ಆವೃತ್ತಿಯೊಂದಿಗೆ ರಫ್ತು ಮಾಡಲಾದ ಜೆಸನ್(JSON) ಅನ್ನು ಹೊಂದಿದ್ದರೆ, ಮತ್ತೆ ಸಂಪಾದಿಸಬಹುದಾದ ಆವೃತ್ತಿಯನ್ನು ಪಡೆಯಲು ನೀವು ಅದನ್ನು ಇಲ್ಲಿಗೆ ಆಮದು ಮಾಡಿಕೊಳ್ಳಬಹುದು. ರಿಯಾಕ್ಟಿವ್ ರೆಸ್ಯೂಮ್‌ನ ಹಿಂದಿನ ಆವೃತ್ತಿಗಳು ದುರದೃಷ್ಟವಶಾತ್ ಸದ್ಯಕ್ಕೆ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ.", + "body": "ನೀವು ರಿಯಾಕ್ಟಿವ್ ರೆಸ್ಯೂಮ್‌ನ ಪ್ರಸ್ತುತ ಆವೃತ್ತಿಯೊಂದಿಗೆ ರಫ್ತು ಮಾಡಲಾದ ಜೆಸನ್ ಅನ್ನು ಹೊಂದಿದ್ದರೆ, ಮತ್ತೆ ಸಂಪಾದಿಸಬಹುದಾದ ಆವೃತ್ತಿಯನ್ನು ಪಡೆಯಲು ನೀವು ಅದನ್ನು ಇಲ್ಲಿಗೆ ಆಮದು ಮಾಡಿಕೊಳ್ಳಬಹುದು. ರಿಯಾಕ್ಟಿವ್ ರೆಸ್ಯೂಮ್‌ನ ಹಿಂದಿನ ಆವೃತ್ತಿಗಳು ದುರದೃಷ್ಟವಶಾತ್ ಸದ್ಯಕ್ಕೆ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ.", "heading": "ಜೆಸನ್ ರೆಸ್ಯೂಮ್‌ನಿಂದ ಆಮದು ಮಾಡಿಕೊಳ್ಳಿ" } }, diff --git a/client/public/locales/ta/common.json b/client/public/locales/ta/common.json index 11f4a110..7e9d15f8 100644 --- a/client/public/locales/ta/common.json +++ b/client/public/locales/ta/common.json @@ -5,7 +5,6 @@ "logout": "வெளியேறு" } }, - "description": "ரியாக்டிவ் ரெஸ்யூம் என்பது ஒரு இலவச மற்றும் ஓப்பன் சோர்ஸ் ரெஸ்யூம் பில்டராகும், இது உங்கள் விண்ணப்பத்தை 1, 2, 3 என எளிதாக உருவாக்குவது, புதுப்பித்தல் மற்றும் பகிர்வது போன்ற சர்வ சாதாரணமான பணிகளைச் செய்ய உருவாக்கப்பட்டுள்ளது.", "footer": { "credit": "<1>அம்ருத் பிள்ளையின் திட்டம்", "license": "சமூகத்தால், சமூகத்திற்காக." diff --git a/client/store/build/buildSlice.ts b/client/store/build/buildSlice.ts index 671fd95d..f3581ddc 100644 --- a/client/store/build/buildSlice.ts +++ b/client/store/build/buildSlice.ts @@ -1,8 +1,6 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import merge from 'lodash/merge'; -import { Language, languageMap } from '@/config/languages'; - export type Theme = 'light' | 'dark'; export type Sidebar = 'left' | 'right'; @@ -13,7 +11,6 @@ export type Orientation = 'horizontal' | 'vertical'; export type BuildState = { theme?: Theme; - language: Language; sidebar: Record; page: { breakLine: boolean; @@ -22,7 +19,6 @@ export type BuildState = { }; const initialState: BuildState = { - language: languageMap['en'], sidebar: { left: { open: false }, right: { open: false }, @@ -35,8 +31,6 @@ const initialState: BuildState = { type SetThemePayload = { theme: Theme }; -type SetLanguagePayload = { language: string }; - type ToggleSidebarPayload = { sidebar: Sidebar }; type SetSidebarStatePayload = { sidebar: Sidebar; state: SidebarState }; @@ -50,11 +44,6 @@ export const buildSlice = createSlice({ state.theme = theme; }, - setLanguage: (state, action: PayloadAction) => { - const { language } = action.payload; - - state.language = languageMap[language]; - }, toggleSidebar: (state, action: PayloadAction) => { const { sidebar } = action.payload; @@ -76,7 +65,7 @@ export const buildSlice = createSlice({ }, }); -export const { setTheme, setLanguage, toggleSidebar, setSidebarState, togglePageBreakLine, togglePageOrientation } = +export const { setTheme, toggleSidebar, setSidebarState, togglePageBreakLine, togglePageOrientation } = buildSlice.actions; export default buildSlice.reducer; diff --git a/client/utils/getCookie.ts b/client/utils/getCookie.ts new file mode 100644 index 00000000..a3c3be21 --- /dev/null +++ b/client/utils/getCookie.ts @@ -0,0 +1,8 @@ +export const getCookie = (name: string): string | undefined => { + const value = `; ${document.cookie}`; + const parts = value.split(`; ${name}=`); + + if (parts.length === 2) { + return parts.at(-1); + } +}; diff --git a/client/wrappers/DateWrapper.tsx b/client/wrappers/DateWrapper.tsx index 7d0c0326..ab1f166e 100644 --- a/client/wrappers/DateWrapper.tsx +++ b/client/wrappers/DateWrapper.tsx @@ -1,14 +1,19 @@ import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; +import { useRouter } from 'next/router'; import { useEffect } from 'react'; const DateWrapper: React.FC = ({ children }) => { + const { locale } = useRouter(); + useEffect(() => { dayjs.extend(relativeTime); // Locales require('dayjs/locale/kn'); - }, []); + + locale && dayjs.locale(locale); + }, [locale]); return <>{children}; };