refactor(lang): 优化远程页面树的命名匹配逻辑

修复多语言路径同时支持camelCase和snake_case的匹配问题,为每个层级同时维护两种命名格式的镜像键,增强路径兼容性
This commit is contained in:
2026-07-04 09:32:56 +08:00
parent eb46748ae0
commit ea504d8434

View File

@@ -856,33 +856,66 @@ function normalizeRemoteTreeForPage(tree, langPath) {
const segments = String(langPath).split('/').filter(Boolean);
if (!segments.length) return tree;
// 沿 langPath 段向下找页面 leaf:同一段同时尝试 camelCase 与 snake_case(bundle 服务器侧
// 对同一段实际可能用任一种命名,例如 point/order_list 在 bundle 里是 `tree.point.order_list.X`,
// 而 login/login 这种 camel 路径又是 `tree.login.login.X`)。
let leaf = tree;
let hasLeaf = true;
for (const segment of segments) {
const key = toCamelCaseName(segment);
if (leaf && typeof leaf === 'object' && !Array.isArray(leaf) && leaf[key] !== undefined) {
leaf = leaf[key];
} else {
hasLeaf = false;
break;
}
const camel = toCamelCaseName(segment);
const snake = toSnakeCaseName(segment);
// 优先 camelCase;没有就回退 snake_case;都没有就放弃
const key = (leaf && typeof leaf === 'object' && !Array.isArray(leaf) && leaf[camel] !== undefined)
? camel
: (leaf && typeof leaf === 'object' && !Array.isArray(leaf) && leaf[snake] !== undefined
? snake
: null);
if (key === null) { hasLeaf = false; break; }
leaf = leaf[key];
}
const lastSegment = toCamelCaseName(segments[segments.length - 1]);
const lastSegmentSnake = toSnakeCaseName(segments[segments.length - 1]);
const currentPageLeaf =
hasLeaf && leaf && typeof leaf === 'object' && !Array.isArray(leaf)
? leaf
: (tree[lastSegment] && typeof tree[lastSegment] === 'object' && !Array.isArray(tree[lastSegment]) ? tree[lastSegment] : null);
: (tree[lastSegment] && typeof tree[lastSegment] === 'object' && !Array.isArray(tree[lastSegment])
? tree[lastSegment]
: (tree[lastSegmentSnake] && typeof tree[lastSegmentSnake] === 'object' && !Array.isArray(tree[lastSegmentSnake])
? tree[lastSegmentSnake]
: null));
if (!currentPageLeaf) return tree;
// (1) namespaced merge
// (1) namespaced merge —— 同时建 camelCase 与 snake_case 镜像键,
// 让两种调用形式都能落到同一份 leaf
const namespaced = {};
let cursor = namespaced;
{
let cursor = namespaced;
for (let i = 0; i < segments.length; i++) {
const camel = toCamelCaseName(segments[i]);
cursor[camel] = i === segments.length - 1 ? deepCloneLang(currentPageLeaf) : {};
cursor = cursor[camel];
}
}
// 在 namespaced 的每个层级再挂一份 snake_case 镜像
const nested = [];
{
let cursor = namespaced;
nested.push(cursor);
for (let i = 0; i < segments.length - 1; i++) {
cursor = cursor[toCamelCaseName(segments[i])];
nested.push(cursor);
}
}
for (let i = 0; i < segments.length; i++) {
const segment = toCamelCaseName(segments[i]);
cursor[segment] = i === segments.length - 1 ? deepCloneLang(currentPageLeaf) : {};
cursor = cursor[segment];
const raw = segments[i];
const camel = toCamelCaseName(raw);
const snake = toSnakeCaseName(raw);
if (snake !== camel) {
const isLeaf = i === segments.length - 1;
nested[i][snake] = isLeaf ? deepCloneLang(currentPageLeaf) : {};
}
}
const merged = deepMergeLang(deepCloneLang(tree), namespaced);