feat(i18n, agents, players): enhance localization and improve agent and player management interfaces
Some checks failed
lotteryadmin CI / build (push) Has been cancelled
Some checks failed
lotteryadmin CI / build (push) Has been cancelled
Updated localization files for English and Nepali, adding new entries and refining existing translations for better clarity. Enhanced the agent management interface with improved delegation features and child agent creation prompts. Improved player management functionalities, including confirmation dialogs for player actions and better handling of player creation and editing processes.
This commit is contained in:
236
scripts/merge-en-translations.mjs
Normal file
236
scripts/merge-en-translations.mjs
Normal file
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Merge missing English (en) i18n keys.
|
||||
* Usage: node scripts/merge-en-translations.mjs
|
||||
*/
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const root = path.join(__dirname, "..");
|
||||
const localesDir = path.join(root, "src/i18n/locales");
|
||||
|
||||
/** @type {Record<string, Record<string, string>>} */
|
||||
const translations = {
|
||||
"adminUsers.json": {
|
||||
roleListHint:
|
||||
"You can add custom roles and configure permissions. Built-in roles (super admin, site admin, site finance, site support, agent) cannot be deleted.",
|
||||
"rolePermissionDialog.packageHint":
|
||||
"Checking a module row on the left grants View only. Select Manage separately for data entry, close, draw, and other admin actions.",
|
||||
confirmSaveRolesTitle: "Save admin roles?",
|
||||
confirmSaveRolesDescription:
|
||||
"This updates role bindings for admin {{name}}; their console permissions will change accordingly.",
|
||||
confirmSaveAccountTitle: "Save admin account?",
|
||||
confirmSaveAccountCreateDescription: "This creates a new admin account and assigns the selected roles.",
|
||||
confirmSaveAccountEditDescription:
|
||||
"This updates account details for admin {{name}}, including status and password changes.",
|
||||
confirmSaveRolePermissionsTitle: "Save role permissions?",
|
||||
confirmSaveRolePermissionsDescription:
|
||||
"This updates feature permissions for role “{{name}}”. All admins bound to this role are affected immediately.",
|
||||
confirmSaveRoleTitle: "Save role details?",
|
||||
confirmSaveRoleCreateDescription: "This creates a new role {{name}}.",
|
||||
confirmSaveRoleEditDescription: "This updates the name, description, and status of role {{name}}.",
|
||||
},
|
||||
"agents.json": {
|
||||
"lineUi.profileReadOnlyHint":
|
||||
"Share, credit, and rebate are configured by your upline. Contact your parent agent or the platform to request changes.",
|
||||
"lineUi.selfAgentOverviewHint":
|
||||
"Credit below is allocated by your upline. Share and rebate are maintained upstream; this account cannot view or edit them.",
|
||||
"lineUi.overviewDownlineHint": "{{count}} direct downline agent(s). Manage them in the Downline tab.",
|
||||
"lineUi.playersUnavailableHint":
|
||||
"This agent cannot create players. Enable “Allow create player” in the agent profile first.",
|
||||
"lineUi.playersNoPermissionHint": "This account does not have player management permission on this node.",
|
||||
"lineUi.downlineColumns.email": "Email",
|
||||
"lineUi.downlineColumns.downlineCount": "Downline count",
|
||||
"lineUi.editCurrent": "Edit this agent",
|
||||
"lineUi.profileTabHint":
|
||||
"Maintain share, credit, rebate, and risk tags here. Use Account & status for login name and password.",
|
||||
"lineUi.nextSteps": "Suggested next steps",
|
||||
"lineUi.stepProfile": "Configure share, credit, and rebate",
|
||||
"lineUi.stepDownline": "Manage direct downline ({{count}} now)",
|
||||
"lineUi.stepPlayers": "Create or maintain direct players",
|
||||
"lineUi.downlineEmpty": "No direct downline yet. Child agents will appear here after creation.",
|
||||
"lineUi.downlineEmptyShort": "No direct downline yet.",
|
||||
"lineUi.sidebarShareRate": "Share {{rate}}%",
|
||||
"lineUi.sidebarAvailableCredit": "Available to grant {{amount}}",
|
||||
"lineUi.expand": "Expand",
|
||||
"lineUi.collapse": "Collapse",
|
||||
"profile.relativeShareRate": "Share rate (% of parent)",
|
||||
"profile.relativeShareRateValue": "{{rate}}% of parent",
|
||||
"profile.capabilityHint":
|
||||
"Takes effect on this agent’s primary account after save. If the platform Agent role included player/node management, login permissions are now tightened by these switches.",
|
||||
"profile.parentCaps": "Parent share {{share}}%, available to grant {{credit}}",
|
||||
"profile.availableCredit": "Available to grant {{amount}}",
|
||||
"profile.riskTags": "Risk tags",
|
||||
"profile.riskTagsPlaceholder": "Comma-separated, e.g. overdue, high_turnover",
|
||||
"profile.saveSuccess": "Share and credit settings saved",
|
||||
"settlementBills.platform": "Platform",
|
||||
"settlementBills.filteredByPeriod": "Showing bills for period #{{id}} only",
|
||||
"settlementBills.clearPeriodFilter": "Show all periods",
|
||||
"settlementBills.columns.party": "Party",
|
||||
"settlementBills.columns.counterparty": "Counterparty",
|
||||
"settlementBills.columns.grossWinLoss": "Win/Loss",
|
||||
"settlementBills.detail": "Details",
|
||||
"settlementBills.confirm": "Confirm bill",
|
||||
"settlementBills.confirmed": "Confirmed",
|
||||
"settlementBills.paymentAmount": "Payment amount",
|
||||
"settlementBills.recordPayment": "Record payment",
|
||||
"settlementBills.paid": "Payment recorded",
|
||||
"settlementBills.subtreeSummary": "Subtree summary",
|
||||
"settlementBills.grossWinLoss": "Win/Loss (gross_win_loss)",
|
||||
"settlementBills.rebateAmount": "Rebate",
|
||||
"settlementBills.shareProfit": "Share profit",
|
||||
"settlementBills.platformRounding": "Platform rounding",
|
||||
"settlementReports.title": "Period reports (credit share line)",
|
||||
"settlementReports.description":
|
||||
"Report set: player win/loss, agent share, rebate, credit, unpaid/overdue bills, and platform P/L.",
|
||||
"settlementReports.type": "Report type",
|
||||
"settlementReports.footnote":
|
||||
"These reports use credit-line period semantics, not legacy wallet commission/rebate reports.",
|
||||
"settlementReports.noPeriodHint":
|
||||
"When no specific period is selected, the last 7 days are used. Platform P/L requires a period.",
|
||||
"settlementReports.types.summary": "Summary",
|
||||
"settlementReports.types.player_win_loss": "Player win/loss",
|
||||
"settlementReports.types.agent_share": "Agent share",
|
||||
"settlementReports.types.rebate": "Rebate",
|
||||
"settlementReports.types.credit": "Credit",
|
||||
"settlementReports.types.unpaid_bills": "Unpaid bills",
|
||||
"settlementReports.types.overdue": "Overdue",
|
||||
"settlementReports.types.platform_pnl": "Platform P/L",
|
||||
"settlementReports.types.draw_period": "By draw",
|
||||
"settlementReports.summary.billCount": "Bill count",
|
||||
"settlementReports.summary.totalNet": "Total net",
|
||||
"settlementReports.summary.totalUnpaid": "Total unpaid",
|
||||
"settlementReports.summary.overdueCount": "Overdue bills",
|
||||
"settlementReports.summary.platformRounding": "Total platform rounding",
|
||||
"settlementReports.rebate.accrued": "Accrued",
|
||||
"settlementReports.rebate.inBill": "In bill",
|
||||
"settlementReports.rebate.settled": "Settled",
|
||||
"settlementReports.rebate.allocated": "Allocated",
|
||||
"settlementReports.credit.agents": "Agent credit",
|
||||
"settlementReports.credit.players": "Player credit",
|
||||
"settlementReports.platformPnl.periodRequired": "Select a specific period to view platform P/L.",
|
||||
"settlementReports.platformPnl.billNet": "Platform bill net",
|
||||
"settlementReports.platformPnl.rounding": "Rounding adjustment",
|
||||
"settlementReports.platformPnl.shareProfit": "Share profit (metadata)",
|
||||
"settlementReports.columns.player": "Player",
|
||||
"settlementReports.columns.gameType": "Play",
|
||||
"settlementReports.columns.grossWinLoss": "Win/Loss",
|
||||
"settlementReports.columns.rebate": "Rebate",
|
||||
"settlementReports.columns.agentId": "Agent ID",
|
||||
"settlementReports.columns.count": "Count",
|
||||
"settlementReports.columns.billId": "Bill",
|
||||
"settlementReports.columns.billType": "Type",
|
||||
"settlementReports.columns.unpaid": "Unpaid",
|
||||
"settlementReports.columns.status": "Status",
|
||||
"settlementReports.columns.overdueDays": "Overdue days",
|
||||
"settlementReports.columns.drawNo": "Draw no.",
|
||||
"settlementReports.columns.code": "Code",
|
||||
"settlementReports.columns.name": "Name",
|
||||
"settlementReports.columns.creditLimit": "Credit limit",
|
||||
"settlementReports.columns.allocated": "Allocated",
|
||||
"settlementReports.columns.available": "Available",
|
||||
"settlementReports.columns.used": "Used",
|
||||
"settlementReports.columns.frozen": "Frozen",
|
||||
"settlementReports.columns.rebateType": "Rebate type",
|
||||
"settlementReports.columns.amount": "Amount",
|
||||
"settlementPeriods.title": "Agent periods",
|
||||
"settlementPeriods.presetHint": "Quick period presets (recommended)",
|
||||
"settlementPeriods.openWithPreset": "Apply quick preset",
|
||||
"settlementPeriods.showAdvanced": "Custom start/end dates",
|
||||
"settlementPeriods.hideAdvanced": "Hide custom dates",
|
||||
"settlementPeriods.range": "Period",
|
||||
"settlementPeriods.empty": "No periods yet. Choose a quick preset and open a period.",
|
||||
"settlementPeriods.start": "Start",
|
||||
"settlementPeriods.end": "End",
|
||||
"settlementPeriods.status": "Status",
|
||||
"settlementPeriods.close": "Close period and generate bills",
|
||||
"settlementPeriods.viewBills": "Bills",
|
||||
"settlementPeriods.opened": "Period opened",
|
||||
"settlementPeriods.closed": "Period closed; bills generated",
|
||||
"settlementPeriods.closeFailed": "Failed to close period",
|
||||
"lineProvision.siteCode": "Integration site",
|
||||
"lineProvision.siteCodePlaceholder": "Select site",
|
||||
"lineProvision.siteRequired": "Select an integration site",
|
||||
"lineProvision.noUnboundSite": "No sites without a level-1 agent",
|
||||
"lineProvision.openIntegrationSites": "Go to integration sites",
|
||||
"lineProvision.passwordHint": "At least 8 characters",
|
||||
"playersPanel.siteCode": "Line site",
|
||||
"playersPanel.passwordHint": "At least 8 characters",
|
||||
"playersPanel.passwordMinLength": "Initial password must be at least 8 characters",
|
||||
"playersPanel.creditLimitInvalid": "Credit limit must be an integer ≥ 0",
|
||||
"playersPanel.creditLimitExceeded": "Credit limit cannot exceed this agent’s available grant",
|
||||
"playersPanel.rebateRateInvalid": "Rebate rate must be between 0 and 100%",
|
||||
"playersPanel.fundingMode": "Funding mode",
|
||||
"playersPanel.authSource": "Auth source",
|
||||
"playersPanel.rebateInherited": "Inherit agent default rebate",
|
||||
"playersPanel.creditListHint":
|
||||
"Credit line: below shows player credit limits and available credit, not main-site wallet balance.",
|
||||
"playersPanel.playerRef": "Player ref",
|
||||
"playersPanel.usernameNickname": "Username / nickname",
|
||||
"playersPanel.creditLimitAvailable": "Credit limit / available",
|
||||
"roles.selectedCount": "{{selected}} / {{total}} selected",
|
||||
"roles.groupSelectedCount": "{{selected}} / {{total}}",
|
||||
"roles.selectGroup": "Select all in group",
|
||||
"roles.noAssignablePermissions": "No permissions available to assign",
|
||||
},
|
||||
"config.json": {
|
||||
"integrationSites.columns.currency": "Currency",
|
||||
"integrationSites.columns.lineRoot": "Level-1 agent",
|
||||
"integrationSites.columns.h5Url": "Lottery H5",
|
||||
"integrationSites.columns.ssoSecret": "SSO secret",
|
||||
"integrationSites.columns.walletApiKey": "Wallet API key",
|
||||
"integrationSites.lineRootBound": "Bound",
|
||||
"integrationSites.lineRootUnbound": "Unbound",
|
||||
"integrationSites.secretNotConfigured": "Secret not configured",
|
||||
"integrationSites.secretCopyRequiresManage":
|
||||
"Integration site manage permission is required to copy secrets",
|
||||
},
|
||||
"jackpot.json": {
|
||||
confirmSavePoolTitle: "Save jackpot pool settings?",
|
||||
confirmSavePoolDescription:
|
||||
"This updates fill rate, thresholds, payout ratio, and related parameters (not pool balance). Use Balance adjustment for balance changes.",
|
||||
},
|
||||
"players.json": {
|
||||
rebateRate: "Rebate",
|
||||
riskTags: "Risk tags",
|
||||
},
|
||||
};
|
||||
|
||||
function setNested(obj, dotKey, value) {
|
||||
const parts = dotKey.split(".");
|
||||
let cur = obj;
|
||||
for (let i = 0; i < parts.length - 1; i++) {
|
||||
if (!(parts[i] in cur) || typeof cur[parts[i]] !== "object" || Array.isArray(cur[parts[i]])) {
|
||||
cur[parts[i]] = {};
|
||||
}
|
||||
cur = cur[parts[i]];
|
||||
}
|
||||
cur[parts[parts.length - 1]] = value;
|
||||
}
|
||||
|
||||
function sortKeysDeep(value) {
|
||||
if (Array.isArray(value)) return value;
|
||||
if (value && typeof value === "object") {
|
||||
return Object.fromEntries(
|
||||
Object.keys(value)
|
||||
.sort()
|
||||
.map((k) => [k, sortKeysDeep(value[k])]),
|
||||
);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
let merged = 0;
|
||||
for (const [file, keys] of Object.entries(translations)) {
|
||||
const enPath = path.join(localesDir, "en", file);
|
||||
const en = JSON.parse(fs.readFileSync(enPath, "utf8"));
|
||||
for (const [dotKey, enValue] of Object.entries(keys)) {
|
||||
setNested(en, dotKey, enValue);
|
||||
merged++;
|
||||
}
|
||||
fs.writeFileSync(enPath, `${JSON.stringify(sortKeysDeep(en), null, 2)}\n`, "utf8");
|
||||
console.log(`Updated ${file} (+${Object.keys(keys).length} keys)`);
|
||||
}
|
||||
console.log(`Total merged: ${merged}`);
|
||||
Reference in New Issue
Block a user