Как динамически загружать языковые JavaScript файлы
Узнайте, как динамически загружать языковые JavaScript файлы на основе языка страницы в многоязычных веб-сайтах. Полное руководство с примерами кода и лучшими практиками для оптимальной производительности.
Как динамически загружать языковые JavaScript-файлы в зависимости от языка страницы на многоязычном сайте?
Я работаю над многоязычным сайтом, который использует внешний виджет погоды. Мне нужно реализовать решение, которое автоматически загружает правильный JavaScript-файл в зависимости от языка текущей страницы.
Текущая реализация:
<div id="weatherInfo2"></div>
<script src="https://abomus.co.il/js/en-weather.js" defer></script>
Желаемая функциональность:
- Когда URL содержит
/de/→ загружатьhttps://abomus.co.il/js/de-weather.js - Когда URL содержит
/fr/→ загружатьhttps://abomus.co.il/js/fr-weather.js - Когда URL содержит
/pl/→ загружатьhttps://abomus.co.il/js/pl-weather.js
Какой самый эффективный метод динамической загрузки соответствующего JavaScript-файла на основе текущего языка страницы с помощью чистого JavaScript? Можно ли использовать атрибут <html lang> для определения языка и условной загрузки нужного скрипта?
Документация по виджету доступна по адресу: https://abomus.co.il/en/widget
Содержание
- Определение языка страницы
- Методы динамической загрузки скриптов
- Примеры реализации
- Лучшие практики и рекомендации
- Обработка ошибок и резервные варианты
Определение языка страницы
У вас есть два основных метода для определения текущего языка страницы:
Метод 1: Использование шаблона URL
function getLanguageFromURL() {
const path = window.location.pathname;
// Извлекаем язык из URL, например /de/, /fr/, /pl/
const languageMatch = path.match(/^\/([a-z]{2})\//);
return languageMatch ? languageMatch[1] : 'en'; // По умолчанию английский
}
Метод 2: Использование атрибута HTML lang
function getLanguageFromHTML() {
const htmlElement = document.documentElement;
return htmlElement.lang || 'en'; // Резерв на английский, если не задан
}
Метод с URL обычно более надежен для многоязычных сайтов, так как он напрямую отражает контекст языка текущей страницы, в то время как атрибут HTML lang предоставляет семантическую альтернативу.
Методы динамической загрузки скриптов
Метод 1: Базовое создание динамического скрипта
function loadLanguageScript(language = 'en') {
// Удаляем существующий скрипт погоды, если он есть
const existingScript = document.querySelector('script[src*="weather.js"]');
if (existingScript) {
existingScript.remove();
}
// Создаем новый элемент скрипта
const script = document.createElement('script');
script.src = `https://abomus.co.il/js/${language}-weather.js`;
script.defer = true;
script.id = 'weather-script';
// Добавляем в документ
document.head.appendChild(script);
}
Метод 2: Использование jQuery (если уже используется в проекте)
function loadLanguageScriptjQuery(language = 'en') {
$.ajax({
url: `https://abomus.co.il/js/${language}-weather.js`,
dataType: "script",
cache: true,
success: function() {
console.log(`Скрипт погоды загружен для ${language}`);
},
error: function() {
console.error(`Не удалось загрузить скрипт погоды для ${language}`);
}
});
}
Метод 3: Современная загрузка модулей (ES6)
async function loadLanguageScriptModern(language = 'en') {
try {
// Удаляем существующий скрипт
const existingScript = document.querySelector('script[src*="weather.js"]');
if (existingScript) {
existingScript.remove();
}
// Создаем и загружаем новый скрипт
const script = document.createElement('script');
script.src = `https://abomus.co.il/js/${language}-weather.js`;
script.defer = true;
return new Promise((resolve, reject) => {
script.onload = () => resolve();
script.onerror = () => reject(new Error(`Не удалось загрузить ${language}-weather.js`));
document.head.appendChild(script);
});
} catch (error) {
console.error('Ошибка загрузки языкового скрипта:', error);
}
}
Примеры реализации
Полное решение с определением по URL
document.addEventListener('DOMContentLoaded', function() {
// Инициализация виджета погоды
function initializeWeatherWidget() {
const language = getLanguageFromURL();
loadLanguageScript(language);
}
// Получение языка из URL
function getLanguageFromURL() {
const path = window.location.pathname;
const languageMatch = path.match(/^\/([a-z]{2})\//);
return languageMatch ? languageMatch[1] : 'en';
}
// Загрузка языкового скрипта
function loadLanguageScript(language = 'en') {
const existingScript = document.querySelector('script[src*="weather.js"]');
if (existingScript) {
existingScript.remove();
}
const script = document.createElement('script');
script.src = `https://abomus.co.il/js/${language}-weather.js`;
script.defer = true;
script.id = 'weather-script';
// Добавление обработки ошибок
script.onerror = function() {
console.warn(`Не удалось загрузить ${language}-weather.js, переход на английский`);
if (language !== 'en') {
loadLanguageScript('en'); // Резерв на английский
}
};
document.head.appendChild(script);
}
// Инициализация при загрузке страницы
initializeWeatherWidget();
// Обработка навигации назад/вперед в браузере
window.addEventListener('popstate', initializeWeatherWidget);
});
Решение с использованием атрибута HTML lang
document.addEventListener('DOMContentLoaded', function() {
function initializeWeatherWidget() {
const language = getLanguageFromHTML();
loadLanguageScript(language);
}
function getLanguageFromHTML() {
const htmlElement = document.documentElement;
// Извлекаем код языка (например, "en" из "en-US")
return htmlElement.lang ? htmlElement.lang.split('-')[0] : 'en';
}
function loadLanguageScript(language = 'en') {
const existingScript = document.querySelector('script[src*="weather.js"]');
if (existingScript) {
existingScript.remove();
}
const script = document.createElement('script');
script.src = `https://abomus.co.il/js/${language}-weather.js`;
script.defer = true;
script.id = 'weather-script';
document.head.appendChild(script);
}
initializeWeatherWidget();
});
Расширенное решение с сохранением языка
class WeatherWidgetLoader {
constructor() {
this.currentLanguage = null;
this.scriptElement = null;
this.init();
}
init() {
this.currentLanguage = this.detectLanguage();
this.loadScript();
// Слушаем изменения языка
window.addEventListener('popstate', () => {
this.currentLanguage = this.detectLanguage();
this.loadScript();
});
}
detectLanguage() {
// Сначала пробуем URL, затем атрибут HTML lang
const urlLanguage = this.getLanguageFromURL();
const htmlLanguage = this.getLanguageFromHTML();
return urlLanguage || htmlLanguage || 'en';
}
getLanguageFromURL() {
const path = window.location.pathname;
const languageMatch = path.match(/^\/([a-z]{2})\//);
return languageMatch ? languageMatch[1] : null;
}
getLanguageFromHTML() {
const htmlElement = document.documentElement;
return htmlElement.lang ? htmlElement.lang.split('-')[0] : null;
}
loadScript(language = this.currentLanguage) {
if (this.scriptElement) {
this.scriptElement.remove();
}
this.scriptElement = document.createElement('script');
this.scriptElement.src = `https://abomus.co.il/js/${language}-weather.js`;
this.scriptElement.defer = true;
this.scriptElement.id = 'weather-script';
// Добавляем обработчики событий
this.scriptElement.onload = () => {
console.log(`Виджет погоды загружен для ${language}`);
this.onScriptLoad();
};
this.scriptElement.onerror = () => {
console.error(`Не удалось загрузить виджет погоды для ${language}`);
if (language !== 'en') {
console.log('Переход на английский');
this.loadScript('en');
}
};
document.head.appendChild(this.scriptElement);
}
onScriptLoad() {
// Опционально: вызываем пользовательское событие или callback
const event = new CustomEvent('weatherWidgetLoaded', {
detail: { language: this.currentLanguage }
});
document.dispatchEvent(event);
}
}
// Инициализация загрузчика виджета
const weatherWidget = new WeatherWidgetLoader();
Лучшие практики и рекомендации
Оптимизация производительности
- Отложенная загрузка: Используйте атрибут
deferдля предотвращения блокировки рендеринга страницы - Кэширование скриптов: Убедитесь, что у скриптов правильные заголовки кэширования
- Загрузка только один раз: Проверяйте, загружен ли скрипт, перед созданием дубликатов
- Загрузка модулей: Рассмотрите использование ES6 модулей для лучшего управления зависимостями
Совместимость с браузерами
- Все методы работают в современных браузерах (Chrome, Firefox, Safari, Edge)
- Для поддержки Internet Explorer избегайте одновременного использования
asyncиdefer - Рассмотрите использование
$.getScript()jQuery для поддержки старых браузеров
SEO-рекомендации
- Убедитесь, что поисковые роботы могут индексировать содержимое виджета
- Используйте правильный
altтекст и семантический HTML для информации о погоде - Рассмотрите реализацию серверного рендеринга для критического контента
Обновление кэша
function loadLanguageScript(language = 'en') {
const timestamp = new Date().getTime(); // Обновление кэша
const script = document.createElement('script');
script.src = `https://abomus.co.il/js/${language}-weather.js?t=${timestamp}`;
script.defer = true;
document.head.appendChild(script);
}
Обработка ошибок и резервные варианты
Надежная обработка ошибок
function loadLanguageScriptSafe(language = 'en') {
return new Promise((resolve, reject) => {
const existingScript = document.querySelector('script[src*="weather.js"]');
if (existingScript) {
existingScript.remove();
}
const script = document.createElement('script');
script.src = `https://abomus.co.il/js/${language}-weather.js`;
script.defer = true;
const timeout = setTimeout(() => {
script.remove();
reject(new Error('Таймаут загрузки скрипта'));
}, 10000); // 10 секунд таймаута
script.onload = () => {
clearTimeout(timeout);
resolve();
};
script.onerror = () => {
clearTimeout(timeout);
if (language !== 'en') {
console.log(`Переход на английский для ${language}`);
loadLanguageScriptSafe('en').then(resolve).catch(reject);
} else {
reject(new Error('Не удалось загрузить даже резервный скрипт'));
}
};
document.head.appendChild(script);
});
}
Стратегия резервирования
- Сначала пробуем запрошенный язык
- При неудаче переходим на английский
- Сообщаем пользователю о переходе на резервный вариант
- Логируем ошибки для отладки
Это комплексное решение предоставляет несколько подходов к динамической загрузке языковых JavaScript файлов на основе языка страницы, с надежной обработкой ошибок и оптимизациями производительности, подходящими для производственных многоязычных сайтов.
Источники
- Stack Overflow - How to dynamically load a JS file with language prefix on a multilingual website
- JavaScript Kit - Dynamically loading an external JavaScript or CSS file
- Educative.io - How to dynamically load a JS file in JavaScript
- Phrase - Node.js Tutorial on Creating a Multilingual Web App
- GitHub - jquery-lang-js
- Medium - Building a Multilingual Static Website
- Kirupa - Loading Script Files Dynamically
- GeeksforGeeks - How to Load External JS Scripts Dynamically in AngularJS
Заключение
Динамическая загрузка языковых JavaScript файлов на основе языка страницы является важной задачей для многоязычных сайтов с внешними виджетами, такими как компоненты погоды. Наиболее эффективный подход сочетает определение языка по шаблону URL с атрибутом HTML lang в качестве механизма резервирования.
Ключевые выводы:
- Используйте сопоставление шаблонов URL для определения основного языка (
/de/,/fr/,/pl/) - Реализуйте правильное удаление скриптов перед загрузкой новых для предотвращения конфликтов
- Добавьте обработку ошибок с переходом на английский язык для надежности
- Рассмотрите оптимизации производительности, такие как атрибуты
deferи обновление кэша - Реализуйте правильную обработку событий для завершения загрузки скрипта
Представленные решения варьируются от простых реализаций на чистом JavaScript до более продвинутых подходов на основе классов с комплексной обработкой ошибок. Выберите метод, который лучше всего соответствует сложности и требованиям вашего проекта, обеспечивая оптимальную производительность и пользовательский опыт для всех поддерживаемых языков.