Как поддерживать изменяющееся состояние языка в expressJS

Я работаю над проектом с использованием nodeJs, handlebars и expressJs framework. Я добавляю функцию изменения языка с помощью модуля i18n-экспресс. Этот модуль добавляет строку запроса в конец URL-адреса, когда мы собираемся изменить язык. Теперь проблема в том, что когда я перемещаю одну страницу на другую, строка запроса удаляется и теряет свое состояние. Итак, как я могу поддерживать состояние языка? если пользователь выбирает французский язык, то все страницы открываются на французском. Это то, что я хочу.

Код:

var i18n =  require("i18n-express");

app.use(i18n({
  translationsPath: path.join(__dirname, 'lang'), // <--- use here. Specify translations files path.
  siteLangs: ["ar","en","cn","fr","ge","he","hu","it","ja","ko","es","ru"],
  cookieLangName : 'ulang',
  textsVarName: 'translation'  
}));

Ссылка на смену языка

<a href = "#!" id = "{{icon}}" onclick = " return changeLanguage(this)"></a>

Функция Onclick для изменения языка

function changeLanguage(event){
   $('#languages img').attr('src','/images/flag-icons/'+event.id+'.png');
   var url = window.location.href;
   url = url.split("?")[0];
   url += '?clang='+event.id;
   window.location.href = url;
   localStorage.setItem("clang", '?clang='+event.id); //event.id returns locale name such as en, ar, sp, fr etc.
   //console.info(url);
}

Можете ли вы создать минимальный пример проблемы «двойного обновления», с которой вы столкнулись (из решения ниже), в коды?

ugh StackExchange 15.10.2018 08:44
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
11
1
2 632
4

Ответы 4

На стороне клиента, если вы можете установить элемент в локальном хранилище, вы также можете получить тот же элемент и использовать его значение, чтобы отправить его в строку запроса. Таким образом, вам в основном нужна дополнительная функция на вашем клиентском javascript, которая будет получать элемент каждый раз при открытии страницы.

    function getParameterByName(name, url) {
        if (!url) url = window.location.href;
        name = name.replace(/[\[\]]/g, '\\$&');
        var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
            results = regex.exec(url);
        if (!results) return null;
        if (!results[2]) return '';
        return decodeURIComponent(results[2].replace(/\+/g, ' '));
    }

    function checkLanguageFromLocalStorage(){
        var clang = getParameterByName('clang');
        if (clang == null) {
            if (localStorage.getItem("clang") != null) {
                var clang = localStorage.getItem("clang");
                var url = window.location.href;
                url = url.split("?")[0];
                url += '?clang='+clang;
                window.location.href = url;
            }
        }
    }

    checkLanguageFromLocalStorage();

Я пробовал это, но он загружает страницу два раза. есть идеи по этому поводу?

Varinder Sohal 11.10.2018 10:47

Основываясь на этом ответе ссылка, вы можете добавить дополнительную проверку в свой элемент управления, чтобы узнать, установлен ли clang уже в строке запроса, чтобы не обновлять страницу, если она уже настроена. Я изменил ответ этой проверкой.

Gianpaolo Papa 15.10.2018 02:32

Рекомендую Lingua для ExpressJS

По сути, Lingua - это промежуточное ПО для Express.js, которое помогает легко интернационализировать ваше веб-приложение. Он определяет язык пользовательского агента и передает ресурсы i18n вашим представлениям.

$ npm install -s lingua

var express = require('express'),
    lingua  = require('lingua');

