{"_id":"@edwinho/kotoba-core","_rev":"7-a87baefdc279b6077b1d78298dffd4c4","name":"@edwinho/kotoba-core","dist-tags":{"latest":"0.2.5"},"versions":{"0.1.0":{"name":"@edwinho/kotoba-core","version":"0.1.0","keywords":["language-learning","translation","japanese","chinese","korean"],"author":{"name":"eho"},"license":"MIT","_id":"@edwinho/kotoba-core@0.1.0","maintainers":[{"name":"edwinho","email":"edwin_ho@me.com"}],"homepage":"https://github.com/eho/kotoba","bugs":{"url":"https://github.com/eho/kotoba/issues"},"dist":{"shasum":"79c9f07b366dee7bfee3addf00126cdceb9076a1","tarball":"https://registry.npmjs.org/@edwinho/kotoba-core/-/kotoba-core-0.1.0.tgz","fileCount":23,"integrity":"sha512-q0RI36+d7kiGGq1B+XJh3tJaFETMZI25wVd5VM8UXqTvWQ7/vPqJjuVMpAy+KgLUmoWrs7DVUtPeWc8SMJWDsg==","signatures":[{"sig":"MEUCIBchUwMk0VofYwOfSbbDt1ujAjdT3LZOMfd4FxTQdZvpAiEAjdAUaSbn7rAU1ZEDf/VPWDkUORWf3kN3ayB1irvlonc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":116055},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"86b781d98fd392d237fb7c2eb4d0cb8203950d94","scripts":{"test":"bun test","build":"bun ../../scripts/clean-package-dist.ts . && bun build src/index.ts --outdir dist --target node --format esm && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit"},"_npmUser":{"name":"edwinho","email":"edwin_ho@me.com"},"repository":{"url":"git+https://github.com/eho/kotoba.git","type":"git","directory":"packages/core"},"_npmVersion":"11.9.0","description":"Framework-neutral language-learning data models, language profiles, and translation draft utilities.","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"~6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/kotoba-core_0.1.0_1780450393227_0.7481533670354845","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@edwinho/kotoba-core","version":"0.2.0","keywords":["language-learning","translation","japanese","chinese","korean"],"author":{"name":"eho"},"license":"MIT","_id":"@edwinho/kotoba-core@0.2.0","maintainers":[{"name":"edwinho","email":"edwin_ho@me.com"}],"homepage":"https://github.com/eho/kotoba","bugs":{"url":"https://github.com/eho/kotoba/issues"},"dist":{"shasum":"21c79826d8daea43804c697561f09b7013c35216","tarball":"https://registry.npmjs.org/@edwinho/kotoba-core/-/kotoba-core-0.2.0.tgz","fileCount":25,"integrity":"sha512-jRxq8s2Hj55taUKFyn6ptYULqt83Mn00c6/nCncWE6p8fvmbrFbaIblx8Dq0gbfKR504dKjLqYhWZ/n2P3oihw==","signatures":[{"sig":"MEUCIQD05ygfIFdqkHN3G6BWpgcE1vvmDt9VoZsYGnEtxXevLAIgfpJJq7dHvZ9XwTF3gF+VlQAv2HiR9p/2lawkOhLaH10=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":133645},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"e8e47f69b0c82c3f75802bc0ecfc7b815070286c","scripts":{"test":"bun test","build":"bun ../../scripts/clean-package-dist.ts . && bun build src/index.ts --outdir dist --target node --format esm && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit"},"_npmUser":{"name":"edwinho","email":"edwin_ho@me.com"},"repository":{"url":"git+https://github.com/eho/kotoba.git","type":"git","directory":"packages/core"},"_npmVersion":"11.9.0","description":"Framework-neutral language-learning data models, language profiles, and translation draft utilities.","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"~6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/kotoba-core_0.2.0_1780621504555_0.8720840014627529","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@edwinho/kotoba-core","version":"0.2.1","keywords":["language-learning","translation","japanese","chinese","korean"],"author":"eho","license":"MIT","_id":"@edwinho/kotoba-core@0.2.1","maintainers":[{"name":"edwinho","email":"edwin_ho@me.com"}],"homepage":"https://github.com/eho/kotoba","bugs":{"url":"https://github.com/eho/kotoba/issues"},"dist":{"shasum":"6fe276fbe41c38781f60473451737ab3d2c8f8ce","tarball":"https://registry.npmjs.org/@edwinho/kotoba-core/-/kotoba-core-0.2.1.tgz","fileCount":25,"integrity":"sha512-V7vD0LW83hz7FKv5JlgyCei7nHMHtG2sAGaaiwAK+HEamWDPpaVOFcWzp03UweC7V43qu6qSbfrFYSyZCUvGIQ==","signatures":[{"sig":"MEYCIQDXyfr9dQxVqOU/vnb1QNPIhrH8LFEkbcBtbQkMuaQjeAIhAJgC2RQms93cPlcZu/XZyPzXSN5fXcISOt/EDEh7kRqG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":133645},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"6fe276fbe41c38781f60473451737ab3d2c8f8ce","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"bun test","build":"bun ../../scripts/clean-package-dist.ts . && bun build src/index.ts --outdir dist --target node --format esm && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit"},"_npmUser":{"name":"edwinho","email":"edwin_ho@me.com"},"_integrity":"sha512-V7vD0LW83hz7FKv5JlgyCei7nHMHtG2sAGaaiwAK+HEamWDPpaVOFcWzp03UweC7V43qu6qSbfrFYSyZCUvGIQ==","repository":{"url":"https://github.com/eho/kotoba.git","type":"git","directory":"packages/core"},"_npmVersion":"10.8.3","description":"Framework-neutral language-learning data models, language profiles, and translation draft utilities.","directories":{},"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"~6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/kotoba-core_0.2.1_1781132237208_0.4169969463482506","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@edwinho/kotoba-core","version":"0.2.2","keywords":["language-learning","translation","japanese","chinese","korean"],"author":{"name":"eho"},"license":"MIT","_id":"@edwinho/kotoba-core@0.2.2","maintainers":[{"name":"edwinho","email":"edwin_ho@me.com"}],"homepage":"https://github.com/eho/kotoba","bugs":{"url":"https://github.com/eho/kotoba/issues"},"dist":{"shasum":"fe6f952767403d5e7c8024ad9f5d5cc7f5088385","tarball":"https://registry.npmjs.org/@edwinho/kotoba-core/-/kotoba-core-0.2.2.tgz","fileCount":25,"integrity":"sha512-pf9mMSdthzVXvSYCHhYCndUkg/ocr7J2C3VudM3zB7Hu6KRJAS88gqrVDGuC3sMrxuBZ/XEV8NWXllHJXBaIeQ==","signatures":[{"sig":"MEQCIHYVuXupG25TQU/d/Gretxw/rkHwLzZkZqFWER0RRycCAiAUCjRaO2BVFr/Aa7I+UmgZvvgkc0WvbK3Z2A1o8TDO0w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":133645},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"60813bbef8c700eb7a9f4cdb48c88cd6c5514bde","scripts":{"test":"bun test","build":"bun ../../scripts/clean-package-dist.ts . && bun build src/index.ts --outdir dist --target node --format esm && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit"},"_npmUser":{"name":"edwinho","email":"edwin_ho@me.com"},"repository":{"url":"git+https://github.com/eho/kotoba.git","type":"git","directory":"packages/core"},"_npmVersion":"11.9.0","description":"Framework-neutral language-learning data models, language profiles, and translation draft utilities.","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"~6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/kotoba-core_0.2.2_1781311907349_0.4086050685941012","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@edwinho/kotoba-core","version":"0.2.3","keywords":["language-learning","translation","japanese","chinese","korean"],"author":{"name":"eho"},"license":"MIT","_id":"@edwinho/kotoba-core@0.2.3","maintainers":[{"name":"edwinho","email":"edwin_ho@me.com"}],"homepage":"https://github.com/eho/kotoba","bugs":{"url":"https://github.com/eho/kotoba/issues"},"dist":{"shasum":"51e03a3fc35658bb5bc2348a7ce431f329758652","tarball":"https://registry.npmjs.org/@edwinho/kotoba-core/-/kotoba-core-0.2.3.tgz","fileCount":25,"integrity":"sha512-YhDD/EGlVJ9K9O1mB8xjDrLnTulvZpcWmWZ9JiIKtnG6H/vV+cHsbfkTkvIBrTD2xUhskCVRGUDy+LwBeW+BGQ==","signatures":[{"sig":"MEUCIBymdLnBGhmWrjSiyadumadYqD4EDPzb4YFL42GbvAHPAiEA0QhKBread/sf1DKfcBxQugsH1icsqvbrmXGmGIwfz8U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":139685},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"a7fca24fd171e315ecf05398e6ed40595464b837","scripts":{"test":"bun test","build":"bun ../../scripts/clean-package-dist.ts . && bun build src/index.ts --outdir dist --target node --format esm && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit"},"_npmUser":{"name":"edwinho","email":"edwin_ho@me.com"},"repository":{"url":"git+https://github.com/eho/kotoba.git","type":"git","directory":"packages/core"},"_npmVersion":"11.9.0","description":"Framework-neutral language-learning data models, language profiles, and translation draft utilities.","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"~6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/kotoba-core_0.2.3_1781323977005_0.39614802666490667","host":"s3://npm-registry-packages-npm-production"}},"0.2.4":{"name":"@edwinho/kotoba-core","version":"0.2.4","keywords":["language-learning","translation","japanese","chinese","korean"],"author":{"name":"eho"},"license":"MIT","_id":"@edwinho/kotoba-core@0.2.4","maintainers":[{"name":"edwinho","email":"edwin_ho@me.com"}],"homepage":"https://github.com/eho/kotoba","bugs":{"url":"https://github.com/eho/kotoba/issues"},"dist":{"shasum":"c99582e525e5085b5bbbbc83e5945caf31ea7539","tarball":"https://registry.npmjs.org/@edwinho/kotoba-core/-/kotoba-core-0.2.4.tgz","fileCount":25,"integrity":"sha512-vQm0PIDKUrBH0hIL0YiELA2ckRBx39BU4fEGJexUiwCMfEFlG/Vc6R/NB3DIVyFSPYk9Fi18Na+qmo/pIOHbuw==","signatures":[{"sig":"MEQCIH1mmXaymXsddhkDevo4kGTJ5KGP23VGimGLGgS8SxMdAiATerKN7TNBzjClbTiXLOdQMmzPr7FZVFYUBm+U6iEtCA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":150683},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"75fa576cbc7498cdb68cdf0bdc1c00bf30737c9e","scripts":{"test":"bun test","build":"bun ../../scripts/clean-package-dist.ts . && bun build src/index.ts --outdir dist --target node --format esm && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit"},"_npmUser":{"name":"edwinho","email":"edwin_ho@me.com"},"repository":{"url":"git+https://github.com/eho/kotoba.git","type":"git","directory":"packages/core"},"_npmVersion":"11.9.0","description":"Framework-neutral language-learning data models, language profiles, and translation draft utilities.","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"~6.0.3"},"_npmOperationalInternal":{"tmp":"tmp/kotoba-core_0.2.4_1781345266422_0.061942693196067156","host":"s3://npm-registry-packages-npm-production"}},"0.2.5":{"name":"@edwinho/kotoba-core","version":"0.2.5","description":"Framework-neutral language-learning data models, language profiles, and translation draft utilities.","author":{"name":"eho"},"license":"MIT","type":"module","homepage":"https://github.com/eho/kotoba","repository":{"type":"git","url":"git+https://github.com/eho/kotoba.git","directory":"packages/core"},"bugs":{"url":"https://github.com/eho/kotoba/issues"},"keywords":["language-learning","translation","japanese","chinese","korean"],"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"build":"bun ../../scripts/clean-package-dist.ts . && bun build src/index.ts --outdir dist --target node --format esm && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit","test":"bun test"},"devDependencies":{"typescript":"~6.0.3"},"publishConfig":{"access":"public"},"gitHead":"722733ca1ec311d2100427c4674715ae11606d9d","_id":"@edwinho/kotoba-core@0.2.5","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-LzvrS65npKBGDeOD++ZPSBlCsu+iVikIxiNMOxm4e+60gskvPhBgRssLQoY4GBYkSh/xMe2869LpoKyA/289Vg==","shasum":"3b185453f1858cd0af6201d23e71494e2c312651","tarball":"https://registry.npmjs.org/@edwinho/kotoba-core/-/kotoba-core-0.2.5.tgz","fileCount":25,"unpackedSize":155140,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDFAW1wG8fTrQ6jN+94CHNvmdRyJKbLfYW7wgRShpBjJQIhAKT+fUKhRQELrUGqR/I4DrsOwd79dYbpyNa9dTBEnxhd"}]},"_npmUser":{"name":"edwinho","email":"edwin_ho@me.com"},"directories":{},"maintainers":[{"name":"edwinho","email":"edwin_ho@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/kotoba-core_0.2.5_1781421654775_0.2072516037520118"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-03T01:33:13.109Z","modified":"2026-06-14T07:20:55.018Z","0.1.0":"2026-06-03T01:33:13.406Z","0.2.0":"2026-06-05T01:05:04.717Z","0.2.1":"2026-06-10T22:57:17.356Z","0.2.2":"2026-06-13T00:51:47.510Z","0.2.3":"2026-06-13T04:12:57.132Z","0.2.4":"2026-06-13T10:07:46.602Z","0.2.5":"2026-06-14T07:20:54.921Z"},"bugs":{"url":"https://github.com/eho/kotoba/issues"},"author":{"name":"eho"},"license":"MIT","homepage":"https://github.com/eho/kotoba","keywords":["language-learning","translation","japanese","chinese","korean"],"repository":{"type":"git","url":"git+https://github.com/eho/kotoba.git","directory":"packages/core"},"description":"Framework-neutral language-learning data models, language profiles, and translation draft utilities.","maintainers":[{"name":"edwinho","email":"edwin_ho@me.com"}],"readme":"# @edwinho/kotoba-core\n\nFramework-neutral data contracts and utilities for Kotoba learning entries,\ntranslation drafts, language profiles, cache keys, and sanitizers.\n\nThis package is intentionally pure. It does not import Expo, React Native,\nGemini provider code, CLI code, app storage, service policy, or runtime\ntransport helpers.\n\n`@edwinho/kotoba-core` is the shared data-contract package used by Kotoba\nproviders, CLI tools, and app integrations. It does not translate text by itself\nand it does not call Gemini or hosted services.\n\n## Install\n\nInside this monorepo, depend on the package by version. Bun workspaces link the\nlocal package when the workspace version satisfies the range:\n\n```json\n{\n  \"dependencies\": {\n    \"@edwinho/kotoba-core\": \"^0.2.0\"\n  }\n}\n```\n\nFor external consumers:\n\n```bash\nbun add @edwinho/kotoba-core\n```\n\n## Concepts\n\nVersion `0.2.0` includes optional Japanese study-token metadata, the\n`StudyTokenMetadata` contract, and the `generateJapaneseFormTable()` helper for\nrendering deterministic verb and adjective form tables from trusted metadata.\n\n`TranslationDraft` is the normalized shape returned by translation providers\nbefore a phrase is saved. It carries source and target text, optional reading\nsupport, enrichment data, study tokens, freshness metadata, and capability\nflags that describe which enrichments are present. It keeps the same field\nshape while supporting future-language drafts through a generic language\nparameter. App consumers can keep using the default Japanese/Chinese draft\ntype, while core/provider tests can infer `TranslationDraft<\"ko\">` from\n`normalizeTranslationDraft({ targetLanguage: \"ko\", ... })`.\n\n`LearningEntry` and `LearningEntryDraft` are the saved-entry contracts used by\nlibrary and note surfaces.\n\nLanguage helpers such as `detectDirection`, `resolveLanguageProfile`,\n`resolveActiveLanguageContext`, and Chinese variant helpers keep language,\nscript, reading-system, and cache-scope decisions centralized.\n\nLanguage support is represented through capability profiles. `LearningLanguage`\ntracks product surfaces that only expose Japanese and Chinese today, while\n`SupportedLearningLanguage` also includes package-level languages such as\nKorean. Each `LanguageCapabilityProfile` declares language, script,\nreading-system, locale, register, romanization, and variant support.\n\nJapanese and Chinese profiles preserve the existing locale, reading,\nromanization, and variant behavior. Korean is included with Hangul/Revised\nRomanization, `ko-KR` speech locale metadata, and register support.\n\nValidators and normalizers accept provider-like or imported data defensively:\nmalformed sections are dropped and reported through `droppedSections`; valid\nsections are normalized into the public contracts. For example,\n`sanitizeStudyTokens` rejects out-of-range tokens and tokens whose surface text\ndoes not match the target text. `sanitizeEnrichmentData` drops malformed nested\nsections such as invalid grammar breakdowns, examples, contrasts, and cached\nnote details. `normalizeTranslationDraft` derives completeness and capability\nmetadata after reading support, Chinese metadata, and study tokens are\nnormalized.\n\nJapanese study tokens can optionally carry trusted morphology metadata under\n`StudyToken.metadata`. Phase 1 supports Japanese verb and adjective metadata\nonly:\n\n```ts\nimport type { StudyTokenMetadata } from \"@edwinho/kotoba-core\";\n\nconst metadata: StudyTokenMetadata = {\n  language: \"ja\",\n  category: \"morphology\",\n  kind: \"verb\",\n  surface: \"飲んだ\",\n  lemma: \"飲む\",\n  verbClass: \"godan-mu\",\n  observedForm: \"past\",\n  confidence: \"high\",\n};\n```\n\n`surface` is the study token that owns the metadata. Core may add\n`observedSurface` when deterministic repair can prove that a split sequence is\none observed morphology phrase, for example a token `高く` with\n`observedSurface: \"高くないです\"`.\n\n`sanitizeStudyTokens` preserves valid metadata and drops only malformed\nmetadata while keeping the token. Dropped metadata is reported through a\nmetadata-specific path such as `studyTokens[0].metadata`.\n\nThe sanitizer also performs bounded Japanese morphology repair for common\nprovider tokenization failures. For example, split polite verb sequences such as\n`食べ` + `ました`, and split adjective sequences such as `静か` + `でした`,\n`高く` + `ない` + `です`, and `静か` + `では` + `なかった`, can be normalized\ninto observed surfaces like `食べました`, `静かでした`, `高くないです`, and\n`静かではなかった` so form tables can mark the observed cell while preserving the\noriginal tappable token surface. These repairs require contiguous target-text\nspans and trusted verb/adjective metadata or clear adjective part-of-speech\nnotes; core does not guess arbitrary morphology from unrelated tokens.\n\n## Package Boundary\n\nThe public package set is intentionally split:\n\n- `@edwinho/kotoba-core` owns framework-neutral language profiles, draft contracts,\n  validators, normalizers, cache/version helpers, and learning-entry utilities.\n- `@edwinho/kotoba-gemini` owns Gemini prompt/schema/provider logic and requires a\n  caller-provided Gemini API key.\n- `@edwinho/kotoba-cli` is a terminal consumer of the public packages. It sends the\n  user's input text to Gemini through `@edwinho/kotoba-gemini` using the user's Gemini\n  API key.\n- App integrations own runtime policy, persistence, and product-specific\n  behavior around these contracts.\n\n## Examples\n\nNormalize a cloud translation result:\n\n```ts\nimport { normalizeTranslationDraft, sanitizeEnrichmentData } from \"@edwinho/kotoba-core\";\n\nconst { enrichment, droppedSections } = sanitizeEnrichmentData(providerPayload.enrichment);\n\nconst draft = normalizeTranslationDraft(\n  {\n    targetLanguage: \"ja\",\n    sourceLanguage: \"en\",\n    sourceText: \"I'm hungry\",\n    targetText: \"お腹が空きました。\",\n    readingSegments: [{ text: \"お腹\", reading: \"おなか\" }],\n    romanization: \"onaka ga sukimashita\",\n    translationText: \"I'm hungry.\",\n    register: \"polite\",\n    enrichment,\n    studyTokens: providerPayload.studyTokens,\n  },\n  {\n    source: \"cloud\",\n    canRegenerateWithCloud: true,\n  }\n);\n\nconsole.log(draft.completeness, draft.capabilities, droppedSections);\n```\n\nResolve language behavior:\n\n```ts\nimport {\n  detectDirection,\n  resolveActiveLanguageContext,\n  resolveLanguageProfile,\n  resolveTTSLocale,\n} from \"@edwinho/kotoba-core\";\n\nconst context = resolveActiveLanguageContext({\n  learningLanguage: \"zh\",\n  chineseVariant: \"cantonese-traditional\",\n});\n\nconst profile = resolveLanguageProfile(context.learningLanguage);\nconst inputMode = detectDirection(\"我肚餓\", context.learningLanguage);\nconst ttsLocale = resolveTTSLocale(\n  context.learningLanguage,\n  context.chineseDisplayScript ?? undefined,\n  context.chineseVariant ?? undefined\n);\n\nconsole.log(profile.defaultScript, inputMode, ttsLocale);\n```\n\nGenerate Japanese form tables from trusted metadata:\n\n```ts\nimport { generateJapaneseFormTable } from \"@edwinho/kotoba-core\";\n\nconst table = generateJapaneseFormTable({\n  language: \"ja\",\n  category: \"morphology\",\n  kind: \"verb\",\n  surface: \"飲んだ\",\n  lemma: \"飲む\",\n  verbClass: \"godan-mu\",\n  observedForm: \"past\",\n  confidence: \"high\",\n});\n\nconsole.log(table?.coreRows);\n// [\n//   {\n//     key: \"non-past\",\n//     label: \"Non-past\",\n//     plain: { value: \"飲む\" },\n//     polite: { value: \"飲みます\" },\n//   },\n//   {\n//     key: \"past\",\n//     label: \"Past\",\n//     plain: { value: \"飲んだ\", observed: true, note: \"Seen here\" },\n//     polite: { value: \"飲みました\" },\n//   },\n//   ...\n// ]\n\nconsole.log(table?.otherRows);\n// [\n//   { label: \"Te-form\", value: \"飲んで\" },\n//   { label: \"Potential\", value: \"飲める\" },\n// ]\n```\n\nBy default, only high-confidence metadata generates a table. Medium-confidence\nmetadata can be enabled explicitly:\n\n```ts\ngenerateJapaneseFormTable(metadata, { minConfidence: \"medium\" });\n```\n\nForm tables are deterministic once metadata is accepted. They should be treated\nas grammar support generated from validated metadata, not as a standalone\nJapanese dictionary. Consumers should prefer high-confidence metadata for\nlearner-facing surfaces and should hide or soften tables when metadata is\nmissing, low-confidence, or unsupported.\n\nResolve Korean as a future-language fixture:\n\n```ts\nimport { normalizeTranslationDraft, resolveLanguageProfile } from \"@edwinho/kotoba-core\";\n\nconst profile = resolveLanguageProfile(\"ko\");\n\nconst draft = normalizeTranslationDraft(\n  {\n    targetLanguage: \"ko\",\n    sourceLanguage: \"en\",\n    sourceText: \"I'm going now\",\n    targetText: \"저 지금 가요.\",\n    readingSystem: \"revised_romanization\",\n    readingSegments: [\n      { text: \"저\", reading: \"jeo\" },\n      { text: \"지금\", reading: \"jigeum\" },\n      { text: \"가요\", reading: \"gayo\" },\n    ],\n    romanization: \"jeo jigeum gayo\",\n    translationText: \"I'm going now.\",\n    register: \"polite\",\n  },\n  {\n    source: \"cloud\",\n    canRegenerateWithCloud: false,\n  }\n);\n\nconsole.log(profile.defaultTTSLocale, draft.readingSystem, draft.register);\n```\n\n## New-Language Checklist\n\nAdd future languages through bounded metadata and tests rather than changing the\n`TranslationDraft` field shape:\n\n1. Add profile metadata in `src/languages/languageProfiles.ts`, including\n   scripts, reading systems, locale metadata, register support, and variant\n   support.\n2. Add script metadata to `ScriptCode` and reading metadata to `ReadingSystem`\n   or a language-specific reading-system alias.\n3. Add detection fixtures for `detectDirection` when the target script can be\n   detected locally.\n4. Add provider prompt guidance and response-schema additions in the provider\n   package for language-specific reading, romanization, register, and\n   enrichment expectations.\n5. Add normalization and sanitizer fixtures that prove language-specific\n   metadata survives and unsupported fields are dropped.\n6. Add public API tests for profile resolution and any new runtime exports.\n7. Add product work separately if the language should appear in settings,\n   navigation, add phrase, library, TTS/STT, or persistence flows.\n\n## Verification\n\nRun package-level checks from the repository root:\n\n```bash\nbun run --cwd packages/core typecheck\nbun run --cwd packages/core test\nbun run --cwd packages/core build\n```\n\nFrom the repository root, `bun run build`, `bun run typecheck`, and\n`bun run test` run all package checks.\n","readmeFilename":"README.md"}