diff --git a/CHANGELOG.md b/CHANGELOG.md
index ed59360..782987a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
### 第九阶段:剧情与收尾
- 多语言:新增 de fr es pl ru ja 六种语言表(连同 zh en 共 8 种,对应游戏主菜单的语言)。英文表是源文,其他语言由 Gemini 分块译出(术语表 `docs/i18n-glossary.md` 在运营仓库,游戏已有的词用官方译名),未经人工校对,文件头有说明。键集合、占位符、`§ ¶ \\n` 标记由单元测试逐语言核对,非中日语言里不得出现汉字或假名。
+- 多语言布局:表格单元、按钮文字放不下时自动缩小字号(最小 68%)再省略,商品名限定两行内缩放;de fr es pl ru 的钱包表、手册章节列表、硬件钱包粘贴键按语言放宽;ru de 等少数过长标签改短(永续“加保证金”键、收益池列头)。
- 中文“匿名币”改称“隐私币”(英文 privacy coin),手册、黑市标签同步。
- 英文手册里写死的“六天”“7 天”改为占位符 `{BmBulkDays}`、`{AmlWindowDays}`,和中文一致。
- 手册里剩下的写死数字也进了 `Tuning`:出金审查污点系数 `AmlTaintMult` 与超额权重 `AmlExcessWeight`、出售速度界线 `BmSellFastMult` / `BmSellDay1Mult`;剧情联动的期限和涨幅改用已有的 `Story*` / `Tumbler*` 常量占位。占位符新增 `{Name:+%}`(倍数显示成涨幅)。
diff --git a/src/Decentralized/Core.cs b/src/Decentralized/Core.cs
index 77cc00d..683c150 100644
--- a/src/Decentralized/Core.cs
+++ b/src/Decentralized/Core.cs
@@ -14,6 +14,12 @@ namespace Decentralized
public static class L
{
public static string T(string key, params object[] args) => ModHelper.GetLocalized(ModInfo.Id, key, args);
+
+ /// 当前游戏语言代码(en zh de fr es pl ru ja)。
+ public static string Code => LocHelper.GetCurrentLocaleCode() ?? "en";
+
+ /// 译文普遍比中英文长的语言:表格列宽、操作键区按此放宽。
+ public static bool Wide { get { var c = Code; return c == "de" || c == "fr" || c == "es" || c == "pl" || c == "ru"; } }
}
public static class Log
diff --git a/src/Decentralized/HandbookWindow.cs b/src/Decentralized/HandbookWindow.cs
index d376621..1b81f3d 100644
--- a/src/Decentralized/HandbookWindow.cs
+++ b/src/Decentralized/HandbookWindow.cs
@@ -11,7 +11,9 @@ namespace Decentralized
{
public const string Id = "pd_handbook";
private const float WinW = 828f, WinH = 680f, ScreenW = 768f, ScreenH = 578f, Bezel = 6f;
- private const float ListW = 190f, TextW = 540f;
+ private static float ListW => L.Wide ? 276f : 190f;
+ private static float RowW => L.Wide ? ListW - 52f : ListW - 12f;
+ private static float TextW => L.Wide ? 456f : 540f;
private static int _chapter;
private static readonly List _picked = new List();
@@ -61,7 +63,7 @@ namespace Decentralized
for (int i = 0; i < chapters.Length; i++)
{
int k = i;
- PledgerSkin.TableRow(b, ListW - 12f, 30f, new[] { ListW - 12f }, new[] { TextAnchor.MiddleLeft },
+ PledgerSkin.TableRow(b, RowW, 30f, new[] { RowW }, new[] { TextAnchor.MiddleLeft },
new[] { Title(chapters[i]) }, i == _chapter, () => { _chapter = k; Open(); }, _rows, _clear);
}
b.End();
diff --git a/src/Decentralized/ModFiles/Localization/de.csv b/src/Decentralized/ModFiles/Localization/de.csv
index c21b997..0c94d79 100644
--- a/src/Decentralized/ModFiles/Localization/de.csv
+++ b/src/Decentralized/ModFiles/Localization/de.csv
@@ -498,7 +498,7 @@ perp.open,Eröffnen
perp.margin,Margin (CRC)
perp.preview,Nominal {0} Ausführung {1}
perp.do.open,Eröffnen
-perp.do.add,Margin hinzufügen
+perp.do.add,+ Margin
perp.do.close,Schließen
perp.opened,"{0} {1} eröffnet: Margin {2} CRC, {3}×."
perp.added,{0} CRC Margin hinzugefügt.
@@ -683,11 +683,11 @@ air.err.wallet,Mit der freigebenden Wallet signieren.
pool.h,Drittanbieter-Renditepools (CRC)
pool.none,Derzeit keine vorhanden.
pool.col.name,Pool
-pool.col.rate,Tageszins
+pool.col.rate,Zins
pool.col.reserve,Reserve
-pool.col.lock,Timelock
+pool.col.lock,Sperre
pool.col.audit,Audit
-pool.col.mine,Eigene
+pool.col.mine,Mein
pool.yes,ja
pool.no,nein
pool.pending,in Auszahlung
diff --git a/src/Decentralized/ModFiles/Localization/es.csv b/src/Decentralized/ModFiles/Localization/es.csv
index 4824417..2f10b9c 100644
--- a/src/Decentralized/ModFiles/Localization/es.csv
+++ b/src/Decentralized/ModFiles/Localization/es.csv
@@ -498,7 +498,7 @@ perp.open,Abrir
perp.margin,Margen (CRC)
perp.preview,Nocional {0} ejecución {1}
perp.do.open,Abrir
-perp.do.add,Agregar margen
+perp.do.add,+ Margen
perp.do.close,Cerrar
perp.opened,"Se abrió {0} {1}: margen {2} CRC, {3}×."
perp.added,Se agregaron {0} CRC de margen.
@@ -683,11 +683,11 @@ air.err.wallet,Firmar con la billetera que aprobó.
pool.h,Fondos de rendimiento de terceros (CRC)
pool.none,Ninguno por ahora.
pool.col.name,Fondo
-pool.col.rate,Tasa diaria
+pool.col.rate,Tasa/día
pool.col.reserve,Reserva
pool.col.lock,Bloqueo
pool.col.audit,Auditoría
-pool.col.mine,Mi depósito
+pool.col.mine,Mío
pool.yes,sí
pool.no,no
pool.pending,retirando
diff --git a/src/Decentralized/ModFiles/Localization/fr.csv b/src/Decentralized/ModFiles/Localization/fr.csv
index 06ae01c..d4d1000 100644
--- a/src/Decentralized/ModFiles/Localization/fr.csv
+++ b/src/Decentralized/ModFiles/Localization/fr.csv
@@ -498,7 +498,7 @@ perp.open,Ouvrir
perp.margin,Marge (CRC)
perp.preview,Notionnel {0} exécution {1}
perp.do.open,Ouvrir
-perp.do.add,Ajouter de la marge
+perp.do.add,+ Marge
perp.do.close,Fermer
perp.opened,"Position {0} {1} ouverte : marge {2} CRC, {3}×."
perp.added,{0} CRC de marge ajoutés.
@@ -687,7 +687,7 @@ pool.col.rate,Taux/j
pool.col.reserve,Réserve
pool.col.lock,Blocage
pool.col.audit,Audit
-pool.col.mine,Dépôt
+pool.col.mine,Mon dépôt
pool.yes,oui
pool.no,non
pool.pending,retrait en cours
diff --git a/src/Decentralized/ModFiles/Localization/pl.csv b/src/Decentralized/ModFiles/Localization/pl.csv
index d747e00..929e2df 100644
--- a/src/Decentralized/ModFiles/Localization/pl.csv
+++ b/src/Decentralized/ModFiles/Localization/pl.csv
@@ -406,7 +406,7 @@ poin.out.done,Wypłacono {0} {1} na {2}.
wallets.count,Portfele {0}/{1}
wallets.col.name,Nazwa
wallets.col.addr,Adres
-wallets.col.taint,Skażenie
+wallets.col.taint,Skażone
wallets.open,Otwórz
wallets.use,Połącz
wallets.current,Połączono
@@ -498,7 +498,7 @@ perp.open,Otwórz
perp.margin,Depozyt zabezpieczający (CRC)
perp.preview,Nominał {0} realizacja {1}
perp.do.open,Otwórz
-perp.do.add,Dodaj depozyt
+perp.do.add,+ Depozyt
perp.do.close,Zamknij
perp.opened,"Otwarto {0} {1}: depozyt {2} CRC, {3}×."
perp.added,Dodano {0} CRC depozytu.
diff --git a/src/Decentralized/ModFiles/Localization/ru.csv b/src/Decentralized/ModFiles/Localization/ru.csv
index 02e44b3..36efc50 100644
--- a/src/Decentralized/ModFiles/Localization/ru.csv
+++ b/src/Decentralized/ModFiles/Localization/ru.csv
@@ -154,7 +154,7 @@ avg.short,ср. покупка {0}
avg.none,—
col.asset,Актив
col.amount,Сумма
-col.value,Стоимость
+col.value,Оценка
col.avg,Ср. покупка
bank.cash.k,Кредиты
bank.rent.k,Аренда
@@ -406,7 +406,7 @@ poin.out.done,{0} {1} выведено на {2}.
wallets.count,Кошельки {0}/{1}
wallets.col.name,Название
wallets.col.addr,Адрес
-wallets.col.taint,Загрязнение
+wallets.col.taint,Грязные
wallets.open,Открыть
wallets.use,Подключить
wallets.current,Подключено
@@ -425,7 +425,7 @@ wallets.destroy.sure,Подтвердить
wallets.destroy.notempty,В {0} ещё есть монеты. Сначала выведите их.
wallets.destroyed,Уничтожен {0}: {1}
hw.balance.value,≈ {0}
-wallets.rename,Переименовать
+wallets.rename,Назвать
wallets.rename.h,Новое имя для {0}
wallets.rename.ok,ОК
hw.fee.slow,Медленно
@@ -498,7 +498,7 @@ perp.open,Открыть
perp.margin,Маржа (CRC)
perp.preview,Номинал {0} цена исполнения {1}
perp.do.open,Открыть
-perp.do.add,Добавить маржу
+perp.do.add,+ Маржа
perp.do.close,Закрыть
perp.opened,"Открыто {0} {1}: маржа {2} CRC, {3}×."
perp.added,Добавлено {0} CRC маржи.
@@ -685,7 +685,7 @@ pool.none,Сейчас пулов нет.
pool.col.name,Пул
pool.col.rate,Ставка
pool.col.reserve,Резерв
-pool.col.lock,Таймлок
+pool.col.lock,Лок
pool.col.audit,Аудит
pool.col.mine,Вклад
pool.yes,да
diff --git a/src/Decentralized/PledgerSkin.cs b/src/Decentralized/PledgerSkin.cs
index 27e4894..93a7f8e 100644
--- a/src/Decentralized/PledgerSkin.cs
+++ b/src/Decentralized/PledgerSkin.cs
@@ -123,6 +123,7 @@ namespace Decentralized
b.BeginPanel(w, height - 6f, align, 0f, 0f);
if (clear != null) clear.Add(b.Last.image);
b.AddLabel(i < texts.Length ? texts[i] : "");
+ FitCurrent(b);
b.End();
}
b.End();
@@ -142,12 +143,46 @@ namespace Decentralized
b.BeginPanel(w, height - 6f, align, 0f, 0f);
if (clear != null) clear.Add(b.Last.image);
b.AddLabel(i < headers.Length ? "" + headers[i] + "" : "");
+ FitCurrent(b);
b.End();
}
b.End();
b.End();
}
+ /// 单行固定宽度的文字放不下时先缩小字号(最小 68%),再省略:各语言译文长度不同,不靠逐语言调列宽。
+ public static void Fit(TMP_Text t)
+ {
+ if (t == null) return;
+ t.enableWordWrapping = false;
+ t.enableAutoSizing = true;
+ t.fontSizeMax = t.fontSize;
+ t.fontSizeMin = Mathf.Round(t.fontSize * 0.68f);
+ t.overflowMode = TextOverflowModes.Ellipsis;
+ }
+
+ /// 刚加的标签限定在固定高度内(可折行),放不下时缩小字号:商品名等多语言下长度差很大的标题用。
+ public static void FitBox(CustomUIBuilder b, float height)
+ {
+ var c = b.CurrentContainer;
+ if (c == null || c.childCount == 0) return;
+ var t = c.GetChild(c.childCount - 1).GetComponentInChildren(true);
+ if (t == null) return;
+ var le = t.gameObject.GetComponent() ?? t.gameObject.AddComponent();
+ le.minHeight = height; le.preferredHeight = height; le.flexibleHeight = 0f;
+ t.enableAutoSizing = true;
+ t.fontSizeMax = t.fontSize;
+ t.fontSizeMin = Mathf.Round(t.fontSize * 0.7f);
+ t.overflowMode = TextOverflowModes.Ellipsis;
+ }
+
+ /// 对当前容器(刚加完标签的单元面板)里的文字做 Fit。
+ public static void FitCurrent(CustomUIBuilder b)
+ {
+ if (b.CurrentContainer == null) return;
+ foreach (var t in b.CurrentContainer.GetComponentsInChildren(true)) Fit(t);
+ }
+
/// 应用整套 PLEDGER 皮肤:机身、边框、墨水屏、刻字、文字颜色、触控键、滚动条与数据表行。
public static void Apply(CustomUIWindow win, RectTransform screen, Image bezel, Image paper, ICollection picked, ICollection clear, IEnumerable rows = null)
{
@@ -230,6 +265,7 @@ namespace Decentralized
}
foreach (var t in btn.GetComponentsInChildren(true))
{
+ Fit(t);
t.color = on ? Ink : KeyText;
if (on) t.fontStyle |= FontStyles.Bold;
}
diff --git a/src/Decentralized/TerminalWindow.cs b/src/Decentralized/TerminalWindow.cs
index 4f36e80..3a6bce9 100644
--- a/src/Decentralized/TerminalWindow.cs
+++ b/src/Decentralized/TerminalWindow.cs
@@ -119,6 +119,7 @@ namespace Decentralized
b.BeginPanel(w, 26f, align, 0f, 0f);
_clear.Add(b.Last.image);
b.AddLabel(header ? "" + text + "" : text);
+ PledgerSkin.FitCurrent(b);
b.End();
}
@@ -984,7 +985,7 @@ namespace Decentralized
{
var d = Session.Data;
b.AddLabel(L.T("wallets.count", d.Wallets.Count, Tuning.WalletMax), "wallets_count_dim");
- var cols = new[] { 100f, 110f, 85f, 70f, 375f };
+ var cols = L.Wide ? new[] { 100f, 92f, 62f, 62f, 372f } : new[] { 100f, 110f, 85f, 70f, 375f };
var aligns = new[] { TextAnchor.MiddleLeft, TextAnchor.MiddleLeft, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleLeft };
TableHeader(b, 740f, cols, aligns, L.T("wallets.col.name"), L.T("wallets.col.addr"), L.T("col.value"), L.T("wallets.col.taint"), "");
for (int i = 0; i < d.Wallets.Count; i++)
@@ -1009,7 +1010,7 @@ namespace Decentralized
Cell(b, cols[3], Fmt.Credits(w.Taint), false, TextAnchor.MiddleRight);
b.End();
b.End();
- b.BeginPanel(cols[4] - 150f, 32f, TextAnchor.MiddleLeft, 0f, 0f);
+ b.BeginPanel(cols[4] - (L.Wide ? 112f : 150f), 32f, TextAnchor.MiddleLeft, 0f, 0f);
_clear.Add(b.Last.image);
b.BeginRow(4f, TextAnchor.MiddleLeft);
RowKey(b, L.T("wallets.open"), () => WalletWindow.Open(w));
@@ -1018,11 +1019,11 @@ namespace Decentralized
if (idx > 0) RowKey(b, _destroyPick == w.Address ? L.T("wallets.destroy.sure") : L.T("wallets.destroy"), () => DestroyWallet(w));
b.End();
b.End();
- b.BeginPanel(84f, 32f, TextAnchor.MiddleRight, 0f, 0f);
+ b.BeginPanel(L.Wide ? 92f : 84f, 32f, TextAnchor.MiddleRight, 0f, 0f);
_clear.Add(b.Last.image);
b.BeginRow(0f, TextAnchor.MiddleRight);
if (idx != d.Current) RowKey(b, L.T("wallets.use"), () => { d.Current = idx; Session.Save(); Open(); });
- else b.AddLabel(L.T("wallets.current"), "wallets_cur_dim");
+ else { b.AddLabel(L.T("wallets.current"), "wallets_cur_dim"); PledgerSkin.FitCurrent(b); }
b.End();
b.End();
b.End();
@@ -1754,6 +1755,7 @@ namespace Decentralized
var sprite = Icon(g.Item);
if (sprite != null) c.AddImage(sprite, 64f, 64f); else c.AddSpace(64f);
c.AddLabel("" + ItemName(g.Item) + "");
+ PledgerSkin.FitBox(c, 52f);
bool asic = g.Kind == GoodKind.Gpu && g.Model != null && Hardware.Specs.TryGetValue(g.Model, out var gs) && gs.Asic;
c.AddLabel(asic ? (g.Health >= 100 ? L.T("black.kind.asicnew") : L.T("black.kind.asic", (int)Math.Round(g.Health))) : g.Kind == GoodKind.Gpu ? (g.Health >= 100 ? L.T("black.kind.gpunew") : L.T("black.kind.gpu", (int)Math.Round(g.Health))) : L.T("black.kind." + g.Kind + (g.Kind == GoodKind.Contraband ? "." + g.Level : "")), "good_kind_dim");
if (!string.IsNullOrEmpty(line2)) c.AddLabel(line2, "good_line2_dim");
diff --git a/src/Decentralized/WalletWindow.cs b/src/Decentralized/WalletWindow.cs
index 727dcef..6fc024e 100644
--- a/src/Decentralized/WalletWindow.cs
+++ b/src/Decentralized/WalletWindow.cs
@@ -265,7 +265,7 @@ namespace Decentralized
b.AddHeader(L.T("hw.send"));
b.AddLabel(L.T("hw.to"));
b.BeginRow(6f, TextAnchor.MiddleLeft);
- b.BeginPanel(RowW - 70f, -1f, TextAnchor.MiddleLeft, 0f, 0f);
+ b.BeginPanel(RowW - (L.Wide ? 100f : 70f), -1f, TextAnchor.MiddleLeft, 0f, 0f);
_clear.Add(b.Last.image);
b.AddInput("0x", dev.To, s => dev.To = s, "to", s => dev.To = s);
b.End();