# -*- coding: utf-8 -*-
#
# Isoliner - грид и изолинии (QGIS).
# © 2026 ООО «Информ++» (www.informpp.ru).
# SPDX-License-Identifier: GPL-2.0-or-later
#
"""Двуязычие интерфейса (RU/EN).

Простой словарный слой: исходные строки в коде - русские, при английской
локали QGIS они подменяются на английские по таблице TRANSLATIONS. Если
перевода нет, возвращается исходная (русская) строка - плагин остаётся
рабочим. Модуль не импортирует QGIS на верхнем уровне, поэтому таблицу
переводов можно проверять обычным Python (см. tests/test_i18n.py).

Язык определяется по настройкам QGIS один раз, лениво, при первом вызове tr().
Для тестов и принудительного переключения есть set_language().
"""

_LANG = None  # 'ru' | 'en' (None = ещё не определён)


def set_language(lang):
    """Принудительно задать язык ('ru'/'en'/'en_US'/...). None - сбросить."""
    global _LANG
    if lang is None:
        _LANG = None
        return
    code = str(lang).strip().lower().replace("-", "_").split("_")[0]
    _LANG = "ru" if code == "ru" else "en"


def language():
    """Текущий язык ('ru'/'en'); инициализирует по QGIS при необходимости."""
    if _LANG is None:
        init_from_qgis()
    return _LANG or "en"


def init_from_qgis():
    """Определить язык интерфейса по настройкам QGIS. По умолчанию 'en'."""
    loc = ""
    try:
        from qgis.core import QgsApplication
        loc = QgsApplication.instance().locale() or ""
    except Exception:
        loc = ""
    if not loc:
        try:
            from qgis.PyQt.QtCore import QSettings
            s = QSettings()
            override = s.value("locale/overrideFlag", False, type=bool)
            loc = s.value("locale/userLocale", "") if override else ""
        except Exception:
            loc = ""
    set_language(loc or "en")
    return _LANG


def tr(s):
    """Перевести строку s на активный язык. RU - исходник, EN - по таблице."""
    if _LANG is None:
        init_from_qgis()
    if _LANG == "en":
        return TRANSLATIONS.get(s, s)
    return s


def missing_keys(keys):
    """Какие из переданных русских строк не имеют английского перевода.

    Удобно для теста покрытия: keys - множество строк, реально обёрнутых в
    _tr()/tr() в коде (извлекается AST-обходом)."""
    return [k for k in keys if k not in TRANSLATIONS]


# --- Таблица переводов RU -> EN -------------------------------------------
# Ключ - русская строка ровно как в коде (включая %d/%s, переносы, символы).
# Значение - английский перевод. Покрывает статический интерфейс:
# имена инструментов, подписи параметров, варианты списков, панели справки,
# живые подписи виджетов. Логи и HTML-отчёты переводятся отдельным проходом.

