multilingual.class.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. <?php
  2. if (!defined('IN_ONLINE')) {
  3. exit('Access Denied');
  4. }
  5. /**
  6. * Description of multilingual
  7. *
  8. * @author Administrator
  9. */
  10. class multilingual{
  11. private static $_multilingual;
  12. function __construct() {
  13. }
  14. public static function getInstance() {
  15. global $memory_limit;
  16. $memory_limit = ini_get("memory_limit");
  17. ini_set("memory_limit", '2048M');
  18. if (!self::$_multilingual) {
  19. $c = __CLASS__;
  20. self::$_multilingual = new $c;
  21. }
  22. return self::$_multilingual;
  23. }
  24. public function multilingual_config() {
  25. $operate = utils::_get('operate');
  26. $operate = strtolower($operate);
  27. /*
  28. * multilingual_page_load
  29. */
  30. if ($operate == "multilingual_page") {
  31. //查询指定语言
  32. $langIds = [];
  33. $langkey = $_POST['langkey'];
  34. // 1. 统一处理 $langs 数组
  35. if (empty($langkey) || strtoupper($langkey) == "ALL") {
  36. // 如果没传或传 ALL,直接查询所有激活语言的 ID
  37. // 优化点:直接查 id,不需要先查 key 再查 id
  38. $langSql = "SELECT id FROM kln_i18n_languages";
  39. $langRows = common::excuteListSql($langSql);
  40. if ($langRows) {
  41. $langIds = array_column($langRows, 'id');
  42. }
  43. } else {
  44. // 2. 如果指定了语言,使用 IN 查询一次性获取
  45. $langs = explode(',', $langkey);
  46. // 安全过滤:防止 SQL 注入,并确保只处理非空字符串
  47. $safeLangs = array();
  48. foreach ($langs as $l) {
  49. $l = trim($l);
  50. if (!empty($l)) {
  51. $safeLangs[] = "'" . common::check_input($l) . "'";
  52. }
  53. }
  54. if (!empty($safeLangs)) {
  55. // 拼接 IN 条件:('english', 'french')
  56. $inClause = implode(',', $safeLangs);
  57. $langSql = "SELECT id FROM kln_i18n_languages WHERE lang_key IN ($inClause)";
  58. $langRows = common::excuteListSql($langSql);
  59. if ($langRows) {
  60. $langIds = array_column($langRows, 'id');
  61. }
  62. }
  63. }
  64. $pageData = $this->_loadPageInfo($langIds);
  65. $langData = $this->_loadLangInfo($langIds);
  66. common::echo_json_encode(200,array("pageData" =>$pageData,"langData" =>$langData));
  67. }
  68. /*
  69. * multilingual_load
  70. */
  71. if ($operate == "multilingual_init") {
  72. $this->_multilingual_init();
  73. }
  74. if ($operate == "multilingual_search") {
  75. $result = $this->_multilingual_search();
  76. common::echo_json_encode(200,$result);
  77. }
  78. /*
  79. * multilingual_save
  80. */
  81. if ($operate == "multilingual_save") {
  82. $multilingual_param = $_POST['multilingual_param'];
  83. $this->_multilingual_save($multilingual_param);
  84. }
  85. if ($operate == "load_all_pages_by_lang") {
  86. $langkey = common::check_input($_POST['langkey']);
  87. $this->_loadAllPagesByLang($langkey);
  88. }
  89. }
  90. private function _multilingual_init() {
  91. // 1. 获取并解析 JSON 数据
  92. $sql = "select * from public.kln_i18n_pages_init where id = 2";
  93. $data = common::excuteObjectSql($sql);
  94. $rawData = $data['data'];
  95. $rawDataArr = json_decode($rawData, true);
  96. if (!$rawDataArr) {
  97. common::echo_json_encode(500, "Invalid JSON format");
  98. exit();
  99. }
  100. foreach($rawDataArr as $_rawDataArr){
  101. $mode = 'update';
  102. $json = $_rawDataArr;
  103. // 获取控制模式,默认为 'update'
  104. $mode = $mode == 'replace' ? 'replace' : 'update';
  105. $pageKey = isset($json['page']) ? common::check_input($json['page']) : '';
  106. $unverifiedNumber = isset($json['unverifiedNumber']) ? intval($json['unverifiedNumber']) : 0;
  107. $dataList = isset($json['data']) ? $json['data'] : [];
  108. //tracking report booking destinationDelivery
  109. if (empty($pageKey)) {
  110. common::echo_json_encode(500, "Missing page key");
  111. exit();
  112. }
  113. // 2. 定义语言映射配置
  114. $langMap = [
  115. 'traditionalChinese' => ['name' => '繁体中文', 'code' => 'zh-TW'],
  116. 'simplifiedChinese' => ['name' => '简体中文', 'code' => 'zh-CN'],
  117. 'english' => ['name' => '英语', 'code' => 'en-US'],
  118. 'french' => ['name' => '法语', 'code' => 'fr-FR'],
  119. 'spanish' => ['name' => '西班牙语', 'code' => 'es-ES'],
  120. 'portuguese' => ['name' => '葡萄牙语', 'code' => 'pt-BR']
  121. ];
  122. global $db;
  123. $db->StartTrans();
  124. try {
  125. // 第一步:处理页面表 (kln_i18n_pages)
  126. $pageId = null;
  127. // --- 模式判断:如果是覆盖模式,先删除旧数据 ---
  128. if ($mode === 'replace') {
  129. // 1. 先删子表 (kln_i18n_keys)
  130. $kikSqlDelete = "DELETE FROM kln_i18n_keys WHERE page_id IN (SELECT id FROM kln_i18n_pages WHERE page_key = '$pageKey')";
  131. $db->Execute($kikSqlDelete) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $kikSqlDelete), 0));
  132. // 2. 再删主表 (kln_i18n_pages) - 虽然上面删了子表,这里为了保险或者重置页面信息也可以删,
  133. $delPageSql = "DELETE FROM kln_i18n_pages WHERE page_key = '$pageKey'";
  134. $db->Execute($delPageSql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $delPageSql), 0));
  135. }
  136. // --- 查询页面是否存在 ---
  137. $checkPageSql = "SELECT id FROM kln_i18n_pages WHERE page_key = '$pageKey'";
  138. $checkPageRes = $db->GetRow($checkPageSql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $checkPageSql), 0));
  139. if (!empty($checkPageRes)) {
  140. // 存在 -> 更新
  141. $pageId = $checkPageRes['id'];
  142. $updatePageSql = "UPDATE kln_i18n_pages SET unverified_number = $unverifiedNumber WHERE id = $pageId";
  143. $db->Execute($updatePageSql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $updatePageSql), 0));
  144. } else {
  145. // 不存在 -> 插入
  146. $insertPageSql = "INSERT INTO kln_i18n_pages (page_key, unverified_number, description) VALUES ('$pageKey', $unverifiedNumber, '')";
  147. $db->Execute($insertPageSql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $insertPageSql), 0));
  148. // 获取新生成的 ID (PostgreSQL)
  149. $seqSql = "SELECT currval('kln_i18n_pages_id_seq')";
  150. $pageIdRow = $db->GetRow($seqSql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $seqSql), 0));
  151. $pageId = $pageIdRow['currval'];
  152. }
  153. // 第二步:循环处理数据
  154. foreach ($dataList as $item) {
  155. $transKey = $item['key'];
  156. $originValue = isset($item['originEnglish']) ? $item['originEnglish'] : '';
  157. foreach ($langMap as $jsonKey => $langInfo) {
  158. // 只处理 JSON 中存在的数据
  159. if (isset($item[$jsonKey])) {
  160. $transValue = common::check_input($item[$jsonKey]);
  161. $statusKey = $jsonKey . 'Status';
  162. $status = isset($item[$statusKey]) ? intval($item[$statusKey]) : 0;
  163. // --- 1. 处理语言表 (kln_i18n_languages) ---
  164. $langKey = common::check_input($jsonKey);
  165. $langName = common::check_input($langInfo['name']);
  166. $localeCode = common::check_input($langInfo['code']);
  167. // 查询语言是否存在
  168. $checkLangSql = "SELECT id FROM kln_i18n_languages WHERE lang_key = '$langKey'";
  169. $checkLangRes = $db->GetRow($checkLangSql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $checkLangSql), 0));
  170. if (!empty($checkLangRes)) {
  171. // 存在 -> 更新
  172. $langId = $checkLangRes['id'];
  173. $updateLangSql = "UPDATE kln_i18n_languages SET lang_name = '$langName', locale_code = '$localeCode' WHERE id = $langId";
  174. $db->Execute($updateLangSql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $updateLangSql), 0));
  175. } else {
  176. // 不存在 -> 插入
  177. $insertLangSql = "INSERT INTO kln_i18n_languages (lang_key, lang_name, locale_code, is_active) VALUES ('$langKey', '$langName', '$localeCode', true)";
  178. $db->Execute($insertLangSql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $updateLangSql), 0));
  179. // 获取 ID
  180. $seqLangSql = "SELECT currval('kln_i18n_languages_id_seq')";
  181. $langIdRow = $db->GetRow($seqLangSql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $seqLangSql), 0));
  182. $langId = $langIdRow['currval'];
  183. }
  184. // --- 2. 处理词条表 (kln_i18n_keys) ---
  185. // 查询词条是否存在
  186. $checkKeySql = "SELECT id FROM kln_i18n_keys WHERE page_id = $pageId AND lang_id = $langId AND trans_key = '$transKey'";
  187. $checkKeyRes = $db->GetRow($checkKeySql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $checkKeySql), 0));
  188. if (!empty($checkKeyRes)) {
  189. // 存在 -> 更新
  190. $updateKeySql = "UPDATE kln_i18n_keys SET trans_value = '$transValue', orgin_value = '$originValue', status = $status WHERE id = " . $checkKeyRes['id'];
  191. $db->Execute($updateKeySql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $updateKeySql), 0));
  192. } else {
  193. // 不存在 -> 插入
  194. $insertKeySql = "INSERT INTO kln_i18n_keys (page_id, lang_id, trans_key, trans_value, orgin_value, status) VALUES ($pageId, $langId, '$transKey', '$transValue', '$originValue', $status)";
  195. $db->Execute($insertKeySql) or ( (!$db->ErrorMsg()) or error_log(common::dbLog($db, $insertKeySql), 0));
  196. }
  197. }
  198. }
  199. }
  200. } catch (Exception $e) {
  201. // 捕获异常,标记错误,以便回滚
  202. error_log("Exception in multilingual_init: " . $e->getMessage());
  203. }
  204. // 结束事务
  205. if ($db->CompleteTrans() === FALSE) {
  206. $msg = 'Save Error';
  207. } else {
  208. $msg = 'Save Success';
  209. }
  210. }
  211. common::echo_json_encode(200, $msg);
  212. exit();
  213. }
  214. /**
  215. * 根据传入的 page_key 查询多语言信息并组装成 JSON 格式
  216. * 支持多个页面查询,将所有数据整合到一个 data 数组中
  217. *
  218. * @param string|array $pageKey 页面标识 (例如 'login' 或 ['login', 'register'])
  219. * @return array 返回组装好的数组 (通常最后会 json_encode 输出)
  220. */
  221. public function _multilingual_search() {
  222. $pageKey = $_POST['pagekey'];
  223. $pageIds = [];
  224. // 1. 统一处理 $pageIds 数组
  225. if (empty($pageKey) || strtoupper($pageKey) == "ALL") {
  226. // 如果没传或传 ALL,直接查询所有页面的 ID
  227. $pageSql = "SELECT id FROM kln_i18n_pages";
  228. $pageRows = common::excuteListSql($pageSql);
  229. if ($pageRows) {
  230. $pageIds = array_column($pageRows, 'id');
  231. }
  232. } else {
  233. // 2. 如果指定了页面,使用 IN 查询一次性获取
  234. $pages = explode(',', $pageKey);
  235. // 安全过滤:防止 SQL 注入,并确保只处理非空字符串
  236. $safePages = array();
  237. foreach ($pages as $p) {
  238. $p = trim($p);
  239. if (!empty($p)) {
  240. $safePages[] = "'" . common::check_input($p) . "'";
  241. }
  242. }
  243. if (!empty($safePages)) {
  244. $inClause = implode(',', $safePages);
  245. // 优化点:一次查询获取所有匹配的 ID 和 unverified_number
  246. $pageSql = "SELECT id, unverified_number FROM kln_i18n_pages WHERE page_key IN ($inClause)";
  247. $pageRows = common::excuteListSql($pageSql);
  248. if ($pageRows) {
  249. $pageIds = array_column($pageRows, 'id');
  250. }
  251. }
  252. }
  253. // 3. 如果没有找到任何页面,返回空数组
  254. if (empty($pageIds)) {
  255. return array();
  256. }
  257. //查询指定语言
  258. $langIds = [];
  259. $langkey = $_POST['langKey'];
  260. // 1. 统一处理 $langs 数组
  261. if (empty($langkey) || strtoupper($langkey) == "ALL") {
  262. // 如果没传或传 ALL,直接查询所有激活语言的 ID
  263. // 优化点:直接查 id,不需要先查 key 再查 id
  264. $langSql = "SELECT id FROM kln_i18n_languages";
  265. $langRows = common::excuteListSql($langSql);
  266. if ($langRows) {
  267. $langIds = array_column($langRows, 'id');
  268. }
  269. } else {
  270. // 2. 如果指定了语言,使用 IN 查询一次性获取
  271. $langs = explode(',', $langkey);
  272. // 安全过滤:防止 SQL 注入,并确保只处理非空字符串
  273. $safeLangs = array();
  274. foreach ($langs as $l) {
  275. $l = trim($l);
  276. if (!empty($l)) {
  277. $safeLangs[] = "'" . common::check_input($l) . "'";
  278. }
  279. }
  280. if (!empty($safeLangs)) {
  281. // 拼接 IN 条件:('english', 'french')
  282. $inClause = implode(',', $safeLangs);
  283. $langSql = "SELECT id FROM kln_i18n_languages WHERE lang_key IN ($inClause)";
  284. $langRows = common::excuteListSql($langSql);
  285. if ($langRows) {
  286. $langIds = array_column($langRows, 'id');
  287. }
  288. }
  289. }
  290. // 4. 查询所有指定页面的翻译词条(一次查询获取所有数据)
  291. $sql = "SELECT
  292. k.trans_key,
  293. k.trans_value,
  294. k.status,
  295. k.orgin_value,
  296. l.lang_key,
  297. p.page_key AS key_page
  298. FROM kln_i18n_keys k
  299. JOIN kln_i18n_languages l ON k.lang_id = l.id
  300. JOIN kln_i18n_pages p ON k.page_id = p.id
  301. WHERE k.page_id IN (" . implode(',', $pageIds) . ")
  302. AND k.lang_id IN (" . implode(',', $langIds) . ")
  303. ORDER BY k.trans_key, p.page_key";
  304. $rows = common::excuteListSql($sql);
  305. if ($rows === FALSE) {
  306. return array();
  307. }
  308. // 5. 数据重组(核心逻辑)
  309. $dataMap = array();
  310. foreach ($rows as $row) {
  311. $key = $row['trans_key'];
  312. $langKey = $row['lang_key'];
  313. // 如果这个 key 还没初始化,先初始化
  314. $mapKey = $key.':'.$row['key_page'];
  315. //$mapKey = $key;
  316. if (!isset($dataMap[$mapKey])) {
  317. $dataMap[$mapKey] = array(
  318. 'key' => $key,
  319. 'key_page' => $row['key_page'] // 记录所属页面
  320. );
  321. }
  322. // 动态填充语言字段
  323. $dataMap[$mapKey][$langKey] = $row['trans_value'];
  324. // 填充状态字段
  325. $dataMap[$mapKey][$langKey . 'Status'] = intval($row['status']);
  326. // 填充原始值(如果有)
  327. //if (!empty($row['orgin_value'])) {
  328. $dataMap[$mapKey]['orginEnglish'] = $row['orgin_value'];
  329. //}
  330. }
  331. // 6. 将 Map 转换为数组列表
  332. $dataList = array_values($dataMap);
  333. // 7. 组装最终结果
  334. $result = array(
  335. 'page' => $pageKey,
  336. 'data' => $dataList
  337. );
  338. //重新查询一下page load
  339. $pageData = $this->_loadPageInfo($langIds);
  340. $result['pageData'] = $pageData;
  341. //langIds传空,意思是查全部语言
  342. $langData = $this->_loadLangInfo(null,$pageIds);
  343. $result['langData'] = $langData;
  344. return $result;
  345. }
  346. /**
  347. * 保存多语言数据
  348. *
  349. * @param array $multilingual_param 页面未审核数量参数,格式:[{unverifiedNumber: 3, page: 'login'}, ...]
  350. * @param array $multilingual_trans_param 翻译状态参数,格式:[{page: 'login', lang: 'traditionalChinese', trans_key: 'username', status: 1}, ...]
  351. * @return bool 是否保存成功
  352. */
  353. public function _multilingual_save($multilingual_param) {
  354. global $db;
  355. try {
  356. // 开启事务确保数据一致性
  357. $db->StartTrans();
  358. //2. 处理翻译词条状态更新
  359. foreach ($multilingual_param as $param) {
  360. $pageKey = common::check_input($param['page']);
  361. $langKey = common::check_input($param['lang']);
  362. $transKey = common::check_input($param['trans_key']);
  363. $trans_value = common::check_input($param['trans_value']);
  364. $status = $param['status'];
  365. // 查询页面ID
  366. $pageSql = "SELECT id FROM kln_i18n_pages WHERE page_key = '".$pageKey."'";
  367. $pageId = $db->GetOne($pageSql);
  368. if (!$pageId) {
  369. throw new Exception("Page not found: " . $pageKey);
  370. }
  371. // 查询语言ID
  372. $langSql = "SELECT id FROM kln_i18n_languages WHERE lang_key = '".$langKey."'";
  373. $langId = $db->GetOne($langSql);
  374. if (!$langId) {
  375. throw new Exception("Language not found: " . $langKey);
  376. }
  377. // 更新翻译状态
  378. $updateTransSql = "UPDATE kln_i18n_keys SET status = $status, trans_value = '$trans_value' ".
  379. " WHERE page_id = " . $pageId .
  380. " AND lang_id = " . $langId .
  381. " AND trans_key = '".$transKey."'";
  382. $db->Execute($updateTransSql);
  383. }
  384. } catch (Exception $e) {
  385. // 捕获异常,标记错误,以便回滚
  386. error_log("Exception in multilingual_save: " . $e->getMessage());
  387. }
  388. // 结束事务
  389. if ($db->CompleteTrans() === FALSE) {
  390. $msg = 'Save Error';
  391. } else {
  392. $msg = 'Save Success';
  393. }
  394. common::echo_json_encode(200, $msg);
  395. exit();
  396. }
  397. /**
  398. * load page info
  399. */
  400. public function _loadPageInfo($langIds){
  401. $pageSql = "SELECT
  402. (select page_key from public.kln_i18n_pages where id = page_id) as page_key,
  403. COUNT(*) AS unverified_count
  404. FROM (
  405. SELECT
  406. page_id,
  407. trans_key,
  408. BOOL_OR(status = 0) AS all_unverified
  409. FROM kln_i18n_keys
  410. WHERE lang_id IN (" . implode(',', $langIds) . ")
  411. GROUP BY page_id, trans_key
  412. ) AS subquery
  413. WHERE all_unverified = TRUE GROUP BY page_id;";
  414. $pageData = common::excuteListSql($pageSql);
  415. $unverified_count = 0;
  416. foreach($pageData as $_pageData){
  417. $unverified_count += $_pageData['unverified_count'];
  418. }
  419. $newItem = [
  420. 'page_key' => 'all',
  421. 'unverified_count' =>$unverified_count
  422. ];
  423. // 将新数组插入到 $pageDate 的开头
  424. array_unshift($pageData, $newItem);
  425. return $pageData;
  426. }
  427. /**
  428. * load lang info
  429. */
  430. public function _loadLangInfo($langIds,$pageIds = array()){
  431. $page_id_sql = "";
  432. if(!empty($pageIds)){
  433. $page_id_sql = "AND k.page_id IN (" . implode(',', $pageIds) . ")";
  434. }
  435. $lang_id_sql = "";
  436. if(!empty($langIds)){
  437. $lang_id_sql = "AND l.id IN (" . implode(',', $langIds) . ")";
  438. }
  439. $langSql = "SELECT
  440. l.lang_key,
  441. COUNT(k.id) AS unverified_count
  442. FROM kln_i18n_languages l
  443. LEFT JOIN kln_i18n_keys k ON l.id = k.lang_id
  444. $page_id_sql
  445. AND k.status = 0
  446. WHERE
  447. l.is_active = TRUE
  448. $lang_id_sql
  449. GROUP BY
  450. l.id, l.lang_key, l.lang_name;";
  451. $langData = common::excuteListSql($langSql);
  452. $unverified_count = 0;
  453. $retLangData = array('all'=>0);
  454. foreach($langData as $_langData){
  455. $unverified_count += $_langData['unverified_count'];
  456. $retLangData[$_langData['lang_key']] = intval($_langData['unverified_count']);
  457. }
  458. $retLangData['all'] =$unverified_count;
  459. return $retLangData;
  460. }
  461. /**
  462. * 按照指定语言查询所有页面的多语言信息,并输出标准 JSON 格式
  463. * 兼容 PHP 7.4
  464. *
  465. * @param string $langKey 语言键,例如 'english', 'simplifiedChinese'
  466. * @return void 输出 JSON 并终止脚本
  467. */
  468. public function _loadAllPagesByLang($langKey = 'english') {
  469. // 1. 参数校验与安全过滤
  470. $langKey = common::check_input($langKey);
  471. if (empty($langKey)) {
  472. $langKey = 'english'; // 默认回退到英语
  473. }
  474. try {
  475. // 2. 查询指定语言的 ID
  476. $langSql = "SELECT id FROM kln_i18n_languages WHERE lang_key = ? AND is_active = TRUE limit 1";
  477. $langObj = common::excuteObjectPrepareSql($langSql,array($langKey));
  478. if (empty($langObj)) {
  479. common::echo_json_encode(500, "Invalid languages");
  480. exit();
  481. }
  482. $langId = $langObj['id'];
  483. // 3. 查询所有激活的页面
  484. $pageSql = "SELECT id, page_key FROM kln_i18n_pages WHERE 1=1";
  485. $pageRows = common::excuteListSql($pageSql);
  486. // 4. 构建页面 ID 列表,用于后续查询
  487. $pageIdMap = array();
  488. foreach ($pageRows as $row) {
  489. $pageIdMap[$row['id']] = $row['page_key'];
  490. }
  491. $pageIds = array_keys($pageIdMap);
  492. // 5. 查询该语言下所有页面的所有翻译词条
  493. $inClause = implode(',', $pageIds);
  494. $transSql = "SELECT page_id, trans_key, trans_value
  495. FROM kln_i18n_keys
  496. WHERE lang_id = $langId
  497. AND page_id IN ($inClause)";
  498. $transRows = common::excuteListSql($transSql);
  499. // 6. 数据组装 (核心逻辑)
  500. $result = array();
  501. // 先初始化所有页面的空数组
  502. foreach ($pageIdMap as $pageKey) {
  503. $result[$pageKey] = array();
  504. }
  505. // 填充翻译数据
  506. foreach ($transRows as $row) {
  507. $pageKey = $pageIdMap[$row['page_id']];
  508. $transKey = $row['trans_key'];
  509. $transValue = $row['trans_value'];
  510. // 直接赋值: $result['login']['username'] = 'User Name'
  511. $result[$pageKey][$transKey] = $transValue;
  512. }
  513. // 7. 输出 JSON
  514. common::echo_json_encode(200, $result);
  515. exit();
  516. } catch (Exception $e) {
  517. // 错误处理
  518. error_log("Error in loadAllPagesByLang: " . $e->getMessage());
  519. common::echo_json_encode(500, "Invalid languages");
  520. exit();
  521. }
  522. }
  523. }
  524. ?>