Skip to content

Commit 636f4c1

Browse files
committed
feat: add localisation (crucial upd)
1 parent d700ab3 commit 636f4c1

28 files changed

Lines changed: 448 additions & 82 deletions

package-lock.json

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"@capacitor/keyboard": "^8.0.5",
3030
"@capacitor/status-bar": "^8.0.2",
3131
"@ionic/angular": "^8.8.11",
32+
"@ngx-translate/core": "^18.0.0",
3233
"git-describe": "^4.1.0",
3334
"rxjs": "~7.8.2",
3435
"tslib": "^2.2.0",

src/app/i18n/eng.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
export const eng = {
2+
COMMON: {
3+
BACK: 'Back',
4+
},
5+
TABS: {
6+
QUIZ: 'Quiz',
7+
THEORY: 'Theory',
8+
PROFILE: 'Profile',
9+
},
10+
PROFILE: {
11+
TITLE: 'Profile',
12+
AVATAR_ALT: 'Profile avatar',
13+
PROGRESS: 'Progress',
14+
DAYS_STREAK: 'Days streak',
15+
SETTINGS: 'Settings',
16+
THEME: 'Theme',
17+
THEME_LIGHT: 'Light',
18+
THEME_DARK: 'Dark',
19+
LANGUAGE: 'Language',
20+
APP_VERSION: 'App version',
21+
ABOUT: 'About',
22+
HOW_TO_LEARN: 'How to learn',
23+
STAR_ON_GITHUB: 'Star on GitHub',
24+
CLEAR_RESULTS: 'Clear Results',
25+
CLEAR_ALERT: {
26+
HEADER: 'All your progress will be lost',
27+
MESSAGE: 'Are you sure you want to clear your progress and start over again?',
28+
CANCEL: 'Cancel',
29+
CONFIRM: 'Clear',
30+
},
31+
},
32+
QUESTIONS: {
33+
TITLE: 'Theory Questions',
34+
SEARCH_PLACEHOLDER: 'Search by topic, keyword or ID',
35+
},
36+
QUESTION_INFO: {
37+
TITLE: 'Question №{{id}}',
38+
UPDATED: 'Updated {{date}}',
39+
MARK_COMPLETE: 'Mark question as complete',
40+
PREV: 'Prev',
41+
NEXT: 'Next',
42+
LOAD_ERROR: {
43+
TITLE: '404 - Answer Text Not Found',
44+
TEXT: 'Help us fill the gap — we\'d love your contribution via a',
45+
LINK: 'Pull Request on GitHub',
46+
},
47+
},
48+
QUIZ: {
49+
RANDOMIZE: 'Randomize Questions',
50+
NUMBER: '№{{id}}',
51+
TAP_TO_READ: 'Tap to read theory',
52+
PROGRESS: 'Progress',
53+
SKIP: 'Skip',
54+
CHECK_ANSWER: 'Check your answer',
55+
},
56+
ANSWER_STRUCTURE: {
57+
TITLE: 'Answer structure for question №{{id}}',
58+
HINT: 'Select the points you covered in your answer - this helps indicate how complete your response was.',
59+
SAVE: 'Save your answer progress',
60+
},
61+
HOW_TO_LEARN: {
62+
TITLE: 'How to learn',
63+
HERO: 'Interview-ready in three passes',
64+
INTRO: 'An interview is an oral exam: you get 60–90 seconds to give a clear, confident answer before the follow-ups begin. Good news — about 20% of the material delivers 80% of the result, and this app is built around exactly that 20%. Here is the whole plan:',
65+
OUTRO: 'That\'s it — no walls of text, no cramming marathons. Just a simple loop that fits into your day. Good luck out there! 🚀',
66+
STEPS: {
67+
S1: {
68+
TITLE: 'Pass 1 — read the Cores',
69+
TEXT: 'Every answer starts with a Core: the 1–2 minute spoken version — definition, key idea, a minimal example, classic pitfalls. That is exactly what interviewers expect to hear first, so simply read the Cores topic by topic.',
70+
},
71+
S2: {
72+
TITLE: 'Rehearse out loud in the Quiz',
73+
TEXT: 'Answer every question aloud, as if the interviewer were already in the room. Then open the answer structure and honestly tick only the points you actually said — anything below 100% will keep coming back until you own it.',
74+
},
75+
S3: {
76+
TITLE: 'Pass 2 — unfold the Deep Dives',
77+
TEXT: 'Once the Cores feel easy, open the Deep Dives: under-the-hood mechanics, edge cases and senior-level details for when the interviewer starts digging.',
78+
},
79+
S4: {
80+
TITLE: '15 minutes a day is enough',
81+
TEXT: 'Cores are phone-sized on purpose — perfect for a commute or a coffee queue. A short daily session beats any cramming marathon and keeps your streak alive.',
82+
},
83+
S5: {
84+
TITLE: 'Pass 3 — the night before',
85+
TEXT: 'Skim the Cores one last time and run the Quiz in random order as a final dress rehearsal. Then walk in and nail the first 90 seconds of every answer.',
86+
},
87+
},
88+
},
89+
};
90+
91+
export type Translations = typeof eng;

