This commit is contained in:
2026-03-03 23:36:23 +08:00
parent 361ccc12d6
commit 6786a76f41
3 changed files with 277 additions and 2 deletions

View File

@@ -114,6 +114,38 @@ static NSString * const kKBKeyboardLayoutI18nFileName = @"kb_keyboard_layouts_i1
}
}
- (NSArray<KBKeyboardRowConfig *> *)kb_mergeRowsFromBase:(NSArray<KBKeyboardRowConfig *> *)baseRows
override:(NSArray<KBKeyboardRowConfig *> *)overrideRows {
if (baseRows.count == 0) { return overrideRows ?: @[]; }
if (overrideRows.count == 0) { return baseRows; }
NSUInteger maxCount = MAX(baseRows.count, overrideRows.count);
NSMutableArray<KBKeyboardRowConfig *> *merged = [NSMutableArray arrayWithCapacity:maxCount];
for (NSUInteger i = 0; i < maxCount; i++) {
KBKeyboardRowConfig *baseRow = (i < baseRows.count) ? baseRows[i] : nil;
KBKeyboardRowConfig *overrideRow = (i < overrideRows.count) ? overrideRows[i] : nil;
if (!baseRow) {
if (overrideRow) { [merged addObject:overrideRow]; }
continue;
}
if (!overrideRow) {
[merged addObject:baseRow];
continue;
}
KBKeyboardRowConfig *row = [KBKeyboardRowConfig new];
row.height = baseRow.height ?: overrideRow.height;
row.insetLeft = baseRow.insetLeft ?: overrideRow.insetLeft;
row.insetRight = baseRow.insetRight ?: overrideRow.insetRight;
row.gap = baseRow.gap ?: overrideRow.gap;
row.align = baseRow.align.length > 0 ? baseRow.align : overrideRow.align;
BOOL hasOverrideItems = [overrideRow.items isKindOfClass:[NSArray class]] && ((NSArray *)overrideRow.items).count > 0;
row.items = hasOverrideItems ? overrideRow.items : baseRow.items;
row.segments = overrideRow.segments ?: baseRow.segments;
[merged addObject:row];
}
return merged.copy;
}
- (void)kb_loadI18nConfig {
NSString *path = [[NSBundle mainBundle] pathForResource:kKBKeyboardLayoutI18nFileName ofType:@"json"];
NSData *data = path.length ? [NSData dataWithContentsOfFile:path] : nil;
@@ -143,9 +175,18 @@ static NSString * const kKBKeyboardLayoutI18nFileName = @"kb_keyboard_layouts_i1
return;
}
KBKeyboardLayout *layout = [KBKeyboardLayout mj_objectWithKeyValues:obj];
if (layout) {
if (!layout) { return; }
KBKeyboardLayout *baseLayout = mergedLayouts[key];
if (!baseLayout) {
mergedLayouts[key] = layout;
return;
}
KBKeyboardLayout *mergedLayout = [KBKeyboardLayout new];
mergedLayout.rows = [self kb_mergeRowsFromBase:baseLayout.rows override:layout.rows];
mergedLayout.shiftRows = [self kb_mergeRowsFromBase:baseLayout.shiftRows override:layout.shiftRows];
mergedLayouts[key] = mergedLayout;
}];
self.layouts = mergedLayouts.copy;

View File

