ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Prisma Datamodel Inflector 模块解析:从 evo-inflector 移植的英文复数化规则引擎

Prisma Datamodel Inflector 模块解析:从 evo-inflector 移植的英文复数化规则引擎 后端数据库GraphQL【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址https://gitcode.com/gh_mirrors/pr/prisma1点击查看免费下载本篇技术指南聚焦 Prisma 官方 monorepo当前镜像仓库prisma1中prisma-datamodel包的inflector模块系统讲解其从 Java 版 evo-inflector 移植而来的英文复数化实现包括English类的完整 API、TwoFormInflector规则引擎的架构设计、Anglicized/Classical 双模式差异以及它在数据模型命名规范化如一对多关系名的复数化中的实际作用。读完本文你将掌握该模块的规则匹配顺序、不可数词与不规则词的处理机制、边界兜底逻辑并能通过仓库内的测试用例验证任意单词的复数化结果。模块定位与来源一次 Apache 2.0 协议的移植inflector模块位于 cli/packages/prisma-datamodel/src/util/inflector其 README.md 明确说明Ported from evo inflector (https://github.com/atteo/evo-inflector). Evo inflector was licensed under the Apache 2.0 License, therefore we have to include the License here and in the tests folder.也就是说该模块并非从零编写而是将 Java 生态中著名的 evo-inflector 库移植为 TypeScript。正因原库采用 Apache 2.0 许可仓库在inflector目录下cli/packages/prisma-datamodel/src/util/inflector/LICENSE以及对应的测试目录cli/packages/prisma-datamodel/__tests__/inflector/LICENSE中都保留了许可证文件。这一点在代码版权头中也有印证——english.ts 和 twoFormInflector.ts 均标注 Copyright 2011 Atteo即 evo-inflector 原作者。整个模块只包含两个源文件职责非常清晰文件职责english.ts英语复数化规则的定义与对外 APIEnglish类twoFormInflector.ts通用双形态单数/复数规则引擎规则接口、正则规则、分类规则、基类对外 APIEnglish类的三个静态方法与一个枚举english.ts 中定义了两种复数化模式的枚举enum Mode { ENGLISH_ANGLICIZED, // 英式“英语化”复数默认 ENGLISH_CLASSICAL, // 古典拉丁/希腊式复数 }English类对外暴露三个静态方法// 返回单词的复数形式 // English.plural(cat) cats public static plural(word: string) // 根据数量返回单数或复数形式 // English.plural(cat, 1) cat; // English.plural(cat, 2) cats; public static pluralByCount(word: string, count: number) // 切换复数模式ANGlicized / CLASSICAL public static setMode(mode: Mode)其中setMode的实现是重新构造一个对应模式的English实例并赋给静态字段inflectorprivate static inflector new English() public static setMode(mode: Mode) { English.inflector new English(mode) }实例方法getPluralByCount的逻辑非常直接count 1返回原词否则调用getPlural。这意味着模块天然支持“列表长度决定名字单复数”这类场景。规则引擎架构TwoFormInflector 与两类规则复数化的核心并不是一堆 if/else而是一条有序规则链。基类 TwoFormInflector 维护一个rules: Rule[]数组规则按注册顺序依次尝试第一个返回非 null 结果的规则生效protected getPlural(word: string) { for (const rule of this.rules) { const result rule.getPlural(word) if (result ! null) { return result } } return null }Rule接口只有getPlural(singular): string | null一个方法返回 null 表示“这条规则不适用于该词”。具体有两类实现1.RegExpRule正则规则——用正则表达式匹配词尾命中则执行替换public getPlural(singular: string): string | null { // Important: Do not use g flag, we dont want to replace globally, only the first one if (this.singular.test(singular)) { return singular.replace(this.singular, this.plural) } else { return null } }源码注释特意强调不使用g全局标志只替换第一个匹配位置避免对单词中部重复替换。2.CategoryRule分类规则——针对一组共享同一变化规律的后缀词表先小写化后匹配词尾再执行后缀替换public getPlural(word: string): string | null { const lowerWord word.toLowerCase() for (const suffix of this.list) { if (lowerWord.endsWith(suffix)) { if (!lowerWord.endsWith(this.singular)) { throw new Error(Internal Error) } return word.substring(0, word.length - this.singular.length) this.plural } } return null }它相当于一张“白名单词表 统一变换规则”只有当单词确实以词表中某个词结尾时才应用比如alumnus → alumni是CATEGORY_US_I表中us → i的变换。注意匹配是小写不敏感的因此Bacterium → Bacteria测试用例中有验证也能正确命中um → a规则。基类还提供了五种注册规则的受保护方法供English构造器调用uncountable(list)不可数词、irregular(singular, plural)不规则词自动生成首字母大写/小写两个变体的正则、rule(singular, plural)忽略大小写的正则规则、ruleFromList(list)、categoryRule(list, singular, plural)。复数规则全解析从不可数词到兜底-sEnglish 的构造函数按注释编号的顺序逐层注册规则层次设计非常讲究1. 不可数词第 2 步fish, sheep, deer, bison, salmon, trout, tuna, elk, series, species, news, homework, scissors, diabetes, measles, mumps, graffiti, rabies等约 60 个词被注册为CategoryRule(list, , )——后缀替换为空即原样返回。2. 不规则复数第 4 步child→children, ephemeris→ephemerides, mongoose→mongooses, mythos→mythoi, soliloquy→soliloquies, trilby→trilbys, genus→genera, quiz→quizzes。其中genus→genera正是数据建模场景的高频词。3. 常见后缀的不规则变化第 5 步[man$, men], // human - humans 由 categoryRule 单独豁免 [([lm])ouse$, $1ice], // mouse - mice [tooth$, teeth], [goose$, geese], [foot$, feet], // foot - feet [zoon$, zoa], // protozoon - protozoa [([csx])is$, $1es], // basis - bases注意这里用ruleFromList注册的是忽略大小写的正则基类rule方法使用new RegExp(singular, i)因此Woman → Women这类首字母大写的词也能正确变化测试用例中有验证。4. 完全同化的古典词形第 6 步通过categoryRule处理codex→codices、radix→radices、bacterium→bacteria、criterion→criteria、alumna→alumnae等。5. 词尾规则([cs]h|[zx])$ → $1eschurch→churches、Box→Boxes-ch/-sh/-ss加eswish→wishes-f/-fe变-vesleaf→leaves规则为([aeo]l)f$→$1ves、([nlw]i)fe$→$1ves等-y规则([aeiou])y$→$1ysferry→ferries由y$→ies处理-o规则元音前加osradio→radios其余加oesecho→echoes另有CATEGORY_O_OS白名单photo, zero, auto, macro, casino, rhino, jumbo等约 30 个词始终加osulum → ulabaculum→bacula测试用例覆盖s$ → sesalias→aliases兜底规则$ → s其余所有词默认加s。关键设计由于规则按注册顺序依次尝试白名单类规则如human→humans使用CATEGORY_MAN_MANS在man$→men之前注册能优先拦截避免human被误转为humen。从源码结构看这种“先特例、后通则、最后兜底”的排序是整个引擎正确性的基石。双模式差异Anglicized 与 Classicalenglish.ts 第 319-341 行展示了两种模式的核心差异——同一批不规则词在两种模式下的复数形式截然不同单词Anglicized默认Classicalbeefbeefsbeevesbrotherbrothersbrethrencowcowskinegeniegeniesgeniimoneymoneysmoniesoctopusoctopusesoctopodesopusopusesoperamongoosemongoosesmongooses共用此外Classical 模式还会额外启用一组拉丁/希腊式词尾规则第 364-380 行trix→trices、eau→eaux、ieu→ieux、(..[iay])nx→$1nges、stamen→staminaen→ina、anathema→anathemataa→ata、iris→iridesis→ides、apparatus→apparatusus→us、tempo→tempio→i、cherub→cherubim→im、apex→apicesex→ices等。而alumnus→alumnius→i在两种模式下都生效。注意测试用例 inflectorTest.ts 中const inflector new English()未传参即默认使用Anglicized模式因此opus→opuses、codex→codices等断言均以英语化结果为准。边界兜底不可数词为何也会被“强行复数化”English.getPlural在 第 429-440 行对规则链结果做了二次兜底public getPlural(word: string) { const plural super.getPlural(word) if (plural word) { if (plural.endsWith(s)) { return plural es // news - newses } else { return plural s // sugar - sugars } } return plural }也就是说当某个不可数词如news、series、scissors经规则链返回原词时并不会原样返回而是按“以 s 结尾加 es、否则加 s”的规则强制生成newses、serieses、scissorses。这一点在专门的测试 noPluralization.ts 中被明确验证——该测试注释为 Must work correctly with types that can not be pluralized必须正确处理无法复数化的类型断言News→Newses、Homework→Homeworks、Scissors→Scissorses。在 prisma-datamodel 中的集成util.plural与公共导出inflector并不是孤立工具它在 src/util/util.ts 中被包装为供数据模型命名使用的plural函数/** * Pluralizes a word like the prisma server would do. * param name The word to pluralize. */ export function plural(name: string): string { const pluralWord English.plural(name) if (pluralWord null || pluralWord name) { if (name.endsWith(s)) { return name es } else { return name s } } else { return pluralWord } }注释 Pluralizes a word like the prisma server would do 表明该函数的输出需要与 Prisma 服务端Scala 侧的复数化行为保持一致是客户端数据模型与服务器行为对齐的关键一环。util.ts中同时还提供了配套的命名工具capitalize首字母大写、lowerCase首字母小写、camelCase按空格/-/_切分后转驼峰且刻意保留后半部分原有大小写。最终这些工具通过 src/index.ts 统一导出export { capitalize, lowerCase, camelCase, plural, dedent } from ./util/util即任何依赖prisma-datamodel的包如prisma-generate-schema、prisma-db-introspection、CLI 工具链都可以通过import { plural } from prisma-datamodel直接使用这套与 Prisma 服务器一致的复数化逻辑用于将单数模型名规范化为复数集合名或一对多关系名。测试验证36 组单词与三种断言场景模块的正确性由两组测试保障均位于 cli/packages/prisma-datamodel/tests/inflector1. inflectorTest.ts——注释标明 Unit tests ported from evo-inflector包含三个测试36 组单词的复数断言覆盖了前述所有规则类型分类规则alga→algae、Bacterium→Bacteria、stimulus→stimuli、codex→codices正则规则church→churches、Box→Boxes、ferry→ferries、wish→wishes大小写保持Woman→Women、NightWolf→NightWolves、WorldAtlas→WorldAtlases兜底逻辑series→serieses、news→newses、scissors→scissorses双模式默认值opus→opuses、index→indexes、tempo→tempos、cherub→cherubs、human→humans。按数量复数化getPluralByCount(cat, 1) cat、getPluralByCount(cat, 2) cats以及demoness→demonesses静态方法English.plural(sulfimide) sulfimides、English.pluralByCount(semifluid, 2) semifluids。2. noPluralization.ts——专测不可复数化类型的强制复数化行为News→Newses、Homework→Homeworks、Scissors→Scissorses。适用前提与使用建议版本与定位本模块属于已废弃的 Prisma 1.x 工具链prisma-datamodel包内部实现适用于需要解析/生成 Prisma 1 数据模型.prisma文件或对齐服务端命名行为的场景Prisma 2 及以后版本已不再使用这套工具链。语言边界规则引擎只覆盖英语含拉丁、希腊词源的英语化形式对中文、日语等多字节语言命名不产生复数化作用。模式选择默认ENGLISH_ANGLICIZED符合多数现代英语用法若需要严格的古典学究式复数如octopus→octopodes、cherub→cherubim可调用English.setMode(Mode.ENGLISH_CLASSICAL)。扩展方式若需新增自定义词可仿照English构造函数通过基类的uncountable、irregular、rule、categoryRule方法在构造器中按优先级注册注意保持“特例在前、兜底在后”的注册顺序。赞分享后端数据库GraphQL【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址https://gitcode.com/gh_mirrors/pr/prisma1点击查看免费下载相关推荐CodeLlama-7b-hf在openMind框架下的完整部署教程快速搭建AI代码助手CodeLlama 7b hf在openMind框架下的完整部署教程快速搭建AI代码助手 想要在openMind框架上快速部署强大的CodeLlama 7b开发工具代码质量Symfony Inflector 项目教程Symfony Inflector 项目教程 1. 项目的目录结构及介绍 Symfony Inflector 项目的目录结构相对简单主要包含以下几个部分 iQwen3.5-9B-Claude-4.6-Opus-Reasoning-Distilled vs 其他推理模型优势与独特之处Qwen3.5 9B Claude 4.6 Opus Reasoning Distilled vs 其他推理模型优势与独特之处 Qwen3.5 9B Clau上一篇Volatility3 Linux内存取证入门教程下一篇Pydantic/Logfire分布式追踪技术指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表