PageSourceSearch

https://bluesdoctors.ru/design/bd/js/i18n.js?v=1787641206

js bluesdoctors.ru collected 2026-10-08 00:00:04 UTC 6,915 bytes, 133 lines download raw bytes

1/* Переключатель RU/EN.
2
3   В вёрстке словарь был зашит константой прямо в скрипт. Здесь он приезжает
4   из базы (таблица s_translations, экран админки «Переводы») и кладётся
5   шаблоном index.tpl в window.BD_I18N — иначе менеджер не смог бы поменять
6   ни одну строку шапки без правки файла темы.
7
8   Ключ без EN-перевода намеренно НЕ подменяется: элемент остаётся с русским
9   текстом из разметки. Пустая строка в словаре означала бы пустое место
10   на английской версии.
11
12   ВИДЫ ПОМЕТОК:
13     data-i18n       — подменяется textContent в любом языке;
14     data-i18n-html  — то же, но значением с html-тегами (innerHTML);
15     data-i18n-en    — подменяется ТОЛЬКО в EN. Так помечено то, чей русский
16                       текст приходит из настроек админки: иначе словарь
17                       затирал бы значение настройки при каждой загрузке;
18     data-i18n-attr  — подменяются АТРИБУТЫ. Значение — список пар
19                       «атрибут:ключ» через запятую:
20                         data-i18n-attr="placeholder:ph_name"
21                         data-i18n-attr="aria-label:a11y_open_photo"
22                       Нужно для placeholder полей формы и aria-label кнопок
23                       (лайтбокс, закрытие модалки, листалка): их текст виден
24                       или слышен посетителю, а textContent у таких элементов
25                       нет. Имена атрибутов берутся ТОЛЬКО из разметки, не из
26                       словаря — иначе строка из админки могла бы подставить
27                       href или on*.
28
29   ДАТЫ. Названия месяцев приходят с сервера уже по-русски (api/Events.php
30   их не переводит: контент сущностей на сайте не переводится). Поэтому
31   шаблоны оборачивают месяц в элемент с data-i18n="month_full_10" —
32   и в EN-режиме он подменяется как обычная строка словаря.
33*/
34(function(){
35
36  var T = window.BD_I18N || {};
37
38  if(!T.ru) T.ru = {};
39  if(!T.en) T.en = {};
40
41  var buttons = document.querySelectorAll('.lang-switch__btn');
42
43  // Исходная (русская) разметка — источник истины для ключей без перевода.
44  var fallback = new WeakMap();
45  var attrFallback = new WeakMap();
46
47  function remember(el, html){
48    if(!fallback.has(el)) fallback.set(el, html);
49    return fallback.get(el);
50  }
51
52  function rememberAttr(el, attr, value){
53    var map = attrFallback.get(el);
54    if(!map){ map = {}; attrFallback.set(el, map); }
55    if(!(attr in map)) map[attr] = value;
56    return map[attr];
57  }
58
59  function setLang(lang){
60
61    var d = T[lang] || T.ru;
62
63    document.documentElement.lang = lang;
64
65    /* og:locale держим согласованным с lang. Для соцсетей это мало что даёт:
66       краулер читает серверный HTML, а он всегда русский. Но противоречие
67       внутри отрисованной страницы («lang=en» при «og:locale=ru_RU») лучше
68       не оставлять. */
69    var locale = document.querySelector('meta[property="og:locale"]');
70    if(locale) locale.setAttribute('content', lang === 'en' ? 'en_US' : 'ru_RU');
71
72    document.querySelectorAll('[data-i18n]').forEach(function(el){
73      var base = remember(el, el.textContent);
74      var k = el.dataset.i18n;
75      el.textContent = (d[k] != null && d[k] !== '') ? d[k] : base;
76    });
77
78    document.querySelectorAll('[data-i18n-html]').forEach(function(el){
79      var base = remember(el, el.innerHTML);
80      var k = el.dataset.i18nHtml;
81      el.innerHTML = (d[k] != null && d[k] !== '') ? d[k] : base;
82    });
83
84    /* data-i18n-en — «переводить, но не подменять по-русски».
85       Так помечены элементы, чей русский текст приходит из настроек админки
86       (город группы, год начала). С обычным data-i18n переключатель при
87       загрузке страницы затирал бы значение настройки строкой из словаря,
88       и менеджер никогда не увидел бы своей правки. В EN-режиме перевод
89       нужен, поэтому здесь он применяется, а при возврате на RU
90       восстанавливается исходная разметка. */
91    document.querySelectorAll('[data-i18n-en]').forEach(function(el){
92      var base = remember(el, el.textContent);
93      var k = el.dataset.i18nEn;
94      var t = (T.en || {})[k];
95      el.textContent = (lang !== 'ru' && t != null && t !== '') ? t : base;
96    });
97
98    /* Атрибуты: placeholder, aria-label, title, alt. Раньше они оставались
99       русскими при любом языке — переключатель работал только с текстом
100       элементов, и в EN-версии подсказки в полях формы и подписи для
101       скринридера были на русском. */
102    document.querySelectorAll('[data-i18n-attr]').forEach(function(el){
103
104      el.dataset.i18nAttr.split(',').forEach(function(pair){
105
106        var parts = pair.split(':');
107        if(parts.length < 2) return;
108
109        var attr = parts[0].trim();
110        var key  = parts[1].trim();
111        if(!attr || !key) return;
112
113        var base = rememberAttr(el, attr, el.getAttribute(attr) || '');
114        el.setAttribute(attr, (d[key] != null && d[key] !== '') ? d[key] : base);
115      });
116    });
117
118    buttons.forEach(function(b){
119      b.classList.toggle('is-active', b.dataset.lang === lang);
120    });
121
122    try { localStorage.setItem('bd-lang', lang); } catch(e) {}
123  }
124
125  buttons.forEach(function(b){
126    b.addEventListener('click', function(){ setLang(b.dataset.lang); });
127  });
128
129  var initial = 'ru';
130  try { initial = localStorage.getItem('bd-lang') || 'ru'; } catch(e) {}
131
132  setLang(initial);
133})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.