src/app/i18n/rus.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { Translations } from './eng';
2+
3+
export const rus: Translations = {
4+
COMMON: {
5+
BACK: 'Назад',
6+
},
7+
TABS: {
8+
QUIZ: 'Квиз',
9+
THEORY: 'Теория',
10+
PROFILE: 'Профиль',
11+
},
12+
PROFILE: {
13+
TITLE: 'Профиль',
14+
AVATAR_ALT: 'Аватар профиля',
15+
PROGRESS: 'Прогресс',
16+
DAYS_STREAK: 'Дней подряд',
17+
SETTINGS: 'Настройки',
18+
THEME: 'Тема',
19+
THEME_LIGHT: 'Светлая',
20+
THEME_DARK: 'Тёмная',
21+
LANGUAGE: 'Язык',
22+
APP_VERSION: 'Версия приложения',
23+
ABOUT: 'О приложении',
24+
HOW_TO_LEARN: 'Как учиться',
25+
STAR_ON_GITHUB: 'Звезда на GitHub',
26+
CLEAR_RESULTS: 'Очистить результаты',
27+
CLEAR_ALERT: {
28+
HEADER: 'Весь ваш прогресс будет потерян',
29+
MESSAGE: 'Вы уверены, что хотите очистить прогресс и начать заново?',
30+
CANCEL: 'Отмена',
31+
CONFIRM: 'Очистить',
32+
},
33+
},
34+
QUESTIONS: {
35+
TITLE: 'Теоретические вопросы',
36+
SEARCH_PLACEHOLDER: 'Поиск по теме, ключевому слову или ID',
37+
},
38+
QUESTION_INFO: {
39+
TITLE: 'Вопрос №{{id}}',
40+
UPDATED: 'Обновлено {{date}}',
41+
MARK_COMPLETE: 'Отметить вопрос как изученный',
42+
PREV: 'Назад',
43+
NEXT: 'Далее',
44+
LOAD_ERROR: {
45+
TITLE: '404 — текст ответа не найден',
46+
TEXT: 'Помогите заполнить пробел — мы будем рады вашему вкладу через',
47+
LINK: 'Pull Request на GitHub',
48+
},
49+
},
50+
QUIZ: {
51+
RANDOMIZE: 'Случайные вопросы',
52+
NUMBER: '№{{id}}',
53+
TAP_TO_READ: 'Нажмите, чтобы прочитать теорию',
54+
PROGRESS: 'Прогресс',
55+
SKIP: 'Пропустить',
56+
CHECK_ANSWER: 'Проверить ответ',
57+
},
58+
ANSWER_STRUCTURE: {
59+
TITLE: 'Структура ответа на вопрос №{{id}}',
60+
HINT: 'Отметьте пункты, которые вы упомянули в своём ответе — это поможет оценить, насколько полным он был.',
61+
SAVE: 'Сохранить прогресс ответа',
62+
},
63+
HOW_TO_LEARN: {
64+
TITLE: 'Как учиться',
65+
HERO: 'Готовность к собеседованию за три прохода',
66+
INTRO: 'Собеседование — это устный экзамен: у вас есть 60–90 секунд, чтобы дать чёткий и уверенный ответ, прежде чем начнутся уточняющие вопросы. Хорошая новость — около 20% материала даёт 80% результата, и это приложение построено именно вокруг этих 20%. Вот весь план:',
67+
OUTRO: 'Вот и всё — никаких простыней текста и марафонов зубрёжки. Лишь простой цикл, который вписывается в ваш день. Удачи! 🚀',
68+
STEPS: {
69+
S1: {
70+
TITLE: 'Проход 1 — читайте Ядра',
71+
TEXT: 'Каждый ответ начинается с Ядра: разговорная версия на 1–2 минуты — определение, ключевая идея, минимальный пример, классические подводные камни. Именно это интервьюеры ожидают услышать первым, так что просто читайте Ядра тему за темой.',
72+
},
73+
S2: {
74+
TITLE: 'Репетируйте вслух в Квизе',
75+
TEXT: 'Отвечайте на каждый вопрос вслух, как будто интервьюер уже в комнате. Затем откройте структуру ответа и честно отметьте только те пункты, которые действительно произнесли — всё, что ниже 100%, будет возвращаться, пока вы это не освоите.',
76+
},
77+
S3: {
78+
TITLE: 'Проход 2 — раскройте Deep Dive',
79+
TEXT: 'Когда Ядра даются легко, откройте Deep Dive: внутренние механизмы, граничные случаи и детали senior-уровня на случай, когда интервьюер начнёт копать глубже.',
80+
},
81+
S4: {
82+
TITLE: '15 минут в день достаточно',
83+
TEXT: 'Ядра намеренно помещаются в экран телефона — идеально для дороги или очереди за кофе. Короткая ежедневная сессия лучше любого марафона зубрёжки и сохраняет ваш стрик.',
84+
},
85+
S5: {
86+
TITLE: 'Проход 3 — вечер накануне',
87+
TEXT: 'В последний раз просмотрите Ядра и пройдите Квиз в случайном порядке как финальную генеральную репетицию. А затем заходите и уверенно выдавайте первые 90 секунд каждого ответа.',
88+
},
89+
},
90+
},
91+
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Injectable } from '@angular/core';
2+
import { Observable, of } from 'rxjs';
3+
import { TranslateLoader } from '@ngx-translate/core';
4+
5+
import { Languages } from 'src/app/enums/app.enum';
6+
import { eng, Translations } from './eng';
7+
import { ukr } from './ukr';
8+
import { rus } from './rus';
9+
10+
const TRANSLATIONS: Record<Languages, Translations> = {
11+
[Languages.eng]: eng,
12+
[Languages.ukr]: ukr,
13+
[Languages.rus]: rus,
14+
};
15+
16+
// Dictionaries are compiled into the bundle: language changes reload the app,
17+
// so a synchronous loader avoids any flash of untranslated keys.
18+
@Injectable()
19+
export class StaticTranslateLoader implements TranslateLoader {
20+
getTranslation(lang: string): Observable<Translations> {
21+
return of(TRANSLATIONS[lang as Languages] ?? eng);
22+
}
23+
}