// Express app configuration code and lingua init.
app.configure(function() {

app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');

// Lingua configuration
app.use(lingua(app, {
    defaultLocale: 'en',
    path: __dirname + '/i18n'
}));

app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
app.use(app.router);

Языковые файлы

'./i18n/en.json' and './i18n/de-de.json').

// en.json
    {
        "title": "Hello World",
        "content": {
            "description": "A little description."
        }
    }

// de-de.json
    {
        "title": "Hallo Welt",
        "content": {
            "description": "Eine kleine Beschreibung."
        }
    }

И вы можете легко реализовать это на своих страницах с помощью:

<h1><%= lingua.title %></h1> <!-- out: <h1>Hello World</h1> -->
<p><%= lingua.content.description %></h1> <!-- out: <p>A little description.</p> -->

Вдруг на этой странице нет @types для программирования TypeScript.

8Observer8 03.12.2019 15:02

Почему бы вам не передать cookie с языком вместо параметра запроса? i18n-express имеет вариант под названием cookieLangName, который вы уже настроили на стороне сервера (cookieLangName: 'ulang'). Установка cookieLangName заставляет i18n-express читать язык из файла cookie с указанным вами именем. Все, что вам нужно, это установить этот файл cookie в своем клиентском скрипте - внутри функции changeLanguage - и он сделает свое дело:

function changeLanguage(event){
   $('#languages img').attr('src','/images/flag-icons/'+event.id+'.png');
   document.cookie = `ulang=${event.id}; path=/`;

   localStorage.setItem("ulang", `ulang=${event.id}; path=/`); // you can still save it to localStorage and synchronize it when cookie is removed
}

Насколько я понимаю, требование сводится к следующему:

Если конечный пользователь выбрал язык, выбор всегда должен быть прозрачным в URL-адресе, чтобы обеспечить правильное функционирование модуля перевода. Выполнение этого требования не должно вызывать ненужную перезагрузку страницы. Однако в рамках этого вопроса игнорируется тот факт, что при холодном запуске, когда clang=xx не существует, для загрузки правильного контента потребуется ручное перенаправление, поскольку предыдущий выбор пользователя известен только клиенту.

Судя по опубликованному вами фрагменту, вы почти у цели. Функция changeLanguage корректно загружает контент на выбранном языке. Если бы я проводил обзор кода, я бы попросил внести несколько изменений в следующий результат:

Исправленный HTML

<a href = "#!" id = "{{icon}}" onclick = "return loadContentInSelectedLanguage(this.id)"></a>

Патченный JS:

function processLanguageSelection(selectedLang) {

  highlightCurrentlySelectedLang(selectedLang);
  saveSelectedLangAcrossSession("clang", selectedLang);

  reloadContentInSelectedLang(selectedLang);
}

function highlightCurrentlySelectedLanguage(selectedLang) {
  $('#languages img').attr('src', '/images/flag-icons/' + selectedLang + '.png');
}

function saveSelectedLangAcrossSession(entryKey, selectedLang) {
  window.localStorage.setItem(entryKey, selectedLang);
}

function reloadContentInSelectedLang(selectedLang) {
  var search = window.location.search || "?";

  if (/clang=\w{2}/.test(search)) {
    search = search.replace(/clang=\w{2}/, "clang = " + selectedLang);
  } else {
    search += ("?" === search ? "clang = " : "&clang = ") + selectedLang;
  }

  window.history.replaceState(null, "", search);
  window.location.reload();
}

Ты почти там, как я уже сказал. Итак, что осталось получить в конечном итоге? - Недостаток заключается в следующем: предыдущий выбор пользователя должен применяться только тогда, когда страница начинает загружаться. И любое необходимое перенаправление должно выполняться как можно раньше, прежде чем браузер начнет обрабатывать тело документа. Естественно, это означает, что часть ваших скриптов, отвечающая за эту ответственность, должна быть первой, что запускается внутри раздела <head>...</head>.

<head>
  <script>
    (function() {
      var previouslySelectedLanguage = window.localStorage.getItem("clang");

      if (/clang=\w{2}/.test(window.location.search)) {
        // correct content should have been loaded in this case
        // otherwise the server needs fixing, but that's not
        // in the scope of this question.

        // determine selectedLang from window.location.search, then..
        highlightCurrentlySelectedLanguage(selectedLang);

        if (!previouslySelectedLanguage || "selectedLang" !== previouslySelectedLanguage) {
          saveSelectedLangAcrossSession("clang", selectedLang);
        }

        return;
      }

      if (previouslySelectedLanguage) {
        // redirect
        reloadContentInSelectedLang(previouslySelectedLanguage);
      }
    })();

  </script>
</head>

Обратите внимание, что примеры, предлагаемые в этом ответе, не готовы к производству. Проявите должную осмотрительность, убедившись, что они надежны, устойчивы и соответствуют другим стандартам, необходимым в вашей организации. Например, это регулярное выражение /clang=\w{2}/ делает смелое предположение, которое не всегда может быть правдой.

Другие вопросы по теме