From e8f99194c21e7d5b0a9f012b495ed815c7bbf1e8 Mon Sep 17 00:00:00 2001 From: Adrian Pascu Date: Tue, 16 Jan 2024 05:08:55 +0100 Subject: [PATCH] =?UTF-8?q?Add=20Russian=20language=20=F0=9F=87=B7?= =?UTF-8?q?=F0=9F=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc | 3 ++- src/Countdown.tsx | 20 +++++++++++------- src/Settings.tsx | 5 +++-- src/translation/en.ts | 11 ++++++++++ src/translation/index.ts | 44 ++++++++++++++++++++++++++++++++++++++++ src/translation/ru.ts | 11 ++++++++++ 6 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 src/translation/en.ts create mode 100644 src/translation/index.ts create mode 100644 src/translation/ru.ts diff --git a/.eslintrc b/.eslintrc index 79fb749..88bce89 100644 --- a/.eslintrc +++ b/.eslintrc @@ -47,6 +47,7 @@ "allowTernary": true, "enforceForJSX": true } - ] + ], + "no-restricted-syntax": "off" } } diff --git a/src/Countdown.tsx b/src/Countdown.tsx index 39a16d5..5e03f86 100644 --- a/src/Countdown.tsx +++ b/src/Countdown.tsx @@ -6,6 +6,14 @@ import FONT_FAMILY from "./font"; import { GIT_HASH } from "./config"; import { calculateAgeLocal } from "./calculate-age"; import { colorBackground, colorPrimary, colorSecondary } from "./colors"; +import { + AGE, + COPY_LABEL, + SOURCE_CODE, + BIRTH_DAY_FORMAT, + AGE_COPIED, + AGE_COPY_FAILED, +} from "./translation"; const animationLoop = (cb: (time: DOMHighResTimeStamp) => void) => { let handle: number; @@ -17,8 +25,6 @@ const animationLoop = (cb: (time: DOMHighResTimeStamp) => void) => { return () => cancelAnimationFrame(handle); }; -const COPY_LABEL = "Click to copy age to clipboard"; - export default ({ birthDay, openSettings, @@ -41,9 +47,9 @@ export default ({ const ageString = `${largeAge()}.${smallAge()}`; try { await navigator.clipboard.writeText(ageString); - toast.success("Age copied to clipboard!"); + toast.success(AGE_COPIED); } catch (err) { - toast.error("Failed to copy age to clipboard!"); + toast.error(AGE_COPY_FAILED); } }; return ( @@ -75,9 +81,9 @@ export default ({ color: colorSecondary(), "margin-left": "4px", }} - title={`Birthday: ${birthDay.toLocaleString()}`} + title={BIRTH_DAY_FORMAT(birthDay)} > -
Age
+
{AGE}
- (source code) + {`(${SOURCE_CODE})`} diff --git a/src/Settings.tsx b/src/Settings.tsx index 49797a4..c5ebf6f 100644 --- a/src/Settings.tsx +++ b/src/Settings.tsx @@ -2,6 +2,7 @@ import { createSignal } from "solid-js"; import { Temporal } from "temporal-polyfill"; import FONT_FAMILY from "./font"; import { colorBackground, colorPrimary, colorSecondary } from "./colors"; +import { ENTER_BIRTHDAY, MOTIVATE } from "./translation"; export default ({ onBirthDay, @@ -28,7 +29,7 @@ export default ({ "margin-bottom": "4px", }} > - Enter your Birthday + {ENTER_BIRTHDAY} - Motivate + {MOTIVATE} ); diff --git a/src/translation/en.ts b/src/translation/en.ts new file mode 100644 index 0000000..565287a --- /dev/null +++ b/src/translation/en.ts @@ -0,0 +1,11 @@ +import type { Temporal } from "temporal-polyfill"; + +export const AGE = "Age"; +export const SOURCE_CODE = "source code"; +export const COPY_LABEL = "Click to copy age to clipboard"; +export const BIRTH_DAY_FORMAT = (birthDay: Temporal.PlainDate) => + `Birthday: ${birthDay.toLocaleString()}`; +export const AGE_COPIED = "Age copied to clipboard!"; +export const AGE_COPY_FAILED = "Failed to copy age to clipboard!"; +export const ENTER_BIRTHDAY = "Enter your Birthday"; +export const MOTIVATE = "Motivate"; diff --git a/src/translation/index.ts b/src/translation/index.ts new file mode 100644 index 0000000..1bcbddb --- /dev/null +++ b/src/translation/index.ts @@ -0,0 +1,44 @@ +const SUPPORTED_LANGUAGES = ["en", "ru"] as const; +const DEFAULT_LANGUAGE = "en"; + +const PREFERRED_LANGUAGES = window.navigator.languages.map((lang) => + lang.slice(0, 2), +); + +const getMatchedLanguage = () => { + for (const lang of PREFERRED_LANGUAGES) { + const match = SUPPORTED_LANGUAGES.find((supportedLang) => { + return lang === supportedLang; + }); + if (match) { + return match; + } + } + return DEFAULT_LANGUAGE; +}; + +const MATCHED_LANGUAGE = getMatchedLanguage(); +const path = `./${MATCHED_LANGUAGE}` as const; +let data; +switch (path) { + // TODO: remove workaround for TypeScript limitation + case "./en": + data = await import("./en"); + break; + case "./ru": + data = await import("./ru"); + break; + default: + throw new Error("Language not supported"); +} + +export const { + AGE, + SOURCE_CODE, + COPY_LABEL, + BIRTH_DAY_FORMAT, + AGE_COPIED, + AGE_COPY_FAILED, + ENTER_BIRTHDAY, + MOTIVATE, +} = data; diff --git a/src/translation/ru.ts b/src/translation/ru.ts new file mode 100644 index 0000000..7a866ca --- /dev/null +++ b/src/translation/ru.ts @@ -0,0 +1,11 @@ +import type { Temporal } from "temporal-polyfill"; + +export const AGE = "Возраст"; +export const SOURCE_CODE = "исходный код"; +export const COPY_LABEL = "Нажмите, чтобы скопировать возраст в буфер обмена"; +export const BIRTH_DAY_FORMAT = (birthDay: Temporal.PlainDate) => + `День рождения: ${birthDay.toLocaleString()}`; +export const AGE_COPIED = "Возраст скопирован в буфер обмена!"; +export const AGE_COPY_FAILED = "Не удалось скопировать возраст в буфер обмена!"; +export const ENTER_BIRTHDAY = "Введите свой день рождения"; +export const MOTIVATE = "Мотивировать";