# -*- 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.1 2D Kriging (точки → растр)': '1.1 2D Kriging (points → raster)',
    '1.2 Изолинии из растра': '1.2 Isolines from raster',
    '1.5 Кросс-валидация вариограммы': '1.5 Variogram cross-validation',
    'Грид и изолинии': 'Grid and isolines',
    'Дополнительные инструменты': 'Additional tools',
    '1.6 Создать пример скважин (демо)': '1.6 Create sample wells (demo)',
    '1.3 Вариограмма (экспериментальная)': '1.3 Variogram (experimental)',
    '1.7 Профили обработки': '1.7 Processing profiles',
    '1.4 Вариограммная карта (анизотропия)': '1.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. Диапазоны кровли и мощности по умолчанию близки к реальным калийным данным; их можно изменить в разделе «Дополнительно».\n\nНеобязательные галки добавляют поля для смежных инструментов: напор (head) для градиента потока и категориальный минтип для индикаторного кригинга. Включённый вывод «Поверхность дрейфа» даёт растр сторонней поверхности и поле dz, линейно с ней связанное, для кригинга с внешним дрейфом.': '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".\n\nOptional checkboxes add fields for the neighbouring tools: head for the flow gradient and a categorical mineral type for indicator kriging. Enabling the "Drift surface" output gives a raster of a secondary surface and a dz field linearly related to it, for external drift kriging.',
    'Доля наггета (от дисперсии)': '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.',
    'Блочный кригинг': 'Block kriging',
    'Дискретизация блока, N×N на ячейку': 'Block discretization, N×N per cell',
    'Оценивает СРЕДНЕЕ по ячейке грида, а не значение в её центре: каждая ячейка разбивается на N×N точек дискретизации, ковариации усредняются по блоку. Поверхность глаже, стандартная ошибка ниже точечной - подходит для оценки запасов и содержаний по блоку. Пробы при этом не воспроизводятся точно (среднее блока ≠ значение в точке). Выключено - обычный точечный кригинг.': 'Estimates the AVERAGE over the grid cell rather than the value at its centre: each cell is split into N×N discretization points and the covariances are averaged over the block. The surface is smoother and the standard error is lower than for point kriging - suitable for estimating reserves and grades over a block. Samples are then not reproduced exactly (the block average ≠ the value at a point). Off - ordinary point kriging.',
    'Сколько точек на сторону ячейки берётся для усреднения по блоку (всего N×N). 4×4 достаточно почти всегда; больше - точнее, но медленнее. Действует только при включённом блочном кригинге.': 'How many points per cell side are used to average over the block (N×N in total). 4×4 is almost always enough; more is more accurate but slower. Active only when block kriging is on.',
    'Блочный кригинг: дискретизация %d×%d на ячейку. Оценка - среднее по блоку, стандартная ошибка блочная (ниже точечной). Значения в узлах-пробах точно не воспроизводятся.': 'Block kriging: %d×%d discretization per cell. The estimate is the block average, the standard error is the block error (lower than point). Values at sample nodes are not reproduced exactly.',
    '2.3 Гидравлический градиент и направление потока': '2.3 Hydraulic gradient and flow direction',
    'Добавить поле напора (для градиента потока)': 'Add a head field (for flow gradient)',
    'Поле напора (head): региональный уклон + локальная вариация. Кригуйте head, затем подайте растр в «Гидравлический градиент и направление потока».': 'Head field (head): a regional slope plus local variation. Krige head, then feed the raster to "Hydraulic gradient and flow direction".',
    'Растр напора': 'Head raster',
    'Гидравлический градиент (модуль)': 'Hydraulic gradient (magnitude)',
    'Направление потока (азимут)': 'Flow direction (azimuth)',
    'Векторы потока (точки)': 'Flow vectors (points)',
    'Сглаживание напора перед расчётом, ячеек (0 = без)': 'Smooth head before computing, cells (0 = none)',
    'Векторы потока: шаг прореживания, ячеек': 'Flow vectors: thinning step, cells',
    'Не задан растр напора.': 'No head raster set.',
    'Не удалось открыть растр напора.': 'Could not open the head raster.',
    'В растре напора нет данных.': 'The head raster has no data.',
    'Растр напора %d x %d, ячейка %.4g x %.4g.': 'Head raster %d x %d, cell %.4g x %.4g.',
    'Сглаживание напора (σ=%g яч.)…': 'Smoothing the head (σ=%g cells)…',
    'Гидравлический градиент · %s': 'Hydraulic gradient · %s',
    'Направление потока · %s': 'Flow direction · %s',
    'Векторы потока · %s': 'Flow vectors · %s',
    'Векторов потока: %d (шаг %d яч.). Слой оформлен стрелками автоматически: поворот по полю «az», размер по «grad». Символику можно поменять в свойствах слоя.': 'Flow vectors: %d (step %d cells). The layer is styled as arrows automatically: rotation by the "az" field, size by "grad". You can change the symbology in the layer properties.',
    'По растру напора (пьезометрической поверхности) строит гидравлический градиент и направление потока. Вход - растр напора, например результат «2D Kriging» по уровням в скважинах.\n\nВыходы: растр модуля градиента |∇h| (безразмерный, м/м), растр азимута направления потока (компасный, 0 = север, вниз по градиенту) и точечный слой векторов потока для оформления стрелками (поля az - азимут, grad - градиент).\n\nЭто геометрия поля напора, без проницаемости: скорость фильтрации по Дарси (v = −K·∇h) требует коэффициента фильтрации K и здесь не считается. Изолинии напора стройте инструментом «Изолинии из растра».\n\nГрадиент усиливает шум грида - при пятнистом результате включите сглаживание (радиус в ячейках) или сгладьте напор в «2D Kriging».': 'From a head raster (the piezometric surface) builds the hydraulic gradient and the flow direction. The input is a head raster, for example the result of "2D Kriging" on borehole water levels.\n\nOutputs: a gradient-magnitude raster |∇h| (dimensionless, m/m), a flow-direction azimuth raster (compass, 0 = north, down-gradient) and a point layer of flow vectors to style with arrows (fields az - azimuth, grad - gradient).\n\nThis is the geometry of the head field, without permeability: the Darcy flow velocity (v = −K·∇h) needs the hydraulic conductivity K and is not computed here. Build head isolines with the "Isolines from raster" tool.\n\nThe gradient amplifies grid noise - if the result is patchy, turn on smoothing (radius in cells) or smooth the head in "2D Kriging".',
    'Растр кригинга': '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',
    '2.1 Категориальный индикаторный кригинг': '2.1 Categorical indicator kriging',
    'Вероятности минтипа': 'Mineral-type probabilities',
    'Вероятности по классам (многополосный)': 'Class probabilities (multiband)',
    'Добавить категориальное поле минтипа (демо замещения)': 'Add a categorical mineral-type field (replacement demo)',
    'Зоны минтипа': 'Mineral-type zones',
    'Карта зон (самый вероятный класс)': 'Zone map (most likely class)',
    'Категориальное поле (класс)': 'Categorical field (class)',
    'Класс «%s»: всего %d точек, индикаторная вариограмма будет шумной, вероятность по нему ненадёжна.': 'Class "%s": only %d points, the indicator variogram will be noisy and its probability unreliable.',
    'Классов: %d, точек: %d.': 'Classes: %d, points: %d.',
    'Коды зон: ': 'Zone codes: ',
    'Поле mintype (демо): ': 'Field mintype (demo): ',
    'Полосы растра вероятностей подписаны именами классов.': 'The probability raster bands are labelled with the class names.',
    'Сетка %d x %d, ячейка %.4g.': 'Grid %d x %d, cell %.4g.',
    'Слишком мало точек с заданным классом.': 'Too few points with a class value.',
    'Уверенность (макс. вероятность)': 'Confidence (max probability)',
    'Индикаторный кригинг по категориальному полю (минтип, литотип, класс). На каждый класс строится индикатор 0/1, кригуется отдельно (ядро GSLIB KB2D), оценка обрезается в 0-1, затем вероятности по классам нормируются к сумме 1. Кодом класса не кригуем: у категорий нет порядка.\n\nВыход: многополосный растр вероятностей (полоса на класс, в описании полосы - имя класса), растр зон (код самого вероятного класса, соответствие кодов в Журнале) и растр уверенности (максимум вероятности). Пустые и NULL исключаются. Вариограмма каждого индикатора подбирается автоматически (сферическая).': 'Indicator kriging on a categorical field (mineral type, lithotype, class). For each class a 0/1 indicator is built and kriged separately (GSLIB KB2D core), the estimate is clipped to 0-1, then the class probabilities are normalised to sum to 1. The class code is not kriged: categories have no order.\n\nOutputs: a multiband probability raster (one band per class, the class name in the band description), a zone raster (code of the most likely class, the mapping is printed to the log) and a confidence raster (maximum probability). Empty and NULL values are excluded. Each indicator variogram is fitted automatically (spherical).',
    'Стиль изолиний': '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',

    # --- Кригинг с внешним дрейфом (External Drift) ---
    '2.2 Кригинг с внешним дрейфом (External Drift)':
        '2.2 External Drift Kriging',
    'Растр внешнего дрейфа (известен всюду)':
        'External drift raster (known everywhere)',
    'Канал растра дрейфа': 'Drift raster band',
    'Степень дрейфа': 'Drift degree',
    '1 (линейный)': '1 (linear)',
    '2 (квадратичный)': '2 (quadratic)',
    'Растр кригинга с дрейфом': 'Drift kriging raster',
    'Кригинг+дрейф %s · %s': 'Kriging+drift %s · %s',
    'Сторонняя величина s, заданная растром во всей области: соседний пласт, '
    'структурная поверхность, грубая модель, сейсмический атрибут. Значение '
    'поля Z регрессируется на s, кригуются остатки, дрейф возвращается из '
    'растра. Растр должен покрывать область оценки и быть в той же системе '
    'координат, что и точки.':
        'A secondary variable s given as a raster across the whole area: an '
        'adjacent seam, a structural surface, a coarse model, a seismic '
        'attribute. The Z field is regressed on s, the residuals are kriged, '
        'and the drift is added back from the raster. The raster must cover '
        'the estimation area and share the CRS of the points.',
    'Связь значения с внешней величиной s. Степень 1 - линейный дрейф '
    'm = a0 + a1·s, обычный выбор для External Drift. Степень 2 описывает '
    'изогнутую связь m = a0 + a1·s + a2·s², но может вобрать часть реальной '
    'структуры в дрейф - после неё посмотрите на вариограмму остатков.':
        'The relation between the value and the external variable s. Degree 1 '
        'is the linear drift m = a0 + a1·s, the usual choice for external '
        'drift. Degree 2 describes a curved relation m = a0 + a1·s + a2·s², '
        'but may absorb part of the real structure into the drift - check the '
        'residual variogram after using it.',
    'Необязательный растр стандартной ошибки кригинга остатков (sqrt '
    'дисперсии): мера неопределённости. Дрейф детерминирован и своей '
    'погрешности к ней не добавляет.':
        'An optional raster of the residual kriging standard error (sqrt of '
        'variance): a measure of uncertainty. The drift is deterministic and '
        'adds no error of its own.',
    'Кригинг с внешним дрейфом (External Drift): оценка по точкам, когда поле '
    'закономерно связано со сторонней величиной, известной всюду в виде '
    'растра (структурная поверхность соседнего пласта, грубая региональная '
    'модель, сейсмический атрибут).\n\nДрейф снимается регрессией значения на '
    'растр, кригуются остатки, дрейф возвращается к оценке из того же растра. '
    'Это та же схема регрессия-кригинг, что и флажок «Снять полиномиальный '
    'тренд» у «2D Kriging», только дрейф здесь не функция координат, а функция '
    'внешнего значения. Степень дрейфа 1 (линейный) почти всегда '
    'достаточна.\n\nВариограмму задавайте по ОСТАТКАМ. Растр дрейфа и точки '
    'должны быть в одной системе координат. Ячейки вне покрытия растра дрейфа '
    'остаются пустыми. Поиск, анизотропия, обрезка и стандартная ошибка - как '
    'у «2D Kriging».':
        'External Drift Kriging: estimation from points when the field is '
        'systematically related to a secondary variable known everywhere as a '
        'raster (the structural surface of an adjacent seam, a coarse regional '
        'model, a seismic attribute).\n\nThe drift is removed by regressing '
        'the value on the raster, the residuals are kriged, and the drift is '
        'added back from the same raster. This is the same regression-kriging '
        'scheme as the "Remove polynomial trend" option of "2D Kriging", only '
        'here the drift is a function of the external value, not of the '
        'coordinates. Drift degree 1 (linear) is almost always '
        'enough.\n\nFit the variogram on the RESIDUALS. The drift raster and '
        'the points must share the CRS. Cells outside the drift raster '
        'coverage are left empty. Search, anisotropy, clipping and the '
        'standard error are as in "2D Kriging".',
    'Не удалось открыть растр дрейфа.': 'Could not open the drift raster.',
    'Не удалось прочитать растр дрейфа.': 'Could not read the drift raster.',
    'Не удалось пересчитать растр дрейфа на сетку кригинга.':
        'Could not resample the drift raster onto the kriging grid.',
    'Растр дрейфа и точки в разных системах координат. Совместите CRS, иначе '
    'выборка дрейфа в скважинах будет неверной.':
        'The drift raster and the points are in different coordinate systems. '
        'Match the CRS, otherwise the drift sampled at the wells will be '
        'wrong.',
    'Внешний дрейф отключён: точек со значением дрейфа %d, для модели нужно '
    'больше %d.':
        'External drift disabled: %d points carry a drift value, the model '
        'needs more than %d.',
    'Отброшено %d точек вне растра дрейфа (нет значения s).':
        '%d points outside the drift raster were dropped (no s value).',
    'Снят внешний дрейф степени %d: убрано %.1f%% дисперсии (s данных %.4g, '
    's остатка %.4g). Кригуются остатки, дрейф возвращается к оценке из '
    'растра. Вариограмму задавайте по остаткам.':
        'External drift of degree %d removed: %.1f%% of the variance taken '
        'out (s of data %.4g, s of residual %.4g). The residuals are kriged '
        'and the drift is added back from the raster. Fit the variogram on '
        'the residuals.',
    '%d ячеек оставлены пустыми: растр дрейфа их не покрывает.':
        '%d cells were left empty: the drift raster does not cover them.',
    'Добавить поверхность дрейфа и поле dz (для внешнего дрейфа)': 'Add a drift surface and a dz field (for external drift)',
    'Поверхность дрейфа (растр, демо)': 'Drift surface (raster, demo)',
    'Поверхность дрейфа (демо)': 'Drift surface (demo)',
    'Растр сторонней поверхности s, известной всюду: подаётся как дрейф в «Кригинг с внешним дрейфом», а поле dz скважин с ним линейно связано. Создаётся только при включённой галке поверхности дрейфа.':
        'A raster of a secondary surface s known everywhere: feed it as the drift to External Drift Kriging, while the wells dz field is linearly related to it. Created only when the drift-surface checkbox is on.',
    'Поверхность дрейфа (растр) и поле dz: dz линейно связано с поверхностью. Запустите «Кригинг с внешним дрейфом» по полю dz с этим растром как дрейфом - сравните с обычным «2D Kriging» по dz без дрейфа.':
        'Drift surface (raster) and dz field: dz is linearly related to the surface. Run External Drift Kriging on dz with this raster as the drift, and compare it with plain 2D Kriging on dz without the drift.',
    'Поверхность дрейфа (растр) + поле dz, для внешнего дрейфа': 'Drift surface (raster) + dz field, for external drift',
    'Включите этот вывод, чтобы получить пару для кригинга с внешним дрейфом: растр гладкой сторонней поверхности s (известна всюду) и поле dz скважин, линейно с ней связанное. Запустите «Кригинг с внешним дрейфом» по полю dz с этим растром как дрейфом. Если вывод пропущен, поле dz не добавляется. По умолчанию выключено.':
        'Enable this output to get a pair for external drift kriging: a raster of a smooth secondary surface s (known everywhere) and a wells dz field linearly related to it. Run External Drift Kriging on dz with this raster as the drift. If the output is skipped, the dz field is not added. Off by default.',
    '1. Грид и изолинии': '1. Grid and isolines',
    '2. Дополнительные инструменты': '2. Additional tools',
}
