feat: RCON API transport, full furnidata translation with LibreTranslate fallback, remove organize feature, bump per-page limit to 500
- Add EMULATOR_MODE=api option with HTTP transport mirroring RCON payload - buildLocalizedFurniDataFiles now falls back to LibreTranslate for customs (incl. pl/ru/ar/ja) - Remove Organiseer import button from studio and Reorganize Catalog from import page - Delete organize API route and PUT handler; remove organizeCatalogAll from catalog-repair.ts - Increase imported-furni list perPage from 50 to 500
This commit is contained in:
1 parent
5668493485
commit
85b5792d40
8 files changed
+146
-768
No files matched your search
@@ -324,22 +324,50 @@ export async function buildLocalizedFurniDataFiles(): Promise<
|
||||
for (const section of ["roomitemtypes", "wallitemtypes"] as const) {
|
||||
const arr = cloned[section]?.furnitype;
|
||||
if (!Array.isArray(arr)) continue;
|
||||
// A language mapped to hotel "com" only carries English names,
|
||||
// so it must NOT be treated as a real translation — fall through
|
||||
// to LibreTranslate for those (pl/ru/ar/ja).
|
||||
const officialIsReal = lang === "en" || hotel !== "com";
|
||||
for (const entry of arr) {
|
||||
const cn =
|
||||
typeof entry.classname === "string" ? entry.classname : "";
|
||||
if (!cn) continue;
|
||||
const t = lookupTranslation(map, cn);
|
||||
if (!t) continue;
|
||||
// Only override when the translation carries content — empty
|
||||
// strings in official data would otherwise blank existing names.
|
||||
let didTranslate = false;
|
||||
if (t.name) {
|
||||
// Prefer the official Habbo translation when it carries content;
|
||||
// otherwise fall back to LibreTranslate (customs, or languages
|
||||
// whose hotel only provides English) so every entry gets a
|
||||
// localized name/description rather than staying English.
|
||||
if (officialIsReal && t?.name) {
|
||||
entry.name = t.name;
|
||||
didTranslate = true;
|
||||
} else if (
|
||||
lang !== "en" &&
|
||||
typeof entry.name === "string" &&
|
||||
entry.name.trim()
|
||||
) {
|
||||
const translated = await translateWithLibre(entry.name, lang);
|
||||
if (translated && translated !== entry.name) {
|
||||
entry.name = translated;
|
||||
didTranslate = true;
|
||||
}
|
||||
}
|
||||
if (t.description) {
|
||||
if (officialIsReal && t?.description) {
|
||||
entry.description = t.description;
|
||||
didTranslate = true;
|
||||
} else if (
|
||||
lang !== "en" &&
|
||||
typeof entry.description === "string" &&
|
||||
entry.description.trim()
|
||||
) {
|
||||
const translated = await translateWithLibre(
|
||||
entry.description,
|
||||
lang,
|
||||
);
|
||||
if (translated && translated !== entry.description) {
|
||||
entry.description = translated;
|
||||
didTranslate = true;
|
||||
}
|
||||
}
|
||||
if (didTranslate) {
|
||||
if (section === "roomitemtypes") translatedRoom++;
|
||||
@@ -361,6 +389,10 @@ export async function buildLocalizedFurniDataFiles(): Promise<
|
||||
await fs.rename(tmp, target);
|
||||
}
|
||||
|
||||
// Persist the LibreTranslate cache once per language so the next
|
||||
// full build reuses translations instead of re-calling the API.
|
||||
if (lang !== "en") await saveLibreCache();
|
||||
|
||||
results.push({
|
||||
lang,
|
||||
hotel,
|
||||
|
||||
Reference in new issue
Block a user