Skip to content

Commit

Permalink
Update translations and fix language changing when signing up (#1355)
Browse files Browse the repository at this point in the history
* Add language parameter to login and signup paths; support Ukrainian language

* Update translations

* Update snapshots

* Mailchimp (#1332)

* User can give marketing consent to a specific course

* syncing with mailchimp

* Mailchimp syncer

* Updated comments

* Updated comments

* Changes to mergefields and renaming

* Added email subscription status to UserMarketingConsent

* Little changes

* Changed println to info

* Moved div

* new checkbox and research consent for mailchimp syncer

* Eslint fixes

* Add kubernetes configs

* Add configuration to control removal of unsupported Mailchimp fields

* Add wait timeout for course language change test

* Refactor course language change test to improve button interaction handling

---------

Co-authored-by: Maija Y <[email protected]>
Co-authored-by: Henrik Nygren <[email protected]>

* Make unsubscribe processing run every 3 hours

* Enhance wait-for-db-migrations script to support waiting for additional tables

---------

Co-authored-by: Maija <[email protected]>
Co-authored-by: Maija Y <[email protected]>
  • Loading branch information
3 people authored Dec 11, 2024
1 parent 58a64b0 commit 1ec21a6
Show file tree
Hide file tree
Showing 21 changed files with 70 additions and 22 deletions.
3 changes: 2 additions & 1 deletion kubernetes/base/headless-lms/mailchimp-syncer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ spec:
- |
echo Waiting for postgres to be available
timeout 120 ./wait-for-db.sh
./wait-for-db-migrations.sh
# Need to also wait for marketing_mailing_list_access_tokens because migrations can take a moment to run, and the syncer depends on this table
./wait-for-db-migrations.sh marketing_mailing_list_access_tokens
resources:
requests:
memory: 100Mi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const UserNavigationControls: React.FC<React.PropsWithChildren<UserNavigationCon
currentPagePath,
courseId,
}) => {
const { t } = useTranslation()
const { t, i18n } = useTranslation()
const loginStateContext = useContext(LoginStateContext)
const [showSettings, setShowSettings] = useState<boolean>(false)
const returnTo = useCurrentPagePathForReturnTo(currentPagePath)
Expand All @@ -46,10 +46,10 @@ const UserNavigationControls: React.FC<React.PropsWithChildren<UserNavigationCon
}

// eslint-disable-next-line i18next/no-literal-string
const loginPathWithReturnTo = `/login?return_to=${encodeURIComponent(returnTo)}`
const loginPathWithReturnTo = `/login?return_to=${encodeURIComponent(returnTo)}&lang=${i18n.language}`

// eslint-disable-next-line i18next/no-literal-string
const signUpPathWithReturnTo = `/signup?return_to=${encodeURIComponent(returnTo)}`
const signUpPathWithReturnTo = `/signup?return_to=${encodeURIComponent(returnTo)}&lang=${i18n.language}`