TRANSLATIONS = {
    'Размер ячейки (0 = авто, min(охват)/50)': 'Cell size (0 = auto, min(extent)/50)',
    '1. 2D Kriging (точки → растр)': '1. 2D Kriging (points → raster)',
    '2. Изолинии из растра': '2. Isolines from raster',
    '5. Кросс-валидация вариограммы': '5. Variogram cross-validation',
    'Грид и изолинии': 'Grid and isolines',
    '6. Создать пример скважин (демо)': '6. Create sample wells (demo)',
    '3. Вариограмма (экспериментальная)': '3. Variogram (experimental)',
    '7. Профили обработки': '7. Processing profiles',
    '4. Вариограммная карта (анизотропия)': '4. Variogram map (anisotropy)',
    'Тип кригинга': 'Kriging type',
    'Радиус поиска (0 = вся выборка)': 'Search radius (0 = whole sample)',
    'Мин. число точек': 'Min. number of points',
    'Макс. число точек': 'Max. number of points',
    'Охват растра (по умолчанию - по слою)': 'Raster extent (default - by layer)',
    'Обрезать по контуру скважин (выпуклая оболочка)': 'Clip to well hull (convex hull)',
    'Буфер оболочки, ед. карты': 'Hull buffer, map units',
    'Маска обрезки (полигон из проекта) - приоритетнее оболочки': 'Clip mask (polygon from project) - takes priority over the hull',
    'Структура %d': 'Structure %d',
    'порог/вклад C': 'sill/contribution C',
    'порог/вклад C (0 = выкл.)': 'sill/contribution C (0 = off)',
    'Шаг изолиний (0 = задать уровни ниже)': 'Isoline step (0 = set levels below)',
    'Начальный уровень (offset)': 'Base level (offset)',
    'Явные уровни (через пробел) - приоритетнее шага': 'Explicit levels (space-separated) - take priority over step',
    'Главная изолиния каждая N-я (0 = выкл.)': 'Index isoline every N-th (0 = off)',
    'Мин. длина линии, ед. карты (0 = без фильтра)': 'Min. line length, map units (0 = no filter)',
    'Бикубическое сглаживание изолиний (сгущение грида)': 'Bicubic isoline smoothing (grid densification)',
    'Скругление линий (Chaikin), итераций (0 = выкл.)': 'Line rounding (Chaikin), iterations (0 = off)',
    'Имя поля значения': 'Value field name',
    'Стандартная ошибка кригинга': 'Kriging standard error',
    'Необязательный растр стандартной ошибки кригинга (sqrt дисперсии ошибки): мера неопределённости оценки. Мала у скважин, растёт вдали от данных.': 'Optional kriging standard-error raster (sqrt of error variance): a measure of estimate uncertainty. Small near wells, grows away from data.',
    'Скользящий контроль (leave-one-out): каждая скважина по очереди исключается, её значение предсказывается кригингом по остальным, и сравнивается с фактическим. Помогает подобрать вариограмму (наггет, радиус, модель) по ошибке, а не на глаз.\n\nВ Журнал выводятся метрики: ME (смещение, к 0), RMSE (меньше - лучше), MSDR (к 1 - вариограмма адекватна по масштабу), R. Перебирайте параметры и сравнивайте RMSE и MSDR.\n\nСлой остатков (опц.) - точки со следующими полями:\n  • <номер скважины> - если задано «Поле номера скважины»;\n  • <имя проверяемого поля> - фактическое значение (факт);\n  • z_est - оценка кригинга по остальным точкам (LOO);\n  • error - оценка минус факт (минус: занижено, плюс: завышено);\n  • abs_error - модуль ошибки;\n  • std_resid - стандартизованный остаток: error / стандартную ошибку кригинга, со знаком (это не дисперсия).\nПо нему видно, где модель промахивается.\n\nHTML-отчёт (по умолчанию) открывается в просмотрщике результатов: интерактивный график «оценка vs факт», гистограмма ошибок и таблица метрик.': 'Leave-one-out cross-validation: each well is removed in turn, its value is predicted by kriging from the rest, and compared with the actual value. Helps tune the variogram (nugget, range, model) by error rather than by eye.\n\nThe Log reports metrics: ME (bias, → 0), RMSE (lower is better), MSDR (→ 1 means the variogram is adequate in scale), R. Try different parameters and compare RMSE and MSDR.\n\nResiduals layer (opt.) - points with the following fields:\n  • <well number> - if "Well number field" is set;\n  • <validated field name> - the actual value;\n  • z_est - kriging estimate from the other points (LOO);\n  • error - estimate minus actual (minus: under, plus: over);\n  • abs_error - absolute error;\n  • std_resid - standardized residual: error / kriging standard error, signed (not a variance).\nIt shows where the model misses.\n\nThe HTML report (default) opens in the result viewer: an interactive "estimate vs actual" plot, an error histogram and a metrics table.',
    'Создаёт точечный слой «скважин» со случайными координатами в пределах области и значением абстрактного компонента (X, %), имеющим пространственную структуру. Предназначен для обучения и проверки инструментов без реальных данных.\n\nОбласть задаётся экстентом (можно по слою, по холсту карты, вручную координатами или рисованием). «Гладкость» задаёт радиус корреляции как долю охвата (больше - крупнее «пятна»). «Доля наггета» задаёт долю дисперсии, приходящуюся на короткомасштабный шум (чем больше, тем меньше предсказуемость). В Журнал выводится стартовая вариограмма - её уточняют кросс-валидацией.\n\nПоля результата: номер скважины, абсолютная отметка кровли (roof), мощность (thick) и содержание X. Диапазоны кровли и мощности по умолчанию близки к реальным калийным данным; их можно изменить в разделе «Дополнительно».': 'Creates a point "wells" layer with random coordinates within an area and a value of an abstract component (X, %), with a spatial structure. Intended for learning and testing the tools without real data.\n\nThe area is set by an extent (by layer, by map canvas, manually by coordinates or by drawing). "Smoothness" sets the correlation range as a fraction of the extent (larger - bigger "patches"). "Nugget fraction" sets the share of variance due to short-range noise (larger - less predictable). The Log prints the starting variogram - refine it with cross-validation.\n\nResult fields: well number, absolute roof elevation (roof), thickness (thick) and grade X. The default roof and thickness ranges are close to real potash data; you can change them under "Advanced".',
    'Доля наггета (от дисперсии)': 'Nugget fraction (of variance)',
    'Зерно ГСЧ (0 = случайно)': 'RNG seed (0 = random)',
    'Строит изотропную экспериментальную полувариограмму по точкам: облако пар усредняется по интервалам расстояния (лагам). Помогает увидеть структуру данных и подобрать вариограмму глазом, а не угадывать наггет/радиус.\n\nПоле группировки (необязательно): для каждого значения поля строится своя кривая - удобно сравнить совокупности разной плотности (поверхностная и подземная разведка) и проверить, общая ли у них структура.\n\nПодбор модели (по умолчанию) даёт наггет C0, вклад C, радиус a и модель. Сохраните их в профиль (поле «Сохранить профиль под именем») и подставьте в «2D Kriging». Можно наложить уже заданную модель, чтобы сравнить её с облаком.\n\nHTML-отчёт открывается в просмотрщике результатов: точки по лагам, модель и подобранная кривая, линия дисперсии данных. Слой-таблица (опц.) содержит лаг, γ(h) и число пар для построения в QGIS.': 'Builds an isotropic experimental semivariogram from points: the pair cloud is averaged over distance intervals (lags). Helps reveal the structure of the data and set the variogram by eye, instead of guessing the nugget/range.\n\nGrouping field (optional): a separate curve is built for each field value - handy to compare populations of different density (surface vs underground survey) and check whether they share a structure.\n\nModel fitting (default) gives nugget C0, contribution C, range a and the model. Save them to a profile (the "Save profile as" field) and apply them in "2D Kriging". You can overlay an already-set model to compare it with the cloud.\n\nThe HTML report opens in the result viewer: points by lag, the model and the fitted curve, the data-variance line. The table layer (opt.) holds lag, γ(h) and the number of pairs for plotting in QGIS.',
    'Управление профилями обработки. Профиль - это именованный набор «вариограмма (Структура 1: наггет, тип, порог, радиус, азимут, оси) + отсев ураганных проб». Профили сохраняют «Вариограмма» и «Кросс-валидация», а подставляет «2D Kriging».\n\nДействие: Показать список (в Журнал), Сохранить вручную (по полям в «Дополнительно»), Удалить выбранный, Очистить все.\n\nСписки профилей в выпадающих полях обновляются при открытии окна: сохранили профиль - переоткройте инструмент, чтобы он появился.': 'Manage processing profiles. A profile is a named set of "variogram (Structure 1: nugget, type, sill, range, azimuth, axes) + outlier removal". Profiles are saved by "Variogram" and "Cross-validation", and applied by "2D Kriging".\n\nAction: Show list (to the Log), Save manually (from the fields under "Advanced"), Delete selected, Clear all.\n\nProfile drop-down lists refresh when the window opens: after saving a profile, reopen the tool so it appears.',
    'Среднее для простого кригинга': 'Mean for simple kriging',
    'Наггет C0': 'Nugget C0',
    'Ураганные пробы: перцентиль обрезки, % (0 = выкл.)': 'Outliers: clip percentile, % (0 = off)',
    'Нижняя граница значения (пусто = нет)': 'Lower value bound (empty = none)',
    'Верхняя граница значения (пусто = нет)': 'Upper value bound (empty = none)',
    'Срезать к границе (capping) вместо удаления': 'Cap to bound (capping) instead of removing',
    'Ординарный/простой кригинг 2D по точечному слою (ядро GSLIB KB2D). Вариограмма: наггет + структура (сферическая, экспоненциальная, гауссова или степенная) с азимутом и анизотропией. Подходит для отметок пласта, мощностей, ФМС, химии и любых числовых атрибутов.\n\nРадиус поиска 0 = по всей выборке; размер ячейки 0 = min(охват)/50; радиус корреляции 0 = max(охват)/3. Опция обрезки убирает экстраполяцию вне контура скважин.': 'Ordinary/simple 2D kriging over a point layer (GSLIB KB2D core). Variogram: nugget + structure (spherical, exponential, Gaussian or power) with azimuth and anisotropy. Suitable for roof elevations, thicknesses, geomechanical properties, chemistry and any numeric attribute.\n\nSearch radius 0 = whole sample; cell size 0 = min(extent)/50; correlation range 0 = max(extent)/3. The clip option removes extrapolation outside the well hull.',
    'Точечный слой': 'Point layer',
    'Поле значения (Z)': 'Value field (Z)',
    'Сгладить грид (Гаусс)': 'Smooth grid (Gaussian)',
    'Радиус сглаживания, ячеек': 'Smoothing radius, cells',
    'Снять полиномиальный тренд': 'Remove polynomial trend',
    'Степень тренда': 'Trend degree',
    '1 (плоскость)': '1 (plane)',
    '2 (квадратичная)': '2 (quadratic)',
    'Региональный тренд снимается МНК перед кригингом, кригуются остатки, тренд возвращается к оценке. Полезно для отметок пласта и мощностей с общим падением. Для химии без тренда эффекта почти нет. Степень 1 обычно достаточна, степень 2 может вобрать часть реальной структуры в тренд - следите за вариограммой остатков.': 'The regional trend is removed by least squares before kriging, the residuals are kriged, and the trend is added back to the estimate. Useful for seam marks and thicknesses with a general dip. For chemistry without a trend the effect is negligible. Degree 1 is usually enough, degree 2 can absorb part of the real structure into the trend, so watch the residual variogram.',
    'Снятие тренда отключено: точек %d, для степени %d нужно больше %d.': 'Detrending off: %d points, degree %d needs more than %d.',
    'Снят тренд степени %d: убрано %.1f%% дисперсии (s данных %.4g, s остатка %.4g). Вариограмму задавайте по остаткам, стандартная ошибка - это ошибка кригинга остатков.': 'Trend of degree %d removed: %.1f%% of variance taken out (data s %.4g, residual s %.4g). Fit the variogram on the residuals, the standard error here is the kriging error of the residuals.',
    'Снят тренд степени %d: убрано %.1f%% дисперсии. Тренд переподбирается на каждом шаге LOO по остальным точкам, вариограмму задавайте по остаткам.': 'Trend of degree %d removed: %.1f%% of variance taken out. The trend is refit at each LOO step on the remaining points, fit the variogram on the residuals.',
    'Растр кригинга': 'Kriging raster',
    'Строит изолинии из растра: равномерный шаг или явные уровни (через пробел), главные (утолщённые) изолинии флагом is_index, фильтр коротких линий.\n\nСкругление линий (Chaikin) слегка сглаживает контуры и убирает «октагоны» от грубого грида. Сглаживание самого поля выполняется в инструменте 2D Kriging.\n\nБикубическое сглаживание (сгущение грида ×2…×4) даёт гладкие изолинии без «октагонов» от грубой сетки - это основной способ сглаживания, сильнее скругления линий (Chaikin). Работает и для линий, и для контурных полигонов: границы поясов совпадают с изолиниями.\n\nПо умолчанию строит и контурные полигоны (пояса между изолиниями) во временный слой - их границы СОВПАДАЮТ с изолиниями, покрытие сплошное. Чтобы их не строить - очистите поле «Контурные полигоны».\n\nПоля: линии - значение уровня (по умолчанию ELEV) и is_index (1 у главных); полигоны - ELEV_MIN/ELEV_MAX (диапазон пояса).': 'Builds isolines from a raster: a uniform step or explicit levels (space-separated), index (thicker) isolines via the is_index flag, a short-line filter.\n\nLine rounding (Chaikin) lightly smooths the contours and removes "octagons" from a coarse grid. Smoothing of the field itself is done in the 2D Kriging tool.\n\nBicubic smoothing (grid densification ×2…×4) gives smooth isolines without "octagons" from a coarse grid - it is the main smoothing method, stronger than line rounding (Chaikin). It works for both lines and contour polygons: band boundaries coincide with the isolines.\n\nBy default it also builds contour polygons (bands between isolines) into a temporary layer - their boundaries COINCIDE with the isolines, coverage is continuous. To skip them - clear the "Contour polygons" field.\n\nFields: lines - the level value (default ELEV) and is_index (1 on index lines); polygons - ELEV_MIN/ELEV_MAX (band range).',
    'Растр': 'Raster',
    'Изолинии (линии)': 'Isolines (lines)',
    'Контурные полигоны': 'Contour polygons',
    'Не задан растр.': 'No raster specified.',
    'Точки со значениями': 'Points with values',
    'Поле значения Z': 'Z value field',
    'Поле номера скважины (необязательно)': 'Well number field (optional)',
    'Сохранить профиль под именем (пусто = не сохранять)': 'Save profile as (empty = do not save)',
    'Слой остатков (точки)': 'Residuals layer (points)',
    'Отчёт о кросс-валидации (HTML)': 'Cross-validation report (HTML)',
    'HTML files (*.html)': 'HTML files (*.html)',
    'Область (экстент)': 'Area (extent)',
    'Число скважин': 'Number of wells',
    'Минимум значения X': 'Minimum of value X',
    'Максимум значения X': 'Maximum of value X',
    'Гладкость (доля охвата)': 'Smoothness (fraction of extent)',
    'Скважины (демо)': 'Wells (demo)',
    'Модель: наггет C0': 'Model: nugget C0',
    'Поле группировки (необязательно, напр. вид разведки)': 'Grouping field (optional, e.g. survey type)',
    'Число лагов': 'Number of lags',
    'Максимальное расстояние, в единицах слоя (0 = пол-диагонали)': 'Maximum distance, in layer units (0 = half-diagonal)',
    'Подобрать модель (рекомендация)': 'Fit model (recommendation)',
    'Таблица вариограммы (лаг, γ, число пар)': 'Variogram table (lag, γ, number of pairs)',
    'Отчёт (HTML)': 'Report (HTML)',
    'Действие': 'Action',
    'Имя профиля (для «Сохранить вручную»)': 'Profile name (for "Save manually")',
    'Строит вариограммную карту - поверхность γ(h_x, h_y): для всех пар берётся вектор разноса (dx, dy) и полудисперсия 0.5·(Δz)², значения усредняются по 2D-сетке лагов. Анизотропия видна как эллипс: направление, вдоль которого γ растёт медленнее (длиннее радиус), - ось максимальной непрерывности (для складчатости - простирание).\n\nВ Журнал и в HTML-отчёт выводятся оценки: азимут главной оси (геогр., 0=С, по часовой), коэффициент анизотропии (малая/главная) и радиус. Их можно подставить в структуру вариограммы «2D Kriging» (азимут, анизотропия, радиус a) - это и есть учёт анизотропии в кригинге. Оценка индикативная: уточняйте по самому хитмапу.\n\nЕсли структура близка к изотропной или радиус меньше ячейки - анизотропия не оценивается (помечается «не выражена»).\n\nОпц. растр поверхности (в координатах лага, начало в 0,0) - для тех, кто хочет видеть карту на холсте.': 'Builds a variogram map - the γ(h_x, h_y) surface: for every pair, the separation vector (dx, dy) and the semivariance 0.5·(Δz)² are taken, and values are averaged over a 2D grid of lags. Anisotropy shows as an ellipse: the direction along which γ grows more slowly (longer range) is the axis of maximum continuity (for folding - the strike).\n\nThe Log and the HTML report give estimates: the major-axis azimuth (geographic, 0=N, clockwise), the anisotropy ratio (minor/major) and the range. They can be fed into the "2D Kriging" variogram structure (azimuth, anisotropy, range a) - this is how anisotropy enters kriging. The estimate is indicative: refine it against the heatmap itself.\n\nIf the structure is near-isotropic or the range is smaller than a cell - anisotropy is not estimated (marked "not expressed").\n\nOpt. surface raster (in lag coordinates, origin at 0,0) - for those who want to see the map on the canvas.',
    'Бинов на полуось (детализация карты)': 'Bins per half-axis (map detail)',
    'Макс. лаг, в единицах слоя (0 = пол-диагонали)': 'Max. lag, in layer units (0 = half-diagonal)',
    'Растр поверхности (опц., в лаг-координатах)': 'Surface raster (opt., in lag coordinates)',
    'Не задан точечный слой.': 'No point layer specified.',
    'Канал': 'Band',
    'Минимум точек в группе, % от выборки (пол 30 точек)': 'Minimum points per group, % of sample (floor 30 points)',
    'Модель для подбора': 'Model to fit',
    'Устойчивая оценка (Кресси-Хокинса)': 'Robust estimator (Cressie-Hawkins)',
    'Показать облако пар': 'Show pair cloud',
    'Наложить заданную модель вариограммы': 'Overlay a given variogram model',
    'Модель: тип': 'Model: type',
    'Модель: порог/вклад C': 'Model: sill/contribution C',
    'Модель: радиус корреляции a': 'Model: correlation range a',
    'Модель: азимут, °': 'Model: azimuth, °',
    'Модель: анизотропия (малая/главная)': 'Model: anisotropy (minor/major)',
    'Отсев: перцентиль обрезки, % (0 = выкл.)': 'Outliers: clip percentile, % (0 = off)',
    'Отсев: нижняя граница (пусто = нет)': 'Outliers: lower bound (empty = none)',
    'Отсев: верхняя граница (пусто = нет)': 'Outliers: upper bound (empty = none)',
    'Отсев: срезать к границе вместо удаления': 'Outliers: cap to bound instead of removing',
    'Мин. число пар в ячейке': 'Min. number of pairs per cell',
    'модель': 'model',
    'радиус корреляции a (0=авто)': 'correlation range a (0=auto)',
    'азимут, °': 'azimuth, °',
    'анизотропия (малая/главная)': 'anisotropy (minor/major)',
    '0 = авто: min(охват)/50': '0 = auto: min(extent)/50',
    'грид: -': 'grid: -',
    ' (авто)': ' (auto)',
    'Профиль «%s»: %s.': 'Profile "%s": %s.',
    ' Расчёт пойдёт по профилю - поля ниже игнорируются.': ' Computation will use the profile - the fields below are ignored.',
    'грид: %d × %d%s': 'grid: %d × %d%s',
    'Профиль не выбран - расчёт по полям диалога.': 'No profile selected - computing from dialog fields.',
    'Профиль не выбран.': 'No profile selected.',
    'Профиль «%s» не найден.': 'Profile "%s" not found.',
    'Сферическая': 'Spherical',
    'Экспоненциальная': 'Exponential',
    'Гауссова': 'Gaussian',
    'Степенная': 'Power',
    'Ординарный (OK)': 'Ordinary (OK)',
    'Простой (SK)': 'Simple (SK)',
    'Авто (лучшая по R²)': 'Auto (best by R²)',
    'Показать список': 'Show list',
    'Сохранить вручную (по полям ниже)': 'Save manually (from fields below)',
    'Удалить выбранный': 'Delete selected',
    'Очистить все': 'Clear all',
    '(не выбран)': '(none)',
    'Загрузить профиль обработки': 'Load processing profile',
    'Профиль (для удаления / просмотра)': 'Profile (for deletion / preview)',
    '\n\n- - -\nРазработано при поддержке ООО «Информ++» (www.informpp.ru).\nСтраница плагина: www.informpp.ru/главная-страница/qgis-isoliner': '\n\n- - -\nDeveloped with the support of Inform++ LLC (www.informpp.ru).\nPlugin page: www.informpp.ru/главная-страница/qgis-isoliner',
    '≥ %.4g (упёрся в макс. лаг)': '≥ %.4g (capped at max lag)',
    '<p><i>Интерактивный график недоступен (нет plotly). Числовые оценки - в сводке выше.</i></p>': '<p><i>Interactive chart unavailable (no plotly). Numeric estimates are in the summary above.</i></p>',
    "<div style='background:#f3f7f4;border:1px solid #cde0d6;padding:8px 14px;border-radius:6px;max-width:900px;margin:12px 0'><b>Что дальше</b><ul style='margin:6px 0'>%s</ul></div>": "<div style='background:#f3f7f4;border:1px solid #cde0d6;padding:8px 14px;border-radius:6px;max-width:900px;margin:12px 0'><b>What's next</b><ul style='margin:6px 0'>%s</ul></div>",
    "<div style='background:#f5f5f7;border:1px solid #ddd;padding:8px 14px;border-radius:6px;display:inline-block'><b>Сводка</b><div style='margin-top:6px'><table cellpadding='4'>%s</table></div></div>": "<div style='background:#f5f5f7;border:1px solid #ddd;padding:8px 14px;border-radius:6px;display:inline-block'><b>Summary</b><div style='margin-top:6px'><table cellpadding='4'>%s</table></div></div>",
    'Точек': 'Points',
    'Поле Z': 'Z field',
    'Макс. лаг': 'Max. lag',
    'не выражена': 'not expressed',
    'Ячейка лага': 'Lag cell',
    'главная ось': 'major axis',
    'Анизотропия': 'Anisotropy',
    'Вариокарта · %s': 'Variomap · %s',
    'Бинов на полуось': 'Bins per half-axis',
    'Дисперсия (силл)': 'Variance (sill)',
    'лаг по северу h_y': 'north lag h_y',
    'Радиус главной оси': 'Major-axis range',
    'Стиль изолиний': 'Isoline style',
    'Без стиля': 'No style',
    'Структура / гипсометрия': 'Structure / hypsometry',
    'Мощности': 'Thickness',
    'Гидроизогипсы': 'Water-table contours',
    'Содержания': 'Grades',
    'Депрессия (штрихи вниз)': 'Depression (downhill hachures)',
    'Выбран депрессионный стиль, но «Сторона склона для бергштрихов» выключена - поля dn_sign нет, штрихи не определят сторону. Включите галку, чтобы штрихи смотрели вниз.': 'The depression style is selected but "Downhill side for hachures" is off, so there is no dn_sign field and the hachures cannot pick a side. Enable the checkbox so the hachures point downhill.',
    'Сторона склона для бергштрихов (поле dn_sign)': 'Downhill side for hachures (dn_sign field)',
    'Сторона склона (dn_sign) для бергштрихов…': 'Downhill side (dn_sign) for hachures…',
    'Не удалось вычислить сторону склона (dn_sign): %s': 'Could not compute the downhill side (dn_sign): %s',
    'Мало точек (%d): оценка кригинга и вариограммы неустойчива.': 'Few points (%d): the kriging and variogram estimates are unstable.',
    'Точек с совпадающими координатами: %d. Частая причина вырожденной матрицы и артефактов. Уберите дубли или усредните пробы в одной точке.': 'Points with coinciding coordinates: %d. A common cause of a singular matrix and artefacts. Remove duplicates or average the samples at one location.',
    'Все значения одинаковы: кригинг вырождается, вариограмма нулевая. Проверьте выбранное поле.': 'All values are identical: kriging degenerates and the variogram is zero. Check the selected field.',
    'Азимут главной оси': 'Major-axis azimuth',
    'Записать анизотропию в профиль': 'Write anisotropy to a profile',
    'Анизотропия не выражена - в профиль писать нечего.': 'Anisotropy not resolved, nothing to write to the profile.',
    'Профиль «%s» не найден - анизотропия не сохранена. Сначала сохраните профиль в «Вариограмме» или «Кросс-валидации».': 'Profile "%s" not found, anisotropy not saved. First save a profile in Variogram or Cross-validation.',
    'В профиль «%s» записаны азимут=%.0f° и анизотропия=%.2f (радиус оставлен прежним: упёрся в макс. лаг). При загрузке профиля они появятся в подписи.': 'Written to profile "%s": azimuth=%.0f° and anisotropy=%.2f (range left unchanged: it hit the max lag). They will appear in the caption when the profile is loaded.',
    'В профиль «%s» записаны азимут=%.0f°, анизотропия=%.2f, радиус a=%.4g. При загрузке профиля они появятся в подписи.': 'Written to profile "%s": azimuth=%.0f°, anisotropy=%.2f, range a=%.4g. They will appear in the caption when the profile is loaded.',
    'лаг по востоку h_x': 'east lag h_x',
    'эллипс анизотропии': 'anisotropy ellipse',
    'Анизотропия (малая/главная)': 'Anisotropy (minor/major)',
    'Вариограммная карта %s · %s': 'Variogram map %s · %s',
    'Вариограммная карта: %d точек…': 'Variogram map: %d points…',
    'Не удалось записать HTML-отчёт: %s': 'Could not write the HTML report: %s',
    'Точки прорежены до %d (для скорости).': 'Points subsampled to %d (for speed).',
    'Не удалось записать растр поверхности: %s': 'Could not write the surface raster: %s',
    'plotly недоступен (%s) - отчёт без графика.': 'plotly unavailable (%s) - report without a chart.',
    'Оценка индикативная - сверьте с формой хитмапа (эллипса).': 'The estimate is indicative - check it against the heatmap (ellipse) shape.',
    'В «2D Kriging» задайте: азимут=%.0f, анизотропия=%.2f, радиус a=%.4g.': 'In "2D Kriging" set: azimuth=%.0f, anisotropy=%.2f, range a=%.4g.',
    'Главная ось непрерывности ~%.0f° (геогр.). Для складчатости это направление простирания.': 'Major continuity axis ~%.0f° (geographic). For folding this is the strike direction.',
    'Подставьте в структуру вариограммы «2D Kriging»: азимут=%.0f, анизотропия=%.2f, радиус a=%.4g.': 'Feed into the "2D Kriging" variogram structure: azimuth=%.0f, anisotropy=%.2f, range a=%.4g.',
    'Анизотропия не разрешается на этой сетке: структура близка к изотропной либо радиус меньше ячейки.': 'Anisotropy is not resolved on this grid: the structure is near-isotropic or the range is smaller than a cell.',
    'Попробуйте уменьшить «Макс. лаг» или увеличить «Бинов на полуось», чтобы разрешить ближнюю структуру.': 'Try reducing "Max. lag" or increasing "Bins per half-axis" to resolve the near structure.',
    'Анизотропия: азимут главной оси %.0f° (геогр.), коэффициент %.2f (малая/главная), радиус главной оси %.4g.': 'Anisotropy: major-axis azimuth %.0f° (geographic), ratio %.2f (minor/major), major-axis range %.4g.',
    'В «2D Kriging» подставьте азимут=%.0f и анизотропию≈%.2f (как ориентир); радиус a задайте больше %.4g по смыслу данных.': 'In "2D Kriging" use azimuth=%.0f and anisotropy≈%.2f (as a guide); set range a larger than %.4g per the data.',
    'Если γ не выходит на полку даже при широком окне - в данных тренд: его убирают до интерполяции либо учитывают видом кригинга.': 'If γ does not reach a plateau even in a wide window - the data has a trend: remove it before interpolation or account for it with the kriging type.',
    'Анизотропия не выражена (структура близка к изотропной или радиус меньше ячейки). Можно уменьшить макс. лаг или увеличить число бинов.': 'Anisotropy not expressed (the structure is near-isotropic or the range is smaller than a cell). You can reduce the max lag or increase the number of bins.',
    'В «2D Kriging» задайте азимут=%.0f и анизотропию≈%.2f как ориентир, радиус a возьмите больше %.4g по смыслу данных. Чтобы измерить радиус - увеличьте «Макс. лаг».': 'In "2D Kriging" set azimuth=%.0f and anisotropy≈%.2f as a guide, and take range a larger than %.4g per the data. To measure the range - increase "Max. lag".',
    'Радиус главной оси упёрся в макс. лаг (%.4g): вдоль простирания вариограмма на полку не вышла - радиус считайте нижней оценкой, а анизотропию (%.2f) - заниженной по выраженности.': 'The major-axis range is capped at the max lag (%.4g): along the strike the variogram did not reach a plateau - treat the range as a lower bound and the anisotropy (%.2f) as understated.',
    'Радиус главной оси упёрся в макс. лаг (%.4g): вдоль простирания вариограмма на полку не вышла. Радиус - нижняя оценка, анизотропия (%.2f) занижена по выраженности. Увеличьте «Макс. лаг», либо это признак тренда / очень сильной непрерывности.': 'The major-axis range is capped at the max lag (%.4g): along the strike the variogram did not reach a plateau. The range is a lower bound and the anisotropy (%.2f) is understated. Increase "Max. lag", or this signals a trend / very strong continuity.',
    'Полигоны · %s': 'Polygons · %s',
    'Изолинии · %s': 'Isolines · %s',
    'Кригинг %s · %s': 'Kriging %s · %s',
    'Остатки CV %s · %s': 'CV residuals %s · %s',
    'Вариограмма %s · %s': 'Variogram %s · %s',
    'Стд. ошибка · %s · %s': 'Std. error · %s · %s',
    ' (показаны ~30000 точек)': ' (showing ~30000 points)',
    ' Радиус подбора (%.4g) достигает края окна (%.4g), это подтверждает: кривая ещё растёт.': ' The fitted range (%.4g) reaches the window edge (%.4g), confirming the curve is still rising.',
    ' Радиус подбора (%.4g) у края окна (%.4g) - считайте его нижней оценкой, при сомнении увеличьте окно и проверьте, стабилизируется ли радиус.': ' The fitted range (%.4g) is at the window edge (%.4g) - treat it as a lower bound; if in doubt, widen the window and check whether the range stabilizes.',
    ' и %d без геометрии': ' and %d without geometry',
    ', анизотропия %.3g по азимуту %.4g°': ', anisotropy %.3g at azimuth %.4g°',
    ', отсев %.4g%%': ', outlier clip %.4g%%',
    '<br>пар %{customdata}': '<br>pairs %{customdata}',
    "<div style='background:#f3f7f4;border:1px solid #cde0d6;padding:8px 14px;border-radius:6px;max-width:900px;margin:12px 0'><b>Рекомендации</b><ul style='margin:6px 0'>%s</ul></div>": "<div style='background:#f3f7f4;border:1px solid #cde0d6;padding:8px 14px;border-radius:6px;max-width:900px;margin:12px 0'><b>Recommendations</b><ul style='margin:6px 0'>%s</ul></div>",
    "<div style='background:#f5f5f7;border:1px solid #ddd;padding:8px 14px;border-radius:6px'><b>Параметры кригинга</b> <span style='color:#888;font-size:88%%'>(отличные от стандартных)</span><div style='margin-top:6px'>%s</div></div>": "<div style='background:#f5f5f7;border:1px solid #ddd;padding:8px 14px;border-radius:6px'><b>Kriging parameters</b> <span style='color:#888;font-size:88%%'>(differing from defaults)</span><div style='margin-top:6px'>%s</div></div>",
    "<div style='background:#f5f5f7;border:1px solid #ddd;padding:8px 14px;border-radius:6px;display:inline-block'><b>Сводка</b><div style='margin-top:6px'>%s</div></div>": "<div style='background:#f5f5f7;border:1px solid #ddd;padding:8px 14px;border-radius:6px;display:inline-block'><b>Summary</b><div style='margin-top:6px'>%s</div></div>",
    '<p><i>Интерактивный график недоступен (нет plotly). ': '<p><i>Interactive chart unavailable (no plotly). ',
    "<p><i>Интерактивный график недоступен (нет plotly). Значения экспериментальной вариограммы:</i></p><table border='1' cellpadding='4' style='border-collapse:collapse'>%s%s</table>": "<p><i>Interactive chart unavailable (no plotly). Experimental variogram values:</i></p><table border='1' cellpadding='4' style='border-collapse:collapse'>%s%s</table>",
    "<span style='color:#777'>все параметры - стандартные</span>": "<span style='color:#777'>all parameters are default</span>",
    "<table style='border-collapse:collapse' cellpadding='6'><tr><th align='left'>Метрика</th><th>Значение</th><th align='left'>Смысл</th></tr>%s</table>": "<table style='border-collapse:collapse' cellpadding='6'><tr><th align='left'>Metric</th><th>Value</th><th align='left'>Meaning</th></tr>%s</table>",
    "<tr><th align='left'>серия</th><th>h</th><th>γ(h)</th><th>пар</th></tr>": "<tr><th align='left'>series</th><th>h</th><th>γ(h)</th><th>pairs</th></tr>",
    '== Кросс-валидация (leave-one-out) ==': '== Cross-validation (leave-one-out) ==',
    'ME (смещение)': 'ME (bias)',
    'ME (смещение):   %+.4g   (ближе к 0 - лучше)': 'ME (bias):       %+.4g   (closer to 0 is better)',
    'ME близок к 0: систематического смещения нет.': 'ME close to 0: no systematic bias.',
    'ME заметно отличается от 0 (%+.3g): возможен систематический сдвиг - проверьте данные и тип кригинга (для простого - заданное среднее).': 'ME differs noticeably from 0 (%+.3g): possible systematic shift - check the data and the kriging type (for simple kriging, the specified mean).',
    'MSDR близок к 1: масштаб вариограммы подобран адекватно.': 'MSDR close to 1: the variogram scale is adequate.',
    'MSDR заметно больше 1 (%.3g): карта стандартной ошибки занижена. Умножьте наггет C0 и вклады C на MSDR (радиус и модель не трогайте) и пересчитайте - сами оценки не изменятся, поправится только дисперсия кригинга.': "MSDR noticeably above 1 (%.3g): the standard-error map is understated. Multiply nugget C0 and contributions C by MSDR (leave range and model) and recompute - the estimates won't change, only the kriging variance is corrected.",
    'MSDR меньше 1 (%.3g): неопределённость завышена. Разделите наггет C0 и вклады C на MSDR (радиус и модель не трогайте) и пересчитайте - оценки не изменятся.': "MSDR below 1 (%.3g): uncertainty is overstated. Divide nugget C0 and contributions C by MSDR (leave range and model) and recompute - the estimates won't change.",
    'MSDR:            %.3f   (ближе к 1 - лучше)': 'MSDR:            %.3f   (closer to 1 is better)',
    'QQ-график остатков': 'Residuals QQ-plot',
    'R (оценка/факт)': 'R (estimate/actual)',
    'R (оценка/факт): %.3f': 'R (estimate/actual): %.3f',
    'RMSE:            %.4g   (меньше - лучше)': 'RMSE:            %.4g   (lower is better)',
    '|Ошибка|': '|Error|',
    'В поле группировки меньше 2 значений - строю только общую кривую.': 'The grouping field has fewer than 2 values - building only the overall curve.',
    'В растре нет валидных значений.': 'The raster has no valid values.',
    'Верхняя граница': 'Upper bound',
    'Выберите профиль для удаления в поле «Профиль».': 'Select a profile to delete in the "Profile" field.',
    'Высокая корреляция (R=%.2f): оценки хорошо согласуются с фактом.': 'High correlation (R=%.2f): estimates agree well with the actual values.',
    'Гауссова модель с почти нулевым наггетом численно неустойчива (кригинг даёт «бычьи глаза», MSDR разваливается). Задайте небольшой наггет C0.': 'A Gaussian model with a near-zero nugget is numerically unstable (kriging gives "bull\'s eyes", MSDR falls apart). Set a small nugget C0.',
    'Гауссова модель: наггет повышен с %.4g до %.4g для устойчивости (минимум %g%% структурного силла).': 'Gaussian model: nugget raised from %.4g to %.4g for stability (minimum %g%% of the structural sill).',
    'Гистограмма ошибок': 'Error histogram',
    'Главные изолинии: каждая %d-я…': 'Index isolines: every %d-th…',
    'Групп больше 12 - группировка пропущена.': 'More than 12 groups - grouping skipped.',
    'Группы меньше %d точек пропущены: %s.': 'Groups smaller than %d points skipped: %s.',
    'Диаграмму можно построить по слою остатков.</i></p>': 'You can build a chart from the residuals layer.</i></p>',
    'Дисперсия данных': 'Data variance',
    'Дисперсия данных: %.4g. Ориентир: суммарный силл (C0 + вклады C) задавайте близким к ней. Наггет и силл - в абсолютных единицах дисперсии, не 0-1.': 'Data variance: %.4g. Guide: set the total sill (C0 + contributions C) close to it. Nugget and sill are in absolute variance units, not 0-1.',
    'Для сохранения укажите «Имя профиля».': 'To save, specify a "Profile name".',
    'Загружено алгоритмов: %d': 'Algorithms loaded: %d',
    'Задайте шаг изолиний или уровни.': 'Specify an isoline step or levels.',
    'Задан только наггет (структурный вклад C = 0): кригинг выродится в локальное среднее, поверхность будет почти плоской.': 'Only the nugget is set (structural contribution C = 0): kriging degenerates into a local mean and the surface will be almost flat.',
    'Итог: параметры можно утверждать - перенесите ту же вариограмму и настройки поиска в «2D Kriging».': 'Verdict: the parameters can be accepted - carry the same variogram and search settings into "2D Kriging".',
    'Итог: параметры стоит подправить (см. ниже) и повторить кросс-валидацию перед финальным кригингом.': 'Verdict: the parameters should be adjusted (see below) and cross-validation repeated before the final kriging.',
    'Контур валидной области…': 'Valid-area outline…',
    'Контур скважин: выпуклая оболочка…': 'Well outline: convex hull…',
    'Кресси-Хокинса': 'Cressie-Hawkins',
    'Кровля: максимум, м (абс.)': 'Roof: maximum, m (abs.)',
    'Кровля: минимум, м (абс.)': 'Roof: minimum, m (abs.)',
    'Кросс-валидация %s · %s': 'Cross-validation %s · %s',
    'Кросс-валидация по %d точкам…': 'Cross-validation over %d points…',
    'Макс. точек': 'Max. points',
    'Максимальное расстояние': 'Maximum distance',
    'Максимальное расстояние (%.4g) меньше типичного шага между точками (~%.4g) - пар почти нет. Значение задаётся в единицах слоя (обычно метры).': 'The maximum distance (%.4g) is smaller than the typical point spacing (~%.4g) - almost no pairs. The value is in layer units (usually metres).',
    'Максимум значения должен быть больше минимума.': 'The maximum value must be greater than the minimum.',
    'Матерона': 'Matheron',
    'Мин. точек': 'Min. points',
    'Мощность: максимум, м': 'Thickness: maximum, m',
    'Мощность: минимум, м': 'Thickness: minimum, m',
    'Назначение диапазонов поясам…': 'Assigning ranges to bands…',
    'Не задана корректная область (экстент).': 'No valid area (extent) specified.',
    'Не удалось добавить %s: %s': 'Could not add %s: %s',
    'Не удалось открыть растр для сглаживания.': 'Could not open the raster for smoothing.',
    'Не удалось открыть растр для сгущения.': 'Could not open the raster for densification.',
    'Не удалось открыть растр.': 'Could not open the raster.',
    'Не удалось перечислить группы: %s': 'Could not enumerate groups: %s',
    'Не удалось разобрать уровень: %r': 'Could not parse level: %r',
    'Недостаточно валидных точек с числовым значением.': 'Not enough valid points with a numeric value.',
    'Недостаточно уровней для полигонов.': 'Not enough levels for polygons.',
    'Ни один пояс не получил значения.': 'No band received a value.',
    'Нижняя граница': 'Lower bound',
    'Низкая корреляция (R=%.2f): модель слабо предсказывает - попробуйте другой радиус, модель или анизотропию; либо это предел данных (короткомасштабная изменчивость, зоны замещения).': "Low correlation (R=%.2f): the model predicts poorly - try a different range, model or anisotropy; or it is the data's limit (short-range variability, replacement zones).",
    'Нодирование сети линий (GEOS)…': 'Noding the line network (GEOS)…',
    'Номер скважины': 'Well number',
    'Обрезка по маске…': 'Clipping by mask…',
    'Осталось профилей: %d%s': 'Profiles remaining: %d%s',
    'Отсев: перцентиль, %': 'Outliers: percentile, %',
    'Оценка': 'Estimator',
    'Оценка vs факт': 'Estimate vs actual',
    'Оценка кригинга (LOO)': 'Kriging estimate (LOO)',
    'Ошибка (оценка − факт)': 'Error (estimate − actual)',
    'Подбор: модель %s, C0=%.4g, C=%.4g, a=%.4g, R²=%.3f': 'Fit: model %s, C0=%.4g, C=%.4g, a=%.4g, R²=%.3f',
    'Подвыборка точек': 'Point subsampling',
    'Подставлен профиль «%s»: %s.': 'Applied profile "%s": %s.',
    'Полигонизация не дала результата (проверьте изолинии/контур).': 'Polygonization produced nothing (check the isolines/outline).',
    'Полигонизация поясов (GEOS)…': 'Polygonizing bands (GEOS)…',
    'После отсева ураганных проб осталось < 2 точек.': 'After outlier removal fewer than 2 points remain.',
    'После усреднения совпадающих точек осталось < 2 узлов.': 'After averaging coincident points fewer than 2 nodes remain.',
    'Поясов получено (GEOS): %d': 'Bands produced (GEOS): %d',
    'Прервано пользователем.': 'Cancelled by the user.',
    'Продление открытых концов за контур…': 'Extending open ends past the outline…',
    'Пропущено точек: %d без значения «%s»%s. Прочитано: %d.': 'Points skipped: %d without a value for "%s"%s. Read: %d.',
    'Профиль «%s» сохранён: %s': 'Profile "%s" saved: %s',
    'Профиль «%s» сохранён: изотропная модель из автоподбора + текущий отсев. Анизотропию можно задать в кросс-валидации или инструменте «Профили».': 'Profile "%s" saved: isotropic auto-fit model + current outlier removal. Anisotropy can be set in cross-validation or the "Profiles" tool.',
    'Профиль «%s» сохранён: проверенная модель Структуры 1 (с анизотропией, если задана) + отсев.': 'Profile "%s" saved: validated Structure 1 model (with anisotropy, if set) + outlier removal.',
    'Профиль «%s» удалён.': 'Profile "%s" deleted.',
    'Профиль не найден - использую значения из диалога. Список профилей обновляется при открытии окна инструмента.': 'Profile not found - using the dialog values. The profile list refreshes when the tool window opens.',
    'Радиус подбора (%.4g) достигает края окна (%.4g) - вариограмма не вышла на плато, радиус считайте нижней оценкой.': 'The fitted range (%.4g) reaches the window edge (%.4g) - the variogram did not reach a plateau; treat the range as a lower bound.',
    'Радиус поиска': 'Search radius',
    'Рекомендация: модель %s, наггет C0=%.4g, вклад C=%.4g (сумма %.4g), радиус a=%.4g. Качество подгонки R²=%.3f.': 'Recommendation: model %s, nugget C0=%.4g, contribution C=%.4g (total %.4g), range a=%.4g. Fit quality R²=%.3f.',
    'Сгенерировано скважин: %d. Поля: кровля (roof), мощность (thick), содержание X. Дисперсия X ≈ %.4g.': 'Wells generated: %d. Fields: roof, thickness (thick), grade X. Variance of X ≈ %.4g.',
    'Сглаживание грида (σ=%g яч.)…': 'Smoothing the grid (σ=%g cells)…',
    'Сглаживание поля (σ=%g яч.)…': 'Smoothing the field (σ=%g cells)…',
    'Сгущение грида ×%d (бикубика)…': 'Densifying the grid ×%d (bicubic)…',
    'Сетка %d x %d, ячейка %.4g, точек %d, структур %d': 'Grid %d x %d, cell %.4g, points %d, structures %d',
    'Скругление линий (Chaikin, %d итер.)…': 'Line rounding (Chaikin, %d iter.)…',
    'Слишком мало оценённых точек.': 'Too few estimated points.',
    'Совпадающих точек усреднено: %d (осталось %d)': 'Coincident points averaged: %d (%d remaining)',
    'Согласование концов изолиний с контуром…': 'Snapping isoline ends to the outline…',
    'Сохраните модель в профиль (поле «Сохранить профиль под именем»), проверьте «Кросс-валидацией» и подставьте профиль в «2D Kriging».': 'Save the model to a profile (the "Save profile as" field), check it with "Cross-validation" and apply the profile in "2D Kriging".',
    'Сохранённые профили (%d):': 'Saved profiles (%d):',
    'Сохранённых профилей нет.': 'No saved profiles.',
    'Среднее (SK)': 'Mean (SK)',
    'Срезка (capping)': 'Capping',
    'Станд. остаток (со знаком)': 'Std. residual (signed)',
    'Стартовая вариограмма для X (кригинг/кросс-валидация): суммарный силл ≈ %.4g, наггет C0 ≈ %.4g, радиус ≈ %.4g (в единицах координат). Уточните наггет по кросс-валидации до MSDR ≈ 1.': 'Starting variogram for X (kriging/cross-validation): total sill ≈ %.4g, nugget C0 ≈ %.4g, range ≈ %.4g (in coordinate units). Refine the nugget via cross-validation until MSDR ≈ 1.',
    'Структура %d: показатель степенной модели ω=%.3g вне (0; 2) - приведён к диапазону.': 'Structure %d: power-model exponent ω=%.3g outside (0; 2) - clamped to range.',
    'Структура %d: степенная модель - поле «радиус a» это показатель ω (0<ω<2), а не радиус; задан 0, взят ω=1.': 'Structure %d: power model - the "range a" field is the exponent ω (0<ω<2), not a range; 0 given, ω=1 used.',
    'Суммарный порог близок к дисперсии данных (%.4g) - масштаб правдоподобен.': 'The total sill is close to the data variance (%.4g) - the scale is plausible.',
    'Суммарный порог заметно выше дисперсии данных (%.4g) - окно, вероятно, перешагивает тренд или безрудную зону. Уменьшите максимальное расстояние до локального масштаба и проверьте выбросы.': 'The total sill is noticeably above the data variance (%.4g) - the window likely crosses a trend or a barren zone. Reduce the maximum distance to a local scale and check for outliers.',
    'Суммарный порог заметно ниже дисперсии данных (%.4g): вариограмма не вышла на плато - увеличьте максимальное расстояние, возможен тренд или вторая структура.': 'The total sill is noticeably below the data variance (%.4g): the variogram did not reach a plateau - increase the maximum distance; a trend or a second structure is possible.',
    'Точек много - для расчёта пар использована случайная подвыборка %d точек.': 'Many points - a random subsample of %d points was used for pair computation.',
    'Точек оценено': 'Points estimated',
    'Точек оценено: %d из %d': 'Points estimated: %d of %d',
    'Точек экспериментальной вариограммы мало для подбора. Увеличьте число лагов или максимальное расстояние.': 'Too few experimental variogram points to fit. Increase the number of lags or the maximum distance.',
    'Точек: %d. Дисперсия данных: %.4g (ориентир для суммарного порога).': 'Points: %d. Data variance: %.4g (a guide for the total sill).',
    'Удалены все профили (%d).': 'All profiles deleted (%d).',
    'Ураганные пробы: срезано %d значений к [%.4g; %.4g].': 'Outliers: %d values capped to [%.4g; %.4g].',
    'Ураганные пробы: удалено %d точек вне [%.4g; %.4g]; осталось %d.': 'Outliers: %d points removed outside [%.4g; %.4g]; %d remaining.',
    'Факт (%s)': 'Actual (%s)',
    'Фильтр коротких линий (< %g)…': 'Short-line filter (< %g)…',
    'азимут=%g°': 'azimuth=%g°',
    'анис=%g': 'anis=%g',
    'ближе к 0 - лучше': 'closer to 0 is better',
    'ближе к 1 - лучше': 'closer to 1 is better',
    'все точки': 'all points',
    'выкл.': 'off',
    'да': 'yes',
    'дисперсия данных': 'data variance',
    'заданная модель': 'given model',
    'из %d': 'of %d',
    'корреляция': 'correlation',
    'меньше - лучше': 'lower is better',
    'модель (малая ось)': 'model (minor axis)',
    'наггет C0=%.4g, %s, порог C=%.4g, радиус a=%.4g': 'nugget C0=%.4g, %s, sill C=%.4g, range a=%.4g',
    'недостаточно точек для QQ': 'too few points for QQ',
    'облако пар': 'pair cloud',
    'оценка (LOO)': 'estimate (LOO)',
    'оценка − факт': 'estimate − actual',
    'ошибка (z-оценка)': 'error (z-score)',
    'подобранная модель': 'fitted model',
    'полудисперсия γ(h)': 'semivariance γ(h)',
    'пояса': 'bands',
    'простой (SK)': 'simple (SK)',
    'профиль': 'profile',
    'расстояние h': 'distance h',
    'скв. %{customdata}<br>факт %{x:.3g}<br>оценка %{y:.3g}<extra></extra>': 'well %{customdata}<br>actual %{x:.3g}<br>estimate %{y:.3g}<extra></extra>',
    'скв. %{text}<br>факт %{x:.3g}<br>оценка %{y:.3g}<extra>худшие</extra>': 'well %{text}<br>actual %{x:.3g}<br>estimate %{y:.3g}<extra>worst</extra>',
    'средняя |ошибка|': 'mean |error|',
    'суммарный силл (C0 + вклады C) ≈ дисперсии данных': 'total sill (C0 + contributions C) ≈ data variance',
    'теор. %{x:.2f}<br>ошибка (z) %{y:.2f}<extra></extra>': 'theor. %{x:.2f}<br>error (z) %{y:.2f}<extra></extra>',
    'теор. квантили (норм.)': 'theor. quantiles (norm.)',
    'факт': 'actual',
}
