Расширенные настройки
Вы можете редактировать дополнительные настройки, которые не доступны в пользовательском интерфейсе, на странице расширенных настроек -> Настройки разработчика -> User Config. Это предназначено для продвинутых пользователей. Подробное описание параметров см. в конце. Текущую конфигурацию config
можно найти здесь, нажав Click to expand the final config
.
Правила пользователя
С помощью Rules
можно настроить конкретные сайты, решить, какой контент должен быть переведен, или изменить стиль веб-страницы и т.д.
[
{
"matches": "www.google.com",
"selectors": [".title"]
},
{
"matches": "twitter.com",
"selectors": [".text"],
"excludeSelectors": ["nav", "footer"]
}
]
Используйте matches
для соответствия определенным сайтам. Допускаются подстановочные знаки, например, *.google.com
, www.google.com/test/*
, file://*
Использование selectors
переопределяет диапазон интеллектуального перевода, переводя только элементы, соответствующие этому селектору.
Использование excludeSelectors
позволяет исключить элементы, не переводя их.
Использование selectors.add
добавляет некоторые селекторы к стандартным.
Использование selectors.remove
уменьшает количество стандартных селекторов.
[
{
"matches": "www.google.com",
"selectors.add": ["baidu.com"],
"excludeSelectors": ["buzzing.cc"]
}
]
Если вы хотите перевести определенную область как единое целое, не разделяя ее на строки, можно использовать селектор atomicBlockSelectors
. Например, личный профиль в Instagram. Важно отметить, что перед использованием atomicBlockSelectors
необходимо сначала выбрать элементы с помощью selectors
.
{
"matches": "https://www.instagram.com/*",
"selectors": [
"div._aa_c h1",
"li._acaz div[role=\"menuitem\"]"
],
"atomicBlockSelectors": [
"div._aa_c h1",
"li._acaz div[role=\"menuitem\"]"
]
}
Если перевод вызывает смещение страницы, наложение текста и другие крайние случаи, можно использовать globalStyles
для корректировки стиля веб-страницы и исправления. Например, заголовки на YouTube, чтобы убрать максимальную высоту оригинальной страницы.
{
"matches": "www.google.com",
"globalStyles": { ".title": "max-height:unset;" }
}
Внедрённый CSS
С помощью внедрённого CSS можно глобально внедрять пользовательские стили веб-страниц. Можно использовать в сочетании с translationClasses
в Rules
.
.imt_wrapper img { width: 16px; height: 16px }
Также можно управлять стилями веб-сайтов, как это делается в обычных менеджерах стилей веб-страниц, для более персонализированного дизайна стилей. (Даже можно использовать display:none
для блокировки рекламы)
.title {
color: red;
}
Конфигурация пользователя
С помощью Config можно настроить параметры данного плагина, такие как сервис перевода, опции перевода для конкретных языков и т.д.
{
"translationService": "tencent",
"translationServices": {
"tencent": {
"secretId": "xxx",
"secretKey": "xxx",
"matches": ["twitter.com"]
}
},
"translationUrlPattern": {
"excludeMatches": ["www.google.com"]
},
"translationLanguagePattern": {
"matches": ["en"]
},
"translationTheme": "none",
"translationThemePatterns": {
"underline": {
"matches": ["discord.com"]
}
},
"sourceLanguageUrlPattern": {
"en": {
"matches": ["*.google.com"]
}
},
"generalRule": {
"_comment": "",
"normalizeBody": "",
"injectedCss": [],
"additionalInjectedCss": [],
"wrapperPrefix": "smart",
"wrapperSuffix": "smart",
"isPdf": false,
"isTransformPreTagNewLine": false,
"urlChangeDelay": 20,
"isShowUserscriptPagePopup": true,
"observeUrlChange": true,
"paragraphMinTextCount": 8,
"paragraphMinWordCount": 2,
"blockMinTextCount": 32,
"blockMinWordCount": 5,
"containerMinTextCount": 18,
"lineBreakMaxTextCount": 0,
"globalAttributes": {},
"globalStyles": {},
"selectors": [],
"preWhitespaceDetectedTags": ["DIV", "SPAN"],
"stayOriginalSelectors": [],
"additionalSelectors": [],
"atomicBlockTags": [],
"excludeSelectors": [],
"additionalExcludeSelectors": [],
"translationClasses": [],
"atomicBlockSelectors": [],
"excludeTags": [],
"metaTags": ["META", "SCRIPT", "STYLE", "NOSCRIPT"],
"additionalExcludeTags": [],
"stayOriginalTags": ["CODE", "TT", "IMG", "SUP"],
"additionalStayOriginalTags": [],
"inlineTags": [],
"additionalInlineTags": [],
"extraInlineSelectors": [],
"additionalInlineSelectors": [],
"extraBlockSelectors": [],
"allBlockTags": [],
"pdfNewParagraphLineHeight": 2.4,
"pdfNewParagraphIndent": 1.2,
"pdfNewParagraphIndentRightIndentPx": 130,
"fingerCountToToggleTranslagePageWhenTouching": 4
},
"rules": [
{
"matches": "www.google.com",
"selectors": [".class"]
}
]
}
В частности, поля правил в rules
могут использовать все поля из generalRule
. Rules
имеют наивысший приоритет, и когда правило соответствует определенному сайту, оно объединяет правила из generalRule
и этого конкретного правила.
Представляем некоторые общие поля в Config.
Разрешить рендеринг обычных HTML тегов
Перейдите в Настройки разработчика -> Изменить полную конфигурацию пользователя
Измените "enableRenderHtmlTag": true
Не отображать неконфигурированные службы перевода во всплывающем окне
"showUnconfiguredTranslationServiceInPopup": false
Конфигурация сервиса перевода
Используйте translationService
для выбора движка перевода по умолчанию. В настоящее время поддерживаются:
| "bing"
| "transmart"
| "google"
| "deepl"
| "openai"
| "gemini"
| "baidu"
| "volc"
| "youdao"
| "caiyun"
| "tencent"
| "openl"
Используйте translationServices
для настройки apikey
различных сервисов перевода. Разные провайдеры требуют различные параметры, и их API ключи могут быть получены на официальных сайтах в разделе для разработчиков.
Например, для использования Tencent Translator, необходимо настроить secretId
, secretKey
. Вы можете подать заявку на получение API ключа на Tencent Cloud, получая 5 миллионов символов бесплатно каждый месяц. Подробности процесса подачи заявки смотрите здесь
"translationServices": {
"tencent": {
"secretId": "xxx",
"secretKey": "xxx",
"matches":["twitter.com"],
"limit": 3,
"apiUrl":"",
"maxTextGroupLengthPerRequest": 25,
"maxTextLengthPerRequest": 1800
}
}
Поле matches
используется для указания конкретных сайтов, для которых будет использоваться данный сервис перевода.
Поле limit
указывает максимальное количество запросов в секунду для данного сервиса перевода (некоторые сервисы могут ограничивать максимальное количество запросов в секунду).
Поле maxTextGroupLengthPerRequest
указывает максимальное количество абзацев за один запрос.
Поле maxTextLengthPerRequest
указывает максимальное количество символов за один запрос.
apiUrl
позволяет настроить адрес интерфейса перевода.
Всегда переводить определенные сайты
translationUrlPattern
настройка для сайтов, которые всегда переводятся, и сайтов, которые никогда не переводятся.
matches
настраивает сайты, которые всегда переводятся,excludeMatches
настраивает сайты, которые никогда не переводятся.
Значение конфигурации может быть доменом или URL-адресом с *
, например: www.google.com/mail/*
"translationUrlPattern": {
"matches": ["stackoverflow.com"],
"excludeMatches": ["www.google.com/mail/*"]
}
Всегда переводить определенные языки
translationLanguagePattern
, настройка для языков, которые всегда переводятся, и языков, которые никогда не переводятся.
matches
настраивает языки, которые всегда переводятся, напримерen
,excludeMatches
настраивает языки, которые никогда не переводятся.
Формат отображения перевода
translationTheme
определяет формат отображения перевода. В настоящее время поддерживаются следующие стили:
| "none"
| "dashed"
| "dotted"
| "underline"
| "mask"
| "paper"
| "highlight"
| "blockquote"
| "weakening"
| "italic"
| "bold"
| "thinDashed";
Соответствующие названия на русском:
{
"none": "Нет",
"dashed": "Пунктирное подчеркивание",
"dotted": "Точечное подчеркивание",
"underline": "Прямое подчеркивание",
"mask": "Эффект размытия",
"paper": "Эффект тени бумаги",
"highlight": "Выделение",
"blockquote": "Стиль цитирования",
"weakening": "Ослабление",
"italic": "Курсив",
"bold": "Жирный",
"thinDashed": "Тонкое пунктирное подчеркивание"
}
translationThemePatterns
позволяет настраивать стили перевода для различных сайтов.
"translationThemePatterns": {
"underline": {
"matches": ["discord.com"]
}
}
Перевод сообщений потоковых страниц в стиле GPT
{
"matches": ["chat.openai.com"], // Адреса в стиле GPT
"excludeSelectors": [".markdown *"],
"aiRule": {
"streamingSelector": ".result-streaming.markdown",
"messageWrapperSelector": ".markdown",
"streamingChange": true
}
}
Правила
rules
является массивом объектов, который может быть настроен для определенных сайтов, например, чтобы Twitter переводил только определенную область:
{
"rules": [
{
"id": "twitter",
"matches": ["twitter.com", "mobile.twitter.com", "tweetdeck.twitter.com"],
"selectors": [
"[data-testid='tweetText']",
".tweet-text",
".js-quoted-tweet-text",
"[data-testid='card.layoutSmall.detail'] > div:nth-child(2)",
"[data-testid='developerBuiltCardContainer'] > div:nth-child(2)",
"[data-testid='card.layoutLarge.detail'] > div:nth-child(2)"
],
"extraInlineSelectors": ["[data-testid=\"tweetText\"] div"]
}
]
}
Текущие встроенные rules
можно найти здесь.
Ниже приведены некоторые важные поля для объяснения:
export interface Rule {
// Соответствие сайтам
id?: string; // Каждое правило адаптации системы имеет свой собственный идентификатор. Если пользователь хочет повторно использовать это правило с изменениями, он может добавить этот идентификатор к своему правилу для повторного использования.
matches?: string | string[]; // Это правило будет соответствовать только указанным сайтам.
excludeMatches?: string | string[]; // Исключает определенные сайты.
selectorMatches?: string | string[]; // Соответствие с использованием селекторов, без необходимости указывать все URL.
excludeSelectorMatches?: string | string[]; // Исключение правил, аналогично вышеуказанному.
// Указание диапазона перевода
selectors?: string | string[]; // Переводить только соответствующие элементы.
excludeSelectors?: string | string[]; // Исключить элементы, не переводить соответствующие элементы.
excludeTags?: string | string[]; // Исключить теги, не переводить соответствующие теги.
// Добавление диапазона перевода, а не замена
additionalSelectors?: string | string[]; // Добавить диапазон перевода. В области интеллектуального перевода добавить места для перевода.
additionalExcludeSelectors?: string | string[]; // Добавить исключаемые элементы, чтобы интеллектуальный перевод не переводил определенные места.
additionalExcludeTags?: string | string[]; // Добавить исключаемые теги.
// Сохранение оригинала
stayOriginalSelectors?: string | string[]; // Соответствующие элементы будут сохранены в оригинале. Часто используется для тегов форумов.
stayOriginalTags?: string | string[]; // Соответствующие теги будут сохранены в оригинале, например, `code`.
// Перевод области
atomicBlockSelectors?: string | string[]; // Селекторы области, соответствующие элементы будут рассматриваться как единое целое и не будут переведены по частям.
atomicBlockTags?: string | string[]; // Селекторы блочных тегов, аналогично выше
// Блок или строчный элемент
extraBlockSelectors?: string | string[]; // Дополнительные селекторы, соответствующие элементы будут обрабатываться как блочные элементы, занимая отдельную строку.
extraInlineSelectors?: string | string[]; // Дополнительные селекторы, соответствующие элементы будут обрабатываться как строчные элементы.
inlineTags?: string | string[]; // Соответствующие теги будут обрабатываться как строчные элементы
preWhitespaceDetectedTags?: string | string[]; // Соответствующие теги будут автоматически переноситься на новую строку
// Стили перевода
translationClasses?: string | string | string[]; // Добавить дополнительные классы к переводу
// Глобальные стили
globalStyles?: Record<string, string>; // Изменить стили страницы, полезно если перевод вызывает нарушение верстки.
globalAttributes?: Record<string, Record<string, string>>; // Изменить атрибуты элементов страницы
// Встроенные стили
injectedCss?: string | string[]; // Встроенные CSS стили
additionalInjectedCss?: string | string[]; // Дополнительные CSS стили, не заменяя существующие напрямую.
// Контекст
wrapperPrefix?: string; // Префикс области перевода, по умолчанию smart, решает переносить строку или нет в зависимости от количества символов.
wrapperSuffix?: string; // Суффикс области перевода
// Минимальное количество символов для перевода в блок
blockMinTextCount?: number; // Минимальное количество символов, чтобы обрабатывать перевод как блочный элемент, иначе как строчный.
blockMinWordCount?: number; // Аналогично выше. Если вы хотите, чтобы они всегда переносились, можно установить 0.
// Минимальное количество символов для перевода содержимого
containerMinTextCount?: number; // При интеллектуальном распознавании, минимальное количество символов в элементе для его перевода, по умолчанию 18
paragraphMinTextCount?: number; // Минимальное количество символов в исходном абзаце, содержимое больше этого числа будет переведено
paragraphMinWordCount?: number; // Минимальное количество слов в исходном абзаце
// Принудительный перенос длинных абзацев
lineBreakMaxTextCount?: number; // При включении перевода длинных абзацев, максимальное количество символов для принудительного переноса строки.
// Время запуска перевода
urlChangeDelay?: number; // Задержка в миллисекундах перед началом перевода после входа на страницу. Для ожидания инициализации страницы, по умолчанию 250 мс
observeUrlChange?: boolean; // Отслеживание изменений URL адреса для повторного запуска перевода, по умолчанию true.
// Мобильные устройства
isShowUserscriptPagePopup?: boolean; // Показывать всплывающее окно на странице на мобильных устройствах, по умолчанию true.
fingerCountToToggleTranslagePageWhenTouching?: number; // Перевод при касании четырьмя пальцами, можно установить 0, 2, 3, 4, 5
// AI streaming перевод
aiRule: {
streamingSelector: string; // Селектор для отметки элементов, переводимых в реальном времени на страницах gpt
messageWrapperSelector: string; // Селектор для обертки сообщений
streamingChange: boolean; // Обновляются ли сообщения на страницах типа gpt инкрементально или полностью. Для gpt это инкрементальное обновление.
};
}
Практика продвинутых настроек
Полезные советы
В этом разделе будут представлены некоторые готовые к использованию настройки.
Просто скопируйте эти настройки одним кликом, откройте настройки разработчика, разверните Edit Full User Config
и скопируйте их в последний пункт. Не забудьте добавить запятую к предыдущему пункту и не добавлять запятую к последнему пункту.
Слишком много неработающих служб перевода, как показать только работающие службы перевода в панели плагина
"showUnconfiguredTranslationServiceInPopup": false
Как настроить использование различных сервисов перевода для разных сайтов по умолчанию? Например, для некоторых сайтов я хочу использовать качественный, но платный сервис перевода, а для других мне достаточно бесплатного перевода, который просто позволяет понять смысл.
Обратите внимание, эта настройка называется сервис перевода. Здесь настроен Google Переводчик для перевода всех связанных с Twitter сайтов, поскольку перевод от Google бесплатен, а Twitter используется для серфинга, главное — понять общий смысл.
Внимательно посмотрите, здесь также настроен сервис перевода от deepl
для специализированного перевода сайтов с низкой допустимой погрешностью, требующих высокой точности, например, академических сайтов типа scihub
"translationServices": {
"google": {
"matches":["https://twitter.com"]
},
"deepl": {
"matches":["https://www.sci-hub.se"]
}
}
⚠️ Обратите внимание, если вы хотите перевести все сайты в одном домене, использование .twitter.com или https://twitter.com/ будет неэффективным. Правильный подход должен соответствовать примеру, указанному выше. Это связано с тем, что .twitter.com может совпадать только с поддоменами, например, xxx.twitter.com, но не включает сам домен верхнего уровня.
Примеры адаптации сайтов
В этом разделе мы рассмотрим некоторые правила
для популярных сайтов, используемые нашим плагином, чтобы понять принципы работы продвинутых настроек на практических примерах. Для краткости здесь будут представлены только самые используемые поля, такие как selectors
, excludeSelectors
и т.д. Если вам интересна эта тема, пожалуйста, свяжитесь с нами, и мы продолжим обновлять соответствующий контент.
Перед началом важно понимать принцип работы плагина для погружающегося перевода, который также является принципом работы самого плагина. Для этого необходимо иметь базовые знания HTML
, CSS
, JavaScript
, которые можно изучить на сайте MDN
. Хорошо, не будем терять время, давайте глубже познакомимся с механизмом работы плагина для погружающегося перевода. Вкратце, его работа заключается во внедрении сторонних скриптов в веб-страницу, которые могут достаточно свободно изменять структуру, стиль и даже поведение веб-страницы.
Наш плагин для погружающегося перевода не исключение, давайте кратко рассмотрим, что он делает:
- Получает набор элементов для перевода
- Переводит текст в этих элементах
- Вставляет результат перевода обратно в набор элементов
Однако, если подумать подробнее, возникают два вопроса:
- Нам нужно определить, какие элементы требуют перевода, чтобы не нарушать погружающийся опыт пользователя, например, простые и понятные кнопки или панель навигации.
- Вставка результатов перевода в набор элементов также представляет новый вызов: как обеспечить, чтобы результаты вставки соответствовали оригинальной веб-странице и не влияли на её стиль.
Суть наших Правил
заключается в решении вышеупомянутых проблем. Так как плагин для погружающегося перевода сталкивается со всеми веб-страницами на рынке, их количество может достигать сотен тысяч, а то и миллионов, а структура страниц и используемые технологии могут сильно отличаться. Из-за различий в веб-страницах почти невозможно найти универсальную логику, которая подошла бы для адаптации всех сайтов. Похоже, что единственным решением является индивидуальная адаптация каждого сайта. Далее, для упрощения адаптации, мы используем концепцию конфигурации как кода, превращая работу по адаптации в задачу настройки полей. Ещё одно преимущество этого подхода заключается в том, что пользователи могут участвовать в процессе адаптации.
При настройке лучше не использовать следующие поля напрямую, так как это может перезаписать существующие настройки. Вместо этого используйте поля selector.add
, excludeSelector.add
для модификации на основе существующих настроек.
Теперь мы рассмотрим работу погружающегося перевода на примере сайта
Ниже приведены Правила
для Twitter. Для краткости мы сосредоточимся на нескольких ключевых полях, остальные поля можно понять, соотнеся их с вышеупомянутыми Правилами
[
{
"id": "twitter",
"matches": [
"twitter.com",
"mobile.twitter.com",
"tweetdeck.twitter.com",
"pro.twitter.com",
"https://platform.twitter.com/embed*"
],
"selectors": [
// Элементы для перевода, будут переведены только элементы, соответствующие селекторам
"[data-testid=\"tweetText\"]",
".tweet-text",
".js-quoted-tweet-text",
"[data-testid='card.layoutSmall.detail'] > div:nth-child(2)",
"[data-testid='developerBuiltCardContainer'] > div:nth-child(2)",
"[data-testid='card.layoutLarge.detail'] > div:nth-child(2)",
"[data-testid='cellInnerDiv'] div[data-testid='UserCell'] > div> div:nth-child(2)",
"[data-testid='UserDescription']",
"[data-testid='HoverCard'] div[dir=auto]",
"[data-testid='HoverCard'] span[dir=auto]",
"[data-testid='HoverCard'] [role='dialog'] div[dir=ltr]",
"[data-testid='birdwatch-pivot'] div[dir=ltr]"
],
"excludeSelectors": [
// Элементы, которые не будут переведены, выбранные CSS-селекторами
"[aria-describedby][role=button]",
"header",
"[data-testid='radioGroupplayback_rate'] div",
"[data-testid='userFollowIndicator']",
"[class='css-901oao r-14j79pv r-37j5jr r-n6v787 r-16dba41 r-1cwl3u0 r-bcqeeo r-qvutc0']",
"[class='css-175oi2r r-1wbh5a2 r-dnmrzs']"
],
"globalStyles": {
// Глобальные стили, принудительно перекрывающие оригинальные стили
"[data-testid='card.layoutLarge.detail'] > div:nth-child(2)": "-webkit-line-clamp: unset;",
"[data-testid='card.layoutSmall.detail'] > div:nth-child(2)": "-webkit-line-clamp: unset;",
"[data-testid='tweetText']": "-webkit-line-clamp: unset;"
}
}
]
selector
: Указывает набор элементов для переводаЗачем нужно это поле
- Потому что не все элементы содержат текст, который нуждается в переводе, предоставление такого поля может гарантировать производительность и обеспечить погруженный опыт пользователя
Пример
- В Твиттере, если мы не укажем selector, тогда он будет переводить весь текст на странице, распознанный как английский, как показано на рисунке ниже, никнеймы пользователей обычно не требуют перевода.
Значение поля
"selectors": [ // Набор CSS-селекторов для перевода
"[data-testid=\"tweetText\"]",
]
Каждый элемент массива - это CSS-селектор, который выбирает элементы на странице, требующие перевода. В качестве примера, первый селектор выбирает все элементы твитов, как показано на рисунке ниже.
excludeSelectors
: Набор элементов, которые не будут переведеныЗачем нужно это поле
- Потому что одного селектора для перевода может быть недостаточно, могут возникнуть ситуации, когда выбранный элемент не требует перевода, то есть могут быть перекрытия, поэтому необходимо установить дополнительное поле для исключения элементов, не требующих перевода
- Учитывая сложность структуры страницы, предоставление двух таких параметров делает конфигурацию более гибкой
- Связанный приоритет: для одинаковых селекторов, selectors > excludeSelectors, остальное зависит от приоритета CSS
Значение поля
"excludeSelectors": [ // Элементы, выбранные CSS-селектором, которые не будут переведены
"[aria-describedby][role=button]",
],
В качестве примера, здесь мы исключаем кнопку подписки из перевода.
globalStyles
: Добавление глобальных стилей, принудительное переопределение исходных стилейЗачем нужно это поле
- В некоторых случаях из-за исходных CSS-стилей веб-страницы, результаты перевода могут выглядеть не очень хорошо, возникают проблемы с обрезкой текста, отсутствием переносов и т.д.
- С помощью этого поля предоставляется радикальное решение, позволяющее напрямую изменить CSS-свойства исходной веб-страницы для решения проблемы
Значение поля
"globalStyles": {
// Глобальные стили, принудительное переопределение исходных стилей
"[data-testid='card.layoutLarge.detail'] > div:nth-child(2)": "-webkit-line-clamp: unset;",
"[data-testid='card.layoutSmall.detail'] > div:nth-child(2)": "-webkit-line-clamp: unset;",
"[data-testid='tweetText']": "-webkit-line-clamp: unset;"
}
Свойство -webkit-line-clamp
используется для контроля количества отображаемых строк, лишние строки будут обрезаны. Здесь, установив его в unset
, можно гарантировать, что переведенный текст не будет обрезан этим свойством.
Настройка адаптации сайта
Что касается правил адаптации, вы также можете создавать собственные правила. Перейдите на страницу опций плагина и кликните на настройки разработчика, разверните Edit User Rules
, где вы можете настроить адаптацию для различных сайтов. Ниже приведено объяснение на примере конкретного правила.
[
{
"selectors.remove": [
"[data-testid=\"tweetText\"]"
],
"selectors.add": [
""
],
"excludeSelectors.add":[
""
],
"excludeSelectors.remove":[
""
],
"id": "twitter"
}
]
Это правило предотвращает перевод твитов на странице Twitter. Ниже подробно описано значение каждого поля.
id
- это набор сайтов, которые уже определены в иммерсивном переводе, каждый id
соответствует определенному сайту. Использование id
имеет два преимущества:
- Использование
id
позволяет наследовать правила адаптации, созданные ранее в иммерсивном переводе, и пользователи могут на их основе добавлять или удалять настройки. - Использование
id
избавляет от необходимости вводить сложные сопоставляющие поля.
Ниже приведены некоторые общие id
встроенных сервисов иммерсивного перевода:
"isEbook"
- настройка страницы чтения epub."isEbookBuilder"
- настройка страницы создания двуязычных книг epub."pdf"
- настройка страницы перевода pdf с двуязычным сопоставлением.
Полный набор id
можно найти в настройках разработчика, кликнув на Click to expand the final config
.
selectors
отвечает за указание CSS-селекторов, которые нужно перевести. Рекомендуется использовать подпункты .add
и .remove
для добавления или удаления на основе существующих настроек.
excludeSelectors
отвечает за исключение CSS-селекторов, которые не нужно переводить. Рекомендуется использовать подпункты .add
и .remove
для добавления или удаления на основе существующих настроек.
Дополнительные объяснения
Разница между блочными (block) и строчными (inline) элементами, если вы хотите узнать больше, можете прочитать здесь.
- Блочные элементы занимают отдельную строку, и каждый новый блочный элемент начинается с новой строки.
- Строчные элементы не занимают отдельную строку, и несколько соседних строчных элементов будут располагаться в одной строке до тех пор, пока в ней хватает места, после чего начнется новая строка.