return loginStateContext.signedIn ? (
<>
Expand Down
50 changes: 35 additions & 15 deletions services/headless-lms/server/src/programs/mailchimp_syncer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use headless_lms_utils::http::REQWEST_CLIENT;
use serde::Deserialize;
use serde_json::json;
use sqlx::{PgConnection, PgPool};
use std::{env, time::Duration};
use std::{
env,
time::{Duration, Instant},
};
use uuid::Uuid;

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -74,6 +77,7 @@ const REQUIRED_FIELDS: &[FieldSchema] = &[
/// These fields are excluded from removing all fields that are not in the schema
const FIELDS_EXCLUDED_FROM_REMOVING: &[&str] = &["PHONE", "PACE", "COUNTRY", "MMERGE9"];
const REMOVE_UNSUPPORTED_FIELDS: bool = false;
const PROCESS_UNSUBSCRIBES_INTERVAL_SECS: u64 = 10_800;

const SYNC_INTERVAL_SECS: u64 = 10;
const PRINT_STILL_RUNNING_MESSAGE_TICKS_THRESHOLD: u32 = 60;
Expand Down Expand Up @@ -115,6 +119,8 @@ pub async fn main() -> anyhow::Result<()> {

info!("Starting mailchimp syncer.");

let mut last_time_unsubscribes_processed = Instant::now();

loop {
interval.tick().await;
ticks += 1;
Expand All @@ -123,7 +129,14 @@ pub async fn main() -> anyhow::Result<()> {
ticks = 0;
info!("Still syncing.");
}
if let Err(e) = sync_contacts(&mut conn, &config).await {
let mut process_unsubscribes = false;
if last_time_unsubscribes_processed.elapsed().as_secs()
>= PROCESS_UNSUBSCRIBES_INTERVAL_SECS
{
process_unsubscribes = true;
last_time_unsubscribes_processed = Instant::now();
};
if let Err(e) = sync_contacts(&mut conn, &config, process_unsubscribes).await {
error!("Error during synchronization: {:?}", e);
}
}
Expand Down Expand Up @@ -348,7 +361,12 @@ async fn remove_field_from_mailchimp(
}

/// Synchronizes the user contacts with Mailchimp.
async fn sync_contacts(conn: &mut PgConnection, _config: &SyncerConfig) -> anyhow::Result<()> {
/// Added a boolean flag to determine whether to process unsubscribes.
async fn sync_contacts(
conn: &mut PgConnection,
_config: &SyncerConfig,
process_unsubscribes: bool,
) -> anyhow::Result<()> {
let access_tokens =
headless_lms_models::marketing_consents::fetch_all_marketing_mailing_list_access_tokens(
conn,
Expand All @@ -360,20 +378,22 @@ async fn sync_contacts(conn: &mut PgConnection, _config: &SyncerConfig) -> anyho
// Iterate through tokens and fetch and send user details to Mailchimp
for token in access_tokens {
// Fetch all users from Mailchimp and sync possible changes locally
let mailchimp_data = fetch_unsubscribed_users_from_mailchimp_in_chunks(
&token.mailchimp_mailing_list_id,
&token.server_prefix,
&token.access_token,
1000,
)
.await?;
if process_unsubscribes {
let mailchimp_data = fetch_unsubscribed_users_from_mailchimp_in_chunks(
&token.mailchimp_mailing_list_id,
&token.server_prefix,
&token.access_token,
1000,
)
.await?;

info!(
"Processing Mailchimp data for list: {}",
token.mailchimp_mailing_list_id
);
info!(
"Processing Mailchimp data for list: {}",
token.mailchimp_mailing_list_id
);

process_unsubscribed_users_from_mailchimp(conn, mailchimp_data).await?;
process_unsubscribed_users_from_mailchimp(conn, mailchimp_data).await?;
}

// Fetch unsynced emails and update them in Mailchimp
let users_with_unsynced_emails =
Expand Down
12 changes: 12 additions & 0 deletions services/headless-lms/wait-for-db-migrations.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,15 @@ done
echo ""

echo "Database is available: courses table found."

# The script can also wait for additional tables by passing them as arguments
for table in "$@"; do
echo "Waiting until I find the $table table in postgres..."
until test "$(psql "$DATABASE_URL" -c '\d' --csv | grep -c ",$table,table,")" -eq 1 2> /dev/null; do
echo -n "."
sleep 1
done
# Clear line because echo -n above wont print line breaks
echo ""
echo "Database is available: $table table found."
done
2 changes: 1 addition & 1 deletion shared-module/packages/common/src/hooks/useLanguage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getValueFromCookieString } from "../utils/cookies"
const LANGUAGE_QUERY_KEY = "lang"
const IS_SERVER = typeof window === "undefined"

const SUPPORTED_LANGUAGES = ["en", "fi"]
const SUPPORTED_LANGUAGES = ["en", "fi", "uk"]
const DEFAULT_LANGUAGE = "en"

const CAN_ACCESS_COOKIES = detectAccessToCookies()
Expand Down
1 change: 1 addition & 0 deletions shared-module/packages/common/src/locales/ar/cms.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"configure-review-answers-option": "تكوين خيار إجابات المراجعة",
"congratulations-explanation": "تُوضع هذه الكتلة في مواد الدورة حيث ترغب في تهنئة الطالب عند إكمال الدورة. بالنسبة للدورات التي تم تكوينها للحصول على ECTS، ستوفر أيضًا رابطًا لصفحة حيث يمكنهم تسجيل إكمالهم في الجامعة المفتوحة.",
"congratulations-placeholder": "عنصر نائب للتهنئة",
"content-saved-successfully": "تم حفظ المحتوى بنجاح!",
"copy-text-placeholder": "أدخل فقرة هنا...",
"course-instance-enrollment-condition": "الطالب مسجل في أي من دورات الدورة التالية:",
"course-progress-placeholder": "عنصر نائب لتقدم الدورة",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"additional-module": "وحدة إضافية",
"american-english": "الإنجليزية",
"an-insight-to-consider": "رؤية للتفكير",
"attempted-exercises": "التمارين المحاولة",
"attempted-exercises-required-for-completion": "التمارين المطلوبة لإكمالها",
"audio-notification-description": "استمع إلى محتوى الصفحة الحالية بصوت عالٍ",
"author": "المؤلفون",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,9 @@
"page-number": "الصفحة {{page-number}}",
"pages": "الصفحات",
"paper-size": "حجم الورق",
"partners-section-button-text": "إضافة قسم الشركاء",
"partners-section-heading": "إضافة شريط شعارات الشركاء",
"partners-section-text": "يتم عرض هذا المكون فوق التذييل مباشرةً في جميع صفحات الدورة، مما يتيح لك عرض شعارات المؤسسات الشريكة أو الرعاة، وكل شعار يرتبط بصفحة مختلفة.",
"password": "كلمة المرور",
"password-must-have-at-least-8-characters": "يجب أن تحتوي كلمة المرور على 8 أحرف على الأقل!",
"passwords-dont-match": "كلمات المرور غير متطابقة!",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"additional-module": "Additional module",
"american-english": "English",
"an-insight-to-consider": "An insight to consider",
"attempted-exercises": "Exercises completed",
"attempted-exercises": "Exercises attempted",
"attempted-exercises-required-for-completion": "Attempted exercises required for completion",
"audio-notification-description": "Hear the current page content read aloud",
"author": "Authors",
Expand Down
1 change: 1 addition & 0 deletions shared-module/packages/common/src/locales/fi/cms.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"configure-review-answers-option": "Määritä arvosteluvastausten asetus",
"congratulations-explanation": "Tämä lohko sijoitetaan kurssimateriaaliin, missä halutaan näyttää opiskelijalle onnittelut kurssin suorittamisesta. Jos kurssilta voi saada opiskelupisteitä, tämä lohko tarjoaa myös linkin sivulle, mistä opiskelija pääsee kirjaamaan suorituksensa Avoimeen yliopistoon.",
"congratulations-placeholder": "Onnittelulohko",
"content-saved-successfully": "Sisältö tallennettu onnistuneesti!",
"copy-text-placeholder": "Kirjoita kappale tähän...",
"course-instance-enrollment-condition": "Opiskelija on ilmoittautunut johonkin seuraavista kurssitoteutuksista:",
"course-progress-placeholder": "Kurssin edistyminen lohko",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"additional-module": "Ylimääräinen moduuli",
"american-english": "Englanti",
"an-insight-to-consider": "Ajatus pohdittavaksi",
"attempted-exercises": "Yritetyt harjoitukset",
"attempted-exercises-required-for-completion": "Yritettyjä tehtäviä vaaditaan läpipääsyyn",
"audio-notification-description": "Kuuntele tämän sivun sisältö ääneen luettuna",
"author": "Kirjoittajat",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,9 @@
"page-number": "sivu {{page-number}}",
"pages": "Sivut",
"paper-size": "Paperin koko",
"partners-section-button-text": "Lisää kumppaniosio",
"partners-section-heading": "Lisää kumppanilogojen palkki",
"partners-section-text": "Tämä komponentti näytetään juuri ennen alatunnistetta kaikilla kurssin sivuilla, ja sen avulla voit esitellä kumppanilaitosten tai sponsorien logoja. Jokainen logo linkittää eri sivulle.",
"passed": "Hyv.",
"password": "Salasana",
"password-must-have-at-least-8-characters": "Salasanassa täytyy olla vähintään 8 kirjainta!",
Expand Down
1 change: 1 addition & 0 deletions shared-module/packages/common/src/locales/uk/cms.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"configure-review-answers-option": "Налаштувати варіант відповідей на рецензію",
"congratulations-explanation": "Цей блок розташований у матеріалі курсу, де ви бажаєте привітати студента з завершенням курсу. Для курсів, які налаштовані на отримання ECTS, він також надасть посилання на сторінку, де вони можуть зареєструвати своє завершення в Відкритому університеті.",
"congratulations-placeholder": "Заповнювач привітань",
"content-saved-successfully": "Вміст успішно збережено!",
"copy-text-placeholder": "Введіть абзац тут...",
"course-instance-enrollment-condition": "Студент записався на будь-який з наступних курсів:",
"course-progress-placeholder": "Заповнювач прогресу курсу",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"additional-module": "Додатковий модуль",
"american-english": "Англійська",
"an-insight-to-consider": "Інсайт для розгляду",
"attempted-exercises": "Спробувані вправи",
"attempted-exercises-required-for-completion": "Спроби вправ, необхідних для завершення",
"audio-notification-description": "Прослуховування вмісту поточної сторінки вголос",
"audio-player": "Слухай",
Expand All @@ -27,7 +28,7 @@
"can-comment-on-portions-of-material-by-highlightig": "Ви можете прокоментувати окремі частини матеріалу, виділивши їх.",
"cannot-render-exercise-task-missing-url": "Неможливо відобразити завдання вправи, відсутня url.",
"chapter-chapter-number-chapter-name": "Розділ {{chapterNumber}}: {{chapterName}}",
"chapter-progress": "прогрес розділа",
"chapter-progress": "Прогрес розділу",
"chatbot-discalimer-sensitive-information": "Ніколи не розголошуйте будь-яку конфіденційну інформацію чатботу.",
"chatbot-disclaimer-check": "Завжди перевіряйте твердження, зроблені чатботом. Чатботи на основі LLM можуть створювати дуже переконливі, але фактично неправильні заяви.",
"chatbot-disclaimer-disclose-part-1": "Завжди розкривайте використання LLM у ваших дослідженнях. Ви можете знайти керівництво Університету Гельсінкі щодо використання LLM у навчанні",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,9 @@
"page-number": "сторінка {{номер сторінки}}",
"pages": "Сторінки",
"paper-size": "Розмір паперу",
"partners-section-button-text": "Додати розділ партнерів",
"partners-section-heading": "Додати панель логотипів партнерів",
"partners-section-text": "Цей компонент відображається безпосередньо над нижнім колонтитулом на всіх сторінках курсу, дозволяє демонструвати логотипи партнерських установ або спонсорів, кожен логотип посилається на різні сторінки.",
"password": "Пароль",
"password-must-have-at-least-8-characters": "Пароль має бути не менше 8 символів!",
"passwords-dont-match": "Паролі не збігаються!",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1ec21a6

Please sign in to comment.