chore: 规范标点
This commit is contained in:
1 parent
e54390a9f8
commit
15e79887fa
84 files changed
+5439
-5398
No files matched your search
+26
-26
@@ -1,10 +1,10 @@
|
||||
/* test_i18n.c - 界面文案表
|
||||
*
|
||||
* 这张表是"每种语言一条"。它最容易出的错不是逻辑,而是漏:加了键忘了翻,
|
||||
* 或者译文里少了个占位符({path} 写成 {paths})—— 用户看到的就是一句缺字的话。
|
||||
* 所以这里的检查全部是机械的:遍历表,逐条比对。
|
||||
* 这张表是"每种语言一条". 它最容易出的错不是逻辑, 而是漏:加了键忘了翻,
|
||||
* 或者译文里少了个占位符 ({path} 写成 {paths})—— 用户看到的就是一句缺字的话.
|
||||
* 所以这里的检查全部是机械的:遍历表, 逐条比对.
|
||||
*
|
||||
* 文案本身好不好不在这里管;"英文界面是不是每句都有着落"才是。
|
||||
* 文案本身好不好不在这里管; "英文界面是不是每句都有着落"才是.
|
||||
*/
|
||||
#include "i18n.h"
|
||||
|
||||
@@ -26,7 +26,7 @@ static int checks = 0;
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* 收一份占位符名单({name} 里的 name),按出现顺序放进 out */
|
||||
/* 收一份占位符名单 ({name} 里的 name), 按出现顺序放进 out */
|
||||
static int placeholders(const char *s, char (*out)[32], int max)
|
||||
{
|
||||
int n = 0;
|
||||
@@ -44,9 +44,9 @@ static int placeholders(const char *s, char (*out)[32], int max)
|
||||
return n;
|
||||
}
|
||||
|
||||
/* 收一份 printf 转换符名单(%zu、%c、%.20s …),原样带走标志/宽度/长度。
|
||||
* json.* 那几条是 printf 模板而不是 {name},两种语言只要转换符顺序或类型
|
||||
* 对不上,snprintf 就会读错参数 —— 比少字更糟,得由机器盯住。 */
|
||||
/* 收一份 printf 转换符名单 (%zu、%c、%.20s …), 原样带走标志/宽度/长度.
|
||||
* json.* 那几条是 printf 模板而不是 {name}, 两种语言只要转换符顺序或类型
|
||||
* 对不上, snprintf 就会读错参数 —— 比少字更糟, 得由机器盯住. */
|
||||
static int printf_specs(const char *s, char (*out)[16], int max)
|
||||
{
|
||||
int n = 0;
|
||||
@@ -71,9 +71,9 @@ static int printf_specs(const char *s, char (*out)[16], int max)
|
||||
return n;
|
||||
}
|
||||
|
||||
/* 有没有中日韩字符(含全角标点:〔〕())。英文那一列里出现它,基本就是
|
||||
/* 有没有中日韩字符 (含全角标点:〔〕 ()). 英文那一列里出现它, 基本就是
|
||||
* "照抄了中文"或者"美化用的框线忘了换" —— 用户看到的是英文句子中间卡着一对
|
||||
* 中文括号。顺带把"英文栏里混进日文假名"这种复制粘贴也一并挡住。 */
|
||||
* 中文括号. 顺带把"英文栏里混进日文假名"这种复制粘贴也一并挡住. */
|
||||
static int has_cjk(const char *s)
|
||||
{
|
||||
for (const unsigned char *p = (const unsigned char *)s; p && *p; p++) {
|
||||
@@ -106,8 +106,8 @@ int main(void)
|
||||
CHECK(!has_cjk(m->en ? m->en : ""), "%s 的英文里混进了中日韩字符",
|
||||
m->key);
|
||||
|
||||
/* key 唯一性:比较是 O(n²),但每个 key 只记一条检查 —— 写成循环里
|
||||
* CHECK 的话,check-docs 数出来的"单元项数"就没意义了。 */
|
||||
/* key 唯一性:比较是 O(n²), 但每个 key 只记一条检查 —— 写成循环里
|
||||
* CHECK 的话, check-docs 数出来的"单元项数"就没意义了. */
|
||||
int dup = 0;
|
||||
for (size_t j = i + 1; j < n; j++)
|
||||
if (strcmp(tab[j].key, m->key) == 0) dup = 1;
|
||||
@@ -116,7 +116,7 @@ int main(void)
|
||||
char pe[16][32], pz[16][32];
|
||||
int ne = placeholders(m->en ? m->en : "", pe, 16);
|
||||
int nz = placeholders(m->zh ? m->zh : "", pz, 16);
|
||||
CHECK(ne == nz, "%s 两种语言的占位符数量不同(en %d / zh %d)",
|
||||
CHECK(ne == nz, "%s 两种语言的占位符数量不同 (en %d / zh %d)",
|
||||
m->key, ne, nz);
|
||||
for (int a = 0; a < ne && a < nz; a++) {
|
||||
int found = 0;
|
||||
@@ -124,7 +124,7 @@ int main(void)
|
||||
if (strcmp(pe[a], pz[b]) == 0) found = 1;
|
||||
CHECK(found, "%s:英文的 {%s} 在中文里没有对应", m->key, pe[a]);
|
||||
}
|
||||
/* 译文里多出一个原文没有的占位符,同样会在运行时漏字 */
|
||||
/* 译文里多出一个原文没有的占位符, 同样会在运行时漏字 */
|
||||
for (int a = 0; a < nz && a < ne; a++) {
|
||||
int found = 0;
|
||||
for (int b = 0; b < ne; b++)
|
||||
@@ -133,21 +133,21 @@ int main(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* 表里有一部分键是**当 printf 模板用的**(repl.usage.*、repl.model.row、
|
||||
* json.* …):调用方直接把 t(key) 交给 printf/snprintf。这些条目的
|
||||
* {name} 检查管不到,得单独比转换符 —— 少一个 %s 会读到别的参数,
|
||||
* 类型写错(%d 对 %zu)更是直接踩内存。 */
|
||||
/* 表里有一部分键是**当 printf 模板用的** (repl.usage.*、repl.model.row、
|
||||
* json.* …):调用方直接把 t(key) 交给 printf/snprintf. 这些条目的
|
||||
* {name} 检查管不到, 得单独比转换符 —— 少一个 %s 会读到别的参数,
|
||||
* 类型写错 (%d 对 %zu)更是直接踩内存. */
|
||||
puts("printf 模板:两种语言的转换符必须一模一样");
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
const LigentMsg *m = &tab[i];
|
||||
char se[16][16], sz[16][16];
|
||||
int ce = printf_specs(m->en ? m->en : "", se, 16);
|
||||
int cz = printf_specs(m->zh ? m->zh : "", sz, 16);
|
||||
if (ce == 0 && cz == 0) continue; /* 不是模板,跳过 */
|
||||
CHECK(ce == cz, "%s:转换符个数不同(en %d / zh %d)", m->key, ce, cz);
|
||||
if (ce == 0 && cz == 0) continue; /* 不是模板, 跳过 */
|
||||
CHECK(ce == cz, "%s:转换符个数不同 (en %d / zh %d)", m->key, ce, cz);
|
||||
for (int a = 0; a < ce && a < cz; a++)
|
||||
CHECK(strcmp(se[a], sz[a]) == 0,
|
||||
"%s:第 %d 个转换符不同(en %s / zh %s)",
|
||||
"%s:第 %d 个转换符不同 (en %s / zh %s)",
|
||||
m->key, a + 1, se[a], sz[a]);
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ int main(void)
|
||||
CHECK(i18n_lang_name()[0] == 'e', "i18n_lang_name");
|
||||
CHECK(strstr(t("cli.err.unknown_option"), "unknown") != NULL, "英文那条");
|
||||
CHECK(strncmp(t("no.such.key"), "[?", 2) == 0,
|
||||
"漏掉的键要显眼地露出来(实际 %s),不能变成空白", t("no.such.key"));
|
||||
"漏掉的键要显眼地露出来 (实际 %s), 不能变成空白", t("no.such.key"));
|
||||
|
||||
puts("占位符替换按名字走");
|
||||
i18n_set_lang(LIGENT_LANG_EN);
|
||||
@@ -170,11 +170,11 @@ int main(void)
|
||||
CHECK(strstr(r, "--nope") != NULL, "值要填进去");
|
||||
CHECK(strstr(r, "{option}") == NULL, "填过的占位符不该留下");
|
||||
CHECK(strstr(tf("cli.err.unknown_option", "wrong", "x", NULL), "{option}") != NULL,
|
||||
"名字对不上时原样保留,别静默吞掉");
|
||||
"名字对不上时原样保留, 别静默吞掉");
|
||||
i18n_set_lang(LIGENT_LANG_ZH);
|
||||
CHECK(strstr(tf("cli.err.unknown_option", "option", "选项X", NULL), "选项X") != NULL,
|
||||
"中文模板同样能填");
|
||||
/* 同一句里多个占位符,且顺序与调用顺序相反 */
|
||||
/* 同一句里多个占位符, 且顺序与调用顺序相反 */
|
||||
i18n_set_lang(LIGENT_LANG_EN);
|
||||
const char *two = tf("doctor.val.match_bad", "guess", "OpenAI",
|
||||
"owner", "DeepSeek", NULL);
|
||||
@@ -192,7 +192,7 @@ int main(void)
|
||||
CHECK(i18n_parse_lang("") < 0, "空串返回 -1");
|
||||
CHECK(i18n_parse_lang(NULL) < 0, "NULL 返回 -1");
|
||||
|
||||
puts("环境探测:LIGENT_LANG > LC_ALL > LC_MESSAGES > LANG,认不出/没设 -> 英文");
|
||||
puts("环境探测:LIGENT_LANG > LC_ALL > LC_MESSAGES > LANG, 认不出/没设 -> 英文");
|
||||
unsetenv("LIGENT_LANG");
|
||||
unsetenv("LC_ALL");
|
||||
unsetenv("LC_MESSAGES");
|
||||
@@ -214,6 +214,6 @@ int main(void)
|
||||
unsetenv("LANG");
|
||||
CHECK(i18n_lang_from_env() == LIGENT_LANG_EN, "清干净之后仍是英文");
|
||||
|
||||
printf("\n%d 项检查,%d 项失败\n", checks, failures);
|
||||
printf("\n%d 项检查, %d 项失败\n", checks, failures);
|
||||
return failures ? 1 : 0;
|
||||
}
|
||||
Reference in new issue
Block a user