@@ -246,6 +246,240 @@
}
]
},
"letters_es": {
"__comment": "西班牙语布局QWERTY",
"rows": [
{
"__comment": "字母第一行 qwertyuiop",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 4,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 4,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"items": [
"letter:q", "letter:w", "letter:e", "letter:r", "letter:t",
"letter:y", "letter:u", "letter:i", "letter:o", "letter:p"
],
"__comment_items": "本行按键列表letter:x/digit:x/sym:x 或 keyDefs 中的 id"
},
{
"__comment": "字母第二行 asdfghjkl",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 4,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 4,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"items": [
"letter:a", "letter:s", "letter:d", "letter:f", "letter:g",
"letter:h", "letter:j", "letter:k", "letter:l"
],
"__comment_items": "本行按键列表letter:x/digit:x/sym:x 或 keyDefs 中的 id"
},
{
"__comment": "字母第三行:左 shift中间字母右 backspace",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 4,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 4,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"segments": {
"__comment": "分段布局left/center/right",
"left": [
{ "id": "shift", "width": "controlWidth", "__comment_id": "引用 keyDefs 的 id", "__comment_width": "宽度引用 metrics.controlWidth" }
],
"__comment_left": "左侧固定按钮",
"center": [
"letter:z", "letter:x", "letter:c", "letter:v", "letter:b", "letter:n", "letter:m"
],
"__comment_center": "中间字母键集合,整体居中",
"right": [
{ "id": "backspace", "width": "controlWidth", "__comment_id": "引用 keyDefs 的 id", "__comment_width": "宽度引用 metrics.controlWidth" }
],
"__comment_right": "右侧固定按钮"
}
},
{
"__comment": "字母第四行123/emoji/space/send",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 4,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 4,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"items": [
"mode_123", "emoji", "space", "send"
],
"__comment_items": "本行按键列表letter:x/digit:x/sym:x 或 keyDefs 中的 id"
}
]
},
"letters_id": {
"__comment": "印度尼西亚语布局QWERTY",
"rows": [
{
"__comment": "字母第一行 qwertyuiop",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 4,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 4,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"items": [
"letter:q", "letter:w", "letter:e", "letter:r", "letter:t",
"letter:y", "letter:u", "letter:i", "letter:o", "letter:p"
],
"__comment_items": "本行按键列表letter:x/digit:x/sym:x 或 keyDefs 中的 id"
},
{
"__comment": "字母第二行 asdfghjkl",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 23,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 0,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"items": [
"letter:a", "letter:s", "letter:d", "letter:f", "letter:g",
"letter:h", "letter:j", "letter:k", "letter:l"
],
"__comment_items": "本行按键列表letter:x/digit:x/sym:x 或 keyDefs 中的 id"
},
{
"__comment": "字母第三行:左 shift中间字母右 backspace",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 4,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 4,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"segments": {
"__comment": "分段布局left/center/right",
"left": [
{ "id": "shift", "width": "controlWidth", "__comment_id": "引用 keyDefs 的 id", "__comment_width": "宽度引用 metrics.controlWidth" }
],
"__comment_left": "左侧固定按钮",
"center": [
"letter:z", "letter:x", "letter:c", "letter:v", "letter:b", "letter:n", "letter:m"
],
"__comment_center": "中间字母键集合,整体居中",
"right": [
{ "id": "backspace", "width": "controlWidth", "__comment_id": "引用 keyDefs 的 id", "__comment_width": "宽度引用 metrics.controlWidth" }
],
"__comment_right": "右侧固定按钮"
}
},
{
"__comment": "字母第四行123/emoji/space/send",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 4,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 4,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"items": [
"mode_123", "emoji", "space", "send"
],
"__comment_items": "本行按键列表letter:x/digit:x/sym:x 或 keyDefs 中的 id"
}
]
},
"letters_pt": {
"__comment": "葡萄牙语布局QWERTY",
"rows": [
{
"__comment": "字母第一行 qwertyuiop",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 4,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 4,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"items": [
"letter:q", "letter:w", "letter:e", "letter:r", "letter:t",
"letter:y", "letter:u", "letter:i", "letter:o", "letter:p"
],
"__comment_items": "本行按键列表letter:x/digit:x/sym:x 或 keyDefs 中的 id"
},
{
"__comment": "字母第二行 asdfghjkl",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 23,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 0,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"items": [
"letter:a", "letter:s", "letter:d", "letter:f", "letter:g",
"letter:h", "letter:j", "letter:k", "letter:l"
],
"__comment_items": "本行按键列表letter:x/digit:x/sym:x 或 keyDefs 中的 id"
},
{
"__comment": "字母第三行:左 shift中间字母右 backspace",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 4,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 4,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"segments": {
"__comment": "分段布局left/center/right",
"left": [
{ "id": "shift", "width": "controlWidth", "__comment_id": "引用 keyDefs 的 id", "__comment_width": "宽度引用 metrics.controlWidth" }
],
"__comment_left": "左侧固定按钮",
"center": [
"letter:z", "letter:x", "letter:c", "letter:v", "letter:b", "letter:n", "letter:m"
],
"__comment_center": "中间字母键集合,整体居中",
"right": [
{ "id": "backspace", "width": "controlWidth", "__comment_id": "引用 keyDefs 的 id", "__comment_width": "宽度引用 metrics.controlWidth" }
],
"__comment_right": "右侧固定按钮"
}
},
{
"__comment": "字母第四行123/emoji/space/send",
"align": "left",
"__comment_align": "对齐方式left/center",
"insetLeft": 4,
"__comment_insetLeft": "本行左边距(覆盖 metrics.edgeInset",
"insetRight": 4,
"__comment_insetRight": "本行右边距(覆盖 metrics.edgeInset",
"gap": 5,
"__comment_gap": "本行按键间距(覆盖 metrics.gap",
"items": [
"mode_123", "emoji", "space", "send"
],
"__comment_items": "本行按键列表letter:x/digit:x/sym:x 或 keyDefs 中的 id"
}
]
},
"numbers": {
"__comment": "数字面板布局123 页)",
"rows": [

View File

@@ -1651,4 +1651,4 @@
]
}
}
}
}