98979b58f8
Create reusable utility modules to eliminate duplication across main.js, cv-matcher.js, and legal.js: - js/utils/form-helpers.js: showFieldError, clearFieldErrors, isValidEmail, extractApiError — shared form validation and error handling - js/utils/i18n.js: currentLang, t, applyLanguage, updateLegalLinks, browserLang — shared translation and language switching - js/utils/api.js: checkApiLive, getRecaptchaWebKey, getGoogleTagManagerId, loadGoogleTagManager — shared API configuration loading - js/modules/cookie-consent.js: getConsent, setConsent, initConsent, setupConsentHandlers — cookie banner and consent management All utilities exposed on window.MyAi namespace for use by existing pages. Full JSDoc headers and inline comments for maintainability. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
92 lines
2.8 KiB
JavaScript
92 lines
2.8 KiB
JavaScript
/**
|
|
* Internationalization (i18n) Utilities
|
|
*
|
|
* Shared helpers for language detection, translation lookup, and language switching.
|
|
* Expects window.MyAi.i18n dictionary to be populated by i18n.js.
|
|
*/
|
|
|
|
var LANG_KEY = "myai_lang";
|
|
|
|
/**
|
|
* Detect browser language preference from navigator.
|
|
* Returns 'ro' if browser language starts with 'ro', otherwise 'en'.
|
|
*
|
|
* @returns {string} - 'ro' or 'en'
|
|
*/
|
|
function browserLang() {
|
|
return ((navigator.language || navigator.userLanguage || 'en').toLowerCase().indexOf('ro') === 0) ? 'ro' : 'en';
|
|
}
|
|
|
|
/**
|
|
* Get the currently active language preference.
|
|
* Uses localStorage if set, otherwise detects from browser.
|
|
*
|
|
* @returns {string} - 'ro' or 'en'
|
|
*/
|
|
function currentLang() {
|
|
return localStorage.getItem(LANG_KEY) || browserLang();
|
|
}
|
|
|
|
/**
|
|
* Translate a key into the current language.
|
|
* Falls back to English if key not found in the current language.
|
|
* Requires window.MyAi.i18n to be populated with en/ro dictionaries.
|
|
*
|
|
* Usage: MyAi.t('form.name') → "Name" (or "Nume" if lang is 'ro')
|
|
*
|
|
* @param {string} key - Translation key (e.g., 'form.name')
|
|
* @returns {string} - Translated text or fallback key if not found
|
|
*/
|
|
function t(key) {
|
|
var lang = currentLang();
|
|
return (window.MyAi.i18n[lang] && window.MyAi.i18n[lang][key]) ||
|
|
window.MyAi.i18n.en[key] || key;
|
|
}
|
|
|
|
/**
|
|
* Apply a language across the entire page.
|
|
* Updates:
|
|
* - localStorage with new language preference
|
|
* - <html lang> attribute
|
|
* - All [data-i18n] elements with translated text
|
|
* - All [data-i18n-placeholder] elements with translated placeholders
|
|
* - Legal page links to point to correct language version
|
|
* - Language button states (aria-pressed)
|
|
*
|
|
* @param {string} lang - Language code ('en' or 'ro')
|
|
*/
|
|
function applyLanguage(lang) {
|
|
localStorage.setItem(LANG_KEY, lang);
|
|
document.documentElement.lang = lang;
|
|
updateLegalLinks(lang);
|
|
$('[data-i18n]').each(function () {
|
|
$(this).text(t($(this).data('i18n')));
|
|
});
|
|
$('[data-i18n-placeholder]').each(function () {
|
|
$(this).attr('placeholder', t($(this).data('i18n-placeholder')));
|
|
});
|
|
$('.lang-flag').attr('aria-pressed', 'false');
|
|
$('.lang-flag[data-lang="' + lang + '"]').attr('aria-pressed', 'true');
|
|
}
|
|
|
|
/**
|
|
* Update all legal page links to point to the active language version.
|
|
* Looks for [data-legal] attribute (e.g., data-legal="terms") and
|
|
* updates href to /legal/{page}-{lang}.html
|
|
*
|
|
* @param {string} lang - Language code ('en' or 'ro')
|
|
*/
|
|
function updateLegalLinks(lang) {
|
|
$('[data-legal]').each(function () {
|
|
var page = $(this).data('legal');
|
|
$(this).attr('href', '/legal/' + page + '-' + lang + '.html');
|
|
});
|
|
}
|
|
|
|
// Expose i18n utilities on window.MyAi for use by other scripts
|
|
window.MyAi = window.MyAi || {};
|
|
window.MyAi.currentLang = currentLang;
|
|
window.MyAi.t = t;
|
|
window.MyAi.applyLanguage = applyLanguage;
|
|
window.MyAi.browserLang = browserLang;
|