From 8f95795bbb26dd4bc9a7633b2f0288b3f6fab890 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 4 Aug 2026 18:08:59 +0300 Subject: [PATCH] =?UTF-8?q?ui(tx):=20=D0=B2=D0=BA=D0=BB=D0=B0=D0=B4=D0=BA?= =?UTF-8?q?=D0=B0=20Transmit=20=D1=86=D0=B5=D0=BB=D0=B8=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D0=B0=D0=BD=D0=B3=D0=BB=D0=B8=D0=B9=D1=81?= =?UTF-8?q?=D0=BA=D0=BE=D0=BC=20+=20=D1=81=D0=B5=D1=82=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=B3=D1=80=D1=83=D0=BF=D0=BF=D1=8B=20Microphone?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Страница была единственной с русскими подписями — переведены подсказки всех четырёх подвкладок, надпись «Profile drive: N %» и диалоги профиля (New / Rename / Delete / Factory / лимит). Строковых литералов с кириллицей в SettingsForm больше нет. Группа Microphone приведена к сетке страницы: подписи в колонке PAD, поля в колонке CX (комбобокс Mic jack и спин Mic gain теперь в одной колонке), Connector переехал во вторую пару колонок к Mic gain — на не-Orion он скрыт и дыры не оставляет, поэтому отдельная третья строка не нужна (176 → 134 px). Тумблеры boost/bias/PTT расставлены с равным шагом; пара «Line In gain» занимает место чекбокса boost и заканчивается до «Mic bias». Английские подписи длиннее русских — все проверены рендером формы offscreen, в группы вписываются. Co-Authored-By: Claude Opus 5 --- SettingsForm.pas | 103 +++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 48 deletions(-) diff --git a/SettingsForm.pas b/SettingsForm.pas index 912e99a..54f99b8 100644 --- a/SettingsForm.pas +++ b/SettingsForm.pas @@ -1502,8 +1502,8 @@ begin with TLabel.Create(Self) do begin Parent := FPageTransmit; - Caption := 'Profile и EQ — содержимое активного TX-профиля; ' - + 'Hardware и Display — свойства устройства, от профиля не зависят.'; + Caption := 'Profile and EQ hold the active TX profile; ' + + 'Hardware and Display are radio properties and do not follow it.'; SetBounds(DpiScale(MARGIN), DpiScale(48), DpiScale(GRP_W), DpiScale(20)); Font.Name := UI_FONT; Font.Size := 9; @@ -1520,10 +1520,11 @@ begin FBtnTXProfDel := MkBtn(Grp, PAD + 514, R1, 100, 'Delete', BtnTXProfDelClick); FBtnTXProfFactory := MkBtn(Grp, PAD + 620, R1, 100, 'Factory', BtnTXProfFactoryClick); - MakeLbl(Grp, 'Правки на вкладках Profile и EQ пишутся в активный профиль сразу — ' - + 'отдельной кнопки «сохранить» нет.', PAD, R1 + 30, GRP_W - 2 * PAD); - MakeLbl(Grp, 'New... создаёт копию текущего звука под новым именем. ' - + 'Factory — заводской набор заново, эквалайзер в ноль.', + MakeLbl(Grp, 'Edits on the Profile and EQ tabs go into the active profile ' + + 'immediately — there is no separate Save button.', + PAD, R1 + 30, GRP_W - 2 * PAD); + MakeLbl(Grp, 'New... forks the current sound under a new name. ' + + 'Factory rebuilds the stock set and flattens the equalizer.', PAD, R1 + 48, GRP_W - 2 * PAD); // ---- Сегменты подвкладок ------------------------------------------------ @@ -1543,31 +1544,34 @@ begin SubPage(0, SubTop); // ---- Микрофонный вход (часть профиля: гарнитура vs микшер-ESSB) ---- - Grp := MakeGroupPanel(FTXSubPage[0], 'Microphone', MARGIN, 0, GRP_W, 176); + // Две строки, обе по общей сетке страницы: подпись в колонке PAD (ширина LW), + // поле в колонке CX, вторая пара — от PAD+320. Тумблеры справа с равным + // шагом. Connector скрыт на не-Orion и потому делит строку с Mic gain — + // спрятанная пара не оставляет дыры. + Grp := MakeGroupPanel(FTXSubPage[0], 'Microphone', MARGIN, 0, GRP_W, 134); - // Row 0: Mic jack selector | Boost (Mic In) или LineInGain (Line In) | Bias | PTT - MakeLbl(Grp, 'Mic jack', PAD, R1 + 5, 65); - FCmbTXMicJack := MkCmb(Grp, PAD + 68, R1, 110); + // Row 0: Mic jack | Boost (Mic In) либо Line In gain (Line In) | Bias | PTT + MakeLbl(Grp, 'Mic jack', PAD, R1 + 5, LW); + FCmbTXMicJack := MkCmb(Grp, CX, R1, 110); FCmbTXMicJack.Items.Add('Mic In'); FCmbTXMicJack.Items.Add('Line In'); FCmbTXMicJack.ItemIndex := 0; FCmbTXMicJack.OnChange := OnMicJackChange; - FChkTXMicBoost := MkChk(Grp, PAD + 190, R1, 165, 'Mic boost +20 dB'); - FLblLineInGain := MakeLbl(Grp, 'Line In gain', PAD + 190, R1 + 5, 80); - FEdLineInGain := MkFloat(Grp, PAD + 190 + 82, R1, 0.0, -34.5, 12.0, 1.5); + // Boost и пара «Line In gain» занимают одно и то же место (видима одна из них). + FChkTXMicBoost := MkChk(Grp, PAD + 302, R1, 170, 'Mic boost +20 dB'); + FLblLineInGain := MakeLbl(Grp, 'Line In gain', PAD + 302, R1 + 5, 76); + FEdLineInGain := MkFloat(Grp, PAD + 382, R1, 0.0, -34.5, 12.0, 1.5); FEdLineInGain.DecimalPlaces := 1; - FChkTXMicBias := MkChk(Grp, PAD + 375, R1, 105, 'Mic bias'); - FChkTXMicPTT := MkChk(Grp, PAD + 490, R1, 160, 'Mic-jack PTT'); + FChkTXMicBias := MkChk(Grp, PAD + 490, R1, 100, 'Mic bias'); + FChkTXMicPTT := MkChk(Grp, PAD + 596, R1, 130, 'Mic-jack PTT'); - // Row 1: Mic gain + // Row 1: Mic gain | Connector Tip/Ring (только Orion boards 4 и 5) MakeLbl(Grp, 'Mic gain (dB)', PAD, R1 + STEP + 5, LW); FEdTXMicGain := MkFloat(Grp, CX, R1 + STEP, 10.0, -20.0, 60.0, 0.5); - // Row 2: Connector Tip/Ring (только Orion boards 4 и 5). Стоит последним — - // на не-Orion строка скрыта и не оставляет дыру посреди группы. - FLblTipRing := MakeLbl(Grp, 'Connector', PAD, R1 + 2 * STEP + 5, 70); - FCmbTXMicTR := MkCmb(Grp, PAD + 73, R1 + 2 * STEP, 90); + FLblTipRing := MakeLbl(Grp, 'Connector', PAD + 302, R1 + STEP + 5, 76); + FCmbTXMicTR := MkCmb(Grp, PAD + 382, R1 + STEP, 96); FCmbTXMicTR.Items.Add('Tip'); // MicTipRing=False, bit3=0 FCmbTXMicTR.Items.Add('Ring'); // MicTipRing=True, bit3=1 FCmbTXMicTR.ItemIndex := 0; @@ -1575,15 +1579,15 @@ begin FCmbTXMicTR.Visible := False; // ---- Кромки TX-фильтра (FIR/фаза/окно — на вкладке Hardware) ---- - Y := 176 + 12; + Y := 134 + 12; Grp := MakeGroupPanel(FTXSubPage[0], 'TX Filter (bandpass)', MARGIN, Y, GRP_W, 108); MakeLbl(Grp, 'Low cut (Hz)', PAD, R1 + 5, LW); FEdTXFiltLow := MkSpin(Grp, CX, R1, 0, 8000, 200); MakeLbl(Grp, 'High cut (Hz)', PAD + 320, R1 + 5, 90); FEdTXFiltHigh := MkSpin(Grp, PAD + 320 + 100, R1, 100, 12000, 3100); - MakeLbl(Grp, 'Ширина полосы голоса. ESSB — просто High cut 3500..5000; ' - + 'знак боковой ставит движок, здесь всегда магнитуда.', + MakeLbl(Grp, 'Voice bandwidth. ESSB is simply a high cut of 3500..5000 Hz; ' + + 'sideband sign is applied by the engine, these are magnitudes.', PAD, R1 + 32, GRP_W - 2 * PAD); // ---- Динамическая обработка ---- @@ -1621,9 +1625,9 @@ begin MakeLbl(Grp, 'AM carrier level', PAD + 320, R1 + 5, 110); FEdTXAMCarrier := MkFloat(Grp, PAD + 320 + 120, R1, 0.5, 0.0, 1.0, 0.05); - FLblTXProfDrive := MakeLbl(Grp, 'Drive профиля: —', PAD, R1 + STEP + 5, 300); - MakeLbl(Grp, 'Мощность — часть профиля, но крутится ползунком DRV в главном окне: ' - + 'текущее значение уходит в активный профиль само.', + FLblTXProfDrive := MakeLbl(Grp, 'Profile drive: —', PAD, R1 + STEP + 5, 300); + MakeLbl(Grp, 'Drive belongs to the profile, but you set it with the DRV slider ' + + 'in the main window — the active profile follows it.', PAD, R1 + STEP + 28, GRP_W - 2 * PAD); FTXSubPage[0].Height := DpiScale(Y + 148 + 12); @@ -1646,13 +1650,15 @@ begin // Главное, что надо знать про этот EQ: точки — не «полосы», а узлы кривой, // и за крайними узлами WDSP обрывает АЧХ (см. WDSPEngine.PushTXEQProfile). - MakeLbl(Grp, 'Точки — узлы кривой: между ними интерполяция по дБ, ' - + 'за крайними точками АЧХ обрывается.', PAD, R1 + 332, GRP_W - 2 * PAD); - MakeLbl(Grp, 'Нижняя точка должна быть не выше нижней кромки TX-фильтра, ' - + 'верхняя — не ниже верхней, иначе EQ сам срежет полосу.', + MakeLbl(Grp, 'Points are curve nodes: the response is interpolated in dB ' + + 'between them and cut off beyond the outer ones.', + PAD, R1 + 332, GRP_W - 2 * PAD); + MakeLbl(Grp, 'Keep the lowest node at or below the TX filter low cut and the ' + + 'highest at or above the high cut, or the EQ will clip the passband.', PAD, R1 + 352, GRP_W - 2 * PAD); - MakeLbl(Grp, 'В режиме 3 полос частоты задаёт WDSP (150 / 1500 / 6000 Гц) — ' - + 'двигается только усиление.', PAD, R1 + 372, GRP_W - 2 * PAD); + MakeLbl(Grp, 'In 3-band mode the frequencies are fixed by WDSP ' + + '(150 / 1500 / 6000 Hz) — only the gains move.', + PAD, R1 + 372, GRP_W - 2 * PAD); FTXSubPage[1].Height := DpiScale(434 + 12); @@ -1667,8 +1673,9 @@ begin FEdTXAttOnTX := MkSpin(Grp, CX, R1, 0, 31, 31); MakeLbl(Grp, 'Tune tone (Hz)', PAD + 320, R1 + 5, 110); FEdTUNFreq := MkSpin(Grp, PAD + 320 + 120, R1, 100, 5000, 750); - MakeLbl(Grp, 'ATT on TX — ослабление RX-ADC на передаче (защита входа), ' - + 'не путать с мощностью.', PAD, R1 + 32, GRP_W - 2 * PAD); + MakeLbl(Grp, 'ATT on TX attenuates the RX ADC while transmitting (input ' + + 'protection) — not to be confused with output power.', + PAD, R1 + 32, GRP_W - 2 * PAD); Y := 108 + 12; Grp := MakeGroupPanel(FTXSubPage[2], 'TX Filter (DSP)', MARGIN, Y, GRP_W, 190); @@ -1689,8 +1696,8 @@ begin FCmbTXFiltWindow.Items.Add(WINDOW_NAMES[i]); FCmbTXFiltWindow.ItemIndex := 1; - MakeLbl(Grp, 'Крутизна и задержка тракта, а не тембр — поэтому вне профиля.', - PAD, R1 + 3 * STEP + 5, GRP_W - 2 * PAD); + MakeLbl(Grp, 'Skirt steepness and path latency, not timbre — hence outside ' + + 'the profile.', PAD, R1 + 3 * STEP + 5, GRP_W - 2 * PAD); Inc(Y, 190 + 12); Grp := MakeGroupPanel(FTXSubPage[2], 'FM / CTCSS', MARGIN, Y, GRP_W, 250); @@ -1712,8 +1719,8 @@ begin MakeLbl(Grp, 'Freq (Hz)', PAD + 230, R1 + 3 * STEP + 5, 80); FEdTXCTCSSFreq := MkFloat(Grp, PAD + 320, R1 + 3 * STEP, 100.0, 50.0, 300.0, 0.1); - MakeLbl(Grp, 'Свойство канала/репитера — профилем голоса не переключается.', - PAD, R1 + 4 * STEP + 5, GRP_W - 2 * PAD); + MakeLbl(Grp, 'A property of the channel or repeater — a voice profile does ' + + 'not switch it.', PAD, R1 + 4 * STEP + 5, GRP_W - 2 * PAD); FTXSubPage[2].Height := DpiScale(Y + 250 + 12); @@ -1934,12 +1941,12 @@ begin if FCmbTXProfile.Items.Count >= TXPROF_MAX then begin MessageDlg('TX Profile', - Format('Больше %d профилей на устройство не поддерживается.', [TXPROF_MAX]), + Format('No more than %d profiles per radio.', [TXPROF_MAX]), mtInformation, [mbOK], 0); Exit; end; S := 'Profile ' + IntToStr(FCmbTXProfile.Items.Count + 1); - if not InputQuery('TX Profile', 'Имя нового профиля (копия текущего звука):', S) then Exit; + if not InputQuery('TX Profile', 'Name for the new profile (copy of the current sound):', S) then Exit; if Trim(S) = '' then Exit; if Assigned(FOnTXProfileAdd) then FOnTXProfileAdd(Trim(S)); end; @@ -1951,7 +1958,7 @@ begin Idx := FCmbTXProfile.ItemIndex; if (Idx < 0) or (Idx >= FCmbTXProfile.Items.Count) then Exit; S := FCmbTXProfile.Items[Idx]; - if not InputQuery('TX Profile', 'Новое имя профиля:', S) then Exit; + if not InputQuery('TX Profile', 'New profile name:', S) then Exit; if Trim(S) = '' then Exit; if Assigned(FOnTXProfileRename) then FOnTXProfileRename(Idx, Trim(S)); end; @@ -1964,7 +1971,7 @@ begin // Последний профиль не удаляем — активному профилю всегда есть куда писать. if (Idx < 0) or (FCmbTXProfile.Items.Count <= 1) then Exit; if MessageDlg('TX Profile', - 'Удалить профиль «' + FCmbTXProfile.Items[Idx] + '»?', + 'Delete profile "' + FCmbTXProfile.Items[Idx] + '"?', mtConfirmation, [mbYes, mbNo], 0) <> mrYes then Exit; if Assigned(FOnTXProfileDelete) then FOnTXProfileDelete(Idx); end; @@ -1976,10 +1983,10 @@ procedure TSettingsForm.BtnTXProfFactoryClick(Sender: TObject); // не доехали бы до тех, у кого секция tx_profiles уже записана. begin if MessageDlg('TX Profile', - 'Заменить весь список профилей заводским набором?'#13#10 - + 'Свои профили и правки заводских будут потеряны.'#13#10 - + 'Активным станет «Default»: микрофон, полоса, динамика и мощность ' - + 'останутся как сейчас, эквалайзер вернётся в ноль.', + 'Replace the whole profile list with the factory set?'#13#10 + + 'Your own profiles and edits to the stock ones will be lost.'#13#10 + + '"Default" becomes active: microphone, bandwidth, dynamics and ' + + 'drive stay as they are, the equalizer returns to flat.', mtConfirmation, [mbYes, mbNo], 0) <> mrYes then Exit; if Assigned(FOnTXProfileFactory) then FOnTXProfileFactory(Self); end; @@ -2001,7 +2008,7 @@ begin if FBtnTXProfDel <> nil then FBtnTXProfDel.Enabled := FCmbTXProfile.Items.Count > 1; if FLblTXProfDrive <> nil then - FLblTXProfDrive.Caption := Format('Drive профиля: %d %%', [DrivePct]); + FLblTXProfDrive.Caption := Format('Profile drive: %d %%', [DrivePct]); finally FLoading := WasLoading; end; @@ -2010,7 +2017,7 @@ end; procedure TSettingsForm.SetTXProfileDrive(DrivePct: Integer); begin if FLblTXProfDrive <> nil then - FLblTXProfDrive.Caption := Format('Drive профиля: %d %%', [DrivePct]); + FLblTXProfDrive.Caption := Format('Profile drive: %d %%', [DrivePct]); end; procedure TSettingsForm.ShowTransmitPage(SubIdx: Integer = 0);