src/app/i18n/ukr.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { Translations } from './eng';
2+
3+
export const ukr: Translations = {
4+
COMMON: {
5+
BACK: 'Назад',
6+
},
7+
TABS: {
8+
QUIZ: 'Квіз',
9+
THEORY: 'Теорія',
10+
PROFILE: 'Профіль',
11+
},
12+
PROFILE: {
13+
TITLE: 'Профіль',
14+
AVATAR_ALT: 'Аватар профілю',
15+
PROGRESS: 'Прогрес',
16+
DAYS_STREAK: 'Днів поспіль',
17+
SETTINGS: 'Налаштування',
18+
THEME: 'Тема',
19+
THEME_LIGHT: 'Світла',
20+
THEME_DARK: 'Темна',
21+
LANGUAGE: 'Мова',
22+
APP_VERSION: 'Версія застосунку',
23+
ABOUT: 'Про застосунок',
24+
HOW_TO_LEARN: 'Як навчатися',
25+
STAR_ON_GITHUB: 'Зірка на GitHub',
26+
CLEAR_RESULTS: 'Очистити результати',
27+
CLEAR_ALERT: {
28+
HEADER: 'Увесь ваш прогрес буде втрачено',
29+
MESSAGE: 'Ви впевнені, що хочете очистити прогрес і почати спочатку?',
30+
CANCEL: 'Скасувати',
31+
CONFIRM: 'Очистити',
32+
},
33+
},
34+
QUESTIONS: {
35+
TITLE: 'Теоретичні питання',
36+
SEARCH_PLACEHOLDER: 'Пошук за темою, ключовим словом або ID',
37+
},
38+
QUESTION_INFO: {
39+
TITLE: 'Питання №{{id}}',
40+
UPDATED: 'Оновлено {{date}}',
41+
MARK_COMPLETE: 'Позначити питання як вивчене',
42+
PREV: 'Назад',
43+
NEXT: 'Далі',
44+
LOAD_ERROR: {
45+
TITLE: '404 — текст відповіді не знайдено',
46+
TEXT: 'Допоможіть заповнити прогалину — ми будемо раді вашому внеску через',
47+
LINK: 'Pull Request на GitHub',
48+
},
49+
},
50+
QUIZ: {
51+
RANDOMIZE: 'Випадкові питання',
52+
NUMBER: '№{{id}}',
53+
TAP_TO_READ: 'Торкніться, щоб прочитати теорію',
54+
PROGRESS: 'Прогрес',
55+
SKIP: 'Пропустити',
56+
CHECK_ANSWER: 'Перевірити відповідь',
57+
},
58+
ANSWER_STRUCTURE: {
59+
TITLE: 'Структура відповіді на питання №{{id}}',
60+
HINT: 'Позначте пункти, які ви згадали у своїй відповіді — це допоможе оцінити, наскільки повною вона була.',
61+
SAVE: 'Зберегти прогрес відповіді',
62+
},
63+
HOW_TO_LEARN: {
64+
TITLE: 'Як навчатися',
65+
HERO: 'Готовність до співбесіди за три проходи',
66+
INTRO: 'Співбесіда — це усний іспит: у вас є 60–90 секунд, щоб дати чітку та впевнену відповідь, перш ніж почнуться уточнювальні запитання. Гарна новина — близько 20% матеріалу дає 80% результату, і цей застосунок побудований саме навколо цих 20%. Ось увесь план:',
67+
OUTRO: 'Ось і все — жодних простирадл тексту та марафонів зубріння. Лише простий цикл, що вписується у ваш день. Успіхів! 🚀',
68+
STEPS: {
69+
S1: {
70+
TITLE: 'Прохід 1 — читайте Ядра',
71+
TEXT: 'Кожна відповідь починається з Ядра: розмовна версія на 1–2 хвилини — визначення, ключова ідея, мінімальний приклад, класичні підводні камені. Саме це інтерв’юери очікують почути першим, тож просто читайте Ядра тема за темою.',
72+
},
73+
S2: {
74+
TITLE: 'Репетируйте вголос у Квізі',
75+
TEXT: 'Відповідайте на кожне питання вголос, ніби інтерв’юер уже в кімнаті. Потім відкрийте структуру відповіді та чесно позначте лише ті пункти, які справді сказали — усе, що нижче 100%, повертатиметься, доки ви його не опануєте.',
76+
},
77+
S3: {
78+
TITLE: 'Прохід 2 — розкрийте Deep Dive',
79+
TEXT: 'Коли Ядра даються легко, відкрийте Deep Dive: внутрішні механізми, крайні випадки та деталі senior-рівня на випадок, коли інтерв’юер почне копати глибше.',
80+
},
81+
S4: {
82+
TITLE: '15 хвилин на день достатньо',
83+
TEXT: 'Ядра навмисно вміщуються в екран телефона — ідеально для дороги чи черги за кавою. Коротка щоденна сесія краща за будь-який марафон зубріння та зберігає ваш стрік.',
84+
},
85+
S5: {
86+
TITLE: 'Прохід 3 — вечір напередодні',
87+
TEXT: 'Востаннє перегляньте Ядра та пройдіть Квіз у випадковому порядку як фінальну генеральну репетицію. А потім заходьте та впевнено видавайте перші 90 секунд кожної відповіді.',
88+
},
89+
},
90+
},
91+
};

0 commit comments

Comments
 (0)