[{"data":1,"prerenderedAt":1003},["ShallowReactive",2],{"navigation_docs":3,"-eslint-plugin-rules":357,"-eslint-plugin-rules-surround":1000},[4,22,40,53,78,107,132,153,167,176,347],{"title":5,"path":6,"stem":7,"children":8,"page":21},"Introduction","\u002Fintroduction","1.introduction",[9,13,17],{"title":10,"path":11,"stem":12},"Why the-i18n-kit","\u002Fintroduction\u002Fwhy","1.introduction\u002F1.why",{"title":14,"path":15,"stem":16},"Architecture","\u002Fintroduction\u002Farchitecture","1.introduction\u002F2.architecture",{"title":18,"path":19,"stem":20},"Built for Agents","\u002Fintroduction\u002Fbuilt-for-agents","1.introduction\u002F3.built-for-agents",false,{"title":23,"icon":24,"path":25,"stem":26,"children":27,"page":21},"ESLint Plugin","i-lucide-shield-check","\u002Feslint-plugin","10.eslint-plugin",[28,32,36],{"title":29,"path":30,"stem":31},"Install and Presets","\u002Feslint-plugin\u002Finstall","10.eslint-plugin\u002F1.install",{"title":33,"path":34,"stem":35},"The Rules","\u002Feslint-plugin\u002Frules","10.eslint-plugin\u002F2.rules",{"title":37,"path":38,"stem":39},"Layer-Aware Missing Keys","\u002Feslint-plugin\u002Flayer-aware","10.eslint-plugin\u002F3.layer-aware",{"title":41,"path":42,"stem":43,"children":44,"page":21},"Getting Started","\u002Fgetting-started","2.getting-started",[45,49],{"title":46,"path":47,"stem":48},"Set Up the MCP Server","\u002Fgetting-started\u002Fagent-setup","2.getting-started\u002F1.agent-setup",{"title":50,"path":51,"stem":52},"From an Unconfigured Repository to a Gated CI Job","\u002Fgetting-started\u002Fcold-start","2.getting-started\u002F2.cold-start",{"title":54,"path":55,"stem":56,"children":57,"page":21},"Monorepos","\u002Fmonorepos","3.monorepos",[58,62,66,70,74],{"title":59,"path":60,"stem":61},"Layers","\u002Fmonorepos\u002Flayers","3.monorepos\u002F1.layers",{"title":63,"path":64,"stem":65},"The Consumer Graph","\u002Fmonorepos\u002Fconsumer-graph","3.monorepos\u002F2.consumer-graph",{"title":67,"path":68,"stem":69},"The Shared Library Scenario","\u002Fmonorepos\u002Fshared-libraries","3.monorepos\u002F3.shared-libraries",{"title":71,"path":72,"stem":73},"Duplicates and Divergence","\u002Fmonorepos\u002Fduplicates-and-divergence","3.monorepos\u002F4.duplicates-and-divergence",{"title":75,"path":76,"stem":77},"Misplaced Usages","\u002Fmonorepos\u002Fmisplaced-usages","3.monorepos\u002F5.misplaced-usages",{"title":79,"path":80,"stem":81,"children":82,"page":21},"Frameworks","\u002Fframeworks","4.frameworks",[83,87,91,95,99,103],{"title":84,"path":85,"stem":86},"Detection","\u002Fframeworks\u002Fdetection","4.frameworks\u002F1.detection",{"title":88,"path":89,"stem":90},"Nuxt","\u002Fframeworks\u002Fnuxt","4.frameworks\u002F2.nuxt",{"title":92,"path":93,"stem":94},"Laravel","\u002Fframeworks\u002Flaravel","4.frameworks\u002F3.laravel",{"title":96,"path":97,"stem":98},"Vue","\u002Fframeworks\u002Fvue","4.frameworks\u002F4.vue",{"title":100,"path":101,"stem":102},"React \u002F Next.js","\u002Fframeworks\u002Freact-next","4.frameworks\u002F5.react-next",{"title":104,"path":105,"stem":106},"Generic","\u002Fframeworks\u002Fgeneric","4.frameworks\u002F6.generic",{"title":108,"path":109,"stem":110,"children":111,"page":21},"Configuration","\u002Fconfiguration","5.configuration",[112,116,120,124,128],{"title":113,"path":114,"stem":115},"Where Configuration Lives","\u002Fconfiguration\u002Fwhere-config-lives","5.configuration\u002F1.where-config-lives",{"title":117,"path":118,"stem":119},"Precedence and Conflicts","\u002Fconfiguration\u002Fprecedence","5.configuration\u002F2.precedence",{"title":121,"path":122,"stem":123},"Declared vs. Derived Configuration","\u002Fconfiguration\u002Fdeclared-vs-derived","5.configuration\u002F3.declared-vs-derived",{"title":125,"path":126,"stem":127},"Configuration Fields","\u002Fconfiguration\u002Freference","5.configuration\u002F4.reference",{"title":129,"path":130,"stem":131},"Referring to Locales","\u002Fconfiguration\u002Flocale-refs","5.configuration\u002F5.locale-refs",{"title":133,"path":134,"stem":135,"children":136,"page":21},"Nuxt Module","\u002Fnuxt-module","6.nuxt-module",[137,141,145,149],{"title":138,"path":139,"stem":140},"Install and Setup","\u002Fnuxt-module\u002Finstall","6.nuxt-module\u002F1.install",{"title":142,"path":143,"stem":144},"What It Publishes","\u002Fnuxt-module\u002Fwhat-it-publishes","6.nuxt-module\u002F2.what-it-publishes",{"title":146,"path":147,"stem":148},"What It Validates","\u002Fnuxt-module\u002Fvalidation","6.nuxt-module\u002F3.validation",{"title":150,"path":151,"stem":152},"Options and Limits","\u002Fnuxt-module\u002Foptions-and-limits","6.nuxt-module\u002F4.options-and-limits",{"title":154,"icon":155,"path":156,"stem":157,"children":158,"page":21},"CI\u002FCD","i-lucide-git-pull-request","\u002Fci-cd","7.ci-cd",[159,163],{"title":160,"path":161,"stem":162},"GitHub Actions","\u002Fci-cd\u002Fgithub-actions","7.ci-cd\u002F1.github-actions",{"title":164,"path":165,"stem":166},"GitLab CI","\u002Fci-cd\u002Fgitlab-ci","7.ci-cd\u002F2.gitlab-ci",{"title":168,"path":169,"stem":170,"children":171,"page":21},"Concepts","\u002Fconcepts","8.concepts",[172],{"title":173,"path":174,"stem":175},"Translation Modes","\u002Fconcepts\u002Ftranslation-modes","8.concepts\u002F1.translation-modes",{"title":177,"path":178,"stem":179,"children":180,"page":-1},"Reference","\u002Freference","9.reference",[181,183,261,339,343],{"title":177,"path":178,"stem":182},"9.reference\u002Findex",{"title":184,"path":185,"stem":186,"children":187,"page":-1},"CLI Commands","\u002Freference\u002Fcli","9.reference\u002F1.cli\u002Findex",[188,189,193,197,201,205,209,213,217,221,225,229,233,237,241,245,249,253,257],{"title":184,"path":185,"stem":186},{"title":190,"path":191,"stem":192},"add","\u002Freference\u002Fcli\u002Fadd","9.reference\u002F1.cli\u002Fadd",{"title":194,"path":195,"stem":196},"check","\u002Freference\u002Fcli\u002Fcheck","9.reference\u002F1.cli\u002Fcheck",{"title":198,"path":199,"stem":200},"find-duplicates","\u002Freference\u002Fcli\u002Ffind-duplicates","9.reference\u002F1.cli\u002Ffind-duplicates",{"title":202,"path":203,"stem":204},"get","\u002Freference\u002Fcli\u002Fget","9.reference\u002F1.cli\u002Fget",{"title":206,"path":207,"stem":208},"init","\u002Freference\u002Fcli\u002Finit","9.reference\u002F1.cli\u002Finit",{"title":210,"path":211,"stem":212},"missing","\u002Freference\u002Fcli\u002Fmissing","9.reference\u002F1.cli\u002Fmissing",{"title":214,"path":215,"stem":216},"move","\u002Freference\u002Fcli\u002Fmove","9.reference\u002F1.cli\u002Fmove",{"title":218,"path":219,"stem":220},"remove","\u002Freference\u002Fcli\u002Fremove","9.reference\u002F1.cli\u002Fremove",{"title":222,"path":223,"stem":224},"remove-orphans","\u002Freference\u002Fcli\u002Fremove-orphans","9.reference\u002F1.cli\u002Fremove-orphans",{"title":226,"path":227,"stem":228},"rename","\u002Freference\u002Fcli\u002Frename","9.reference\u002F1.cli\u002Frename",{"title":230,"path":231,"stem":232},"scaffold","\u002Freference\u002Fcli\u002Fscaffold","9.reference\u002F1.cli\u002Fscaffold",{"title":234,"path":235,"stem":236},"scan","\u002Freference\u002Fcli\u002Fscan","9.reference\u002F1.cli\u002Fscan",{"title":238,"path":239,"stem":240},"search","\u002Freference\u002Fcli\u002Fsearch","9.reference\u002F1.cli\u002Fsearch",{"title":242,"path":243,"stem":244},"status","\u002Freference\u002Fcli\u002Fstatus","9.reference\u002F1.cli\u002Fstatus",{"title":246,"path":247,"stem":248},"translate","\u002Freference\u002Fcli\u002Ftranslate","9.reference\u002F1.cli\u002Ftranslate",{"title":250,"path":251,"stem":252},"translate-key","\u002Freference\u002Fcli\u002Ftranslate-key","9.reference\u002F1.cli\u002Ftranslate-key",{"title":254,"path":255,"stem":256},"update","\u002Freference\u002Fcli\u002Fupdate","9.reference\u002F1.cli\u002Fupdate",{"title":258,"path":259,"stem":260},"write","\u002Freference\u002Fcli\u002Fwrite","9.reference\u002F1.cli\u002Fwrite",{"title":262,"path":263,"stem":264,"children":265,"page":-1},"MCP Tools","\u002Freference\u002Fmcp","9.reference\u002F2.mcp\u002Findex",[266,267,271,275,279,283,287,291,295,299,303,307,311,315,319,323,327,331,335],{"title":262,"path":263,"stem":264},{"title":268,"path":269,"stem":270},"discover","\u002Freference\u002Fmcp\u002Fdiscover","9.reference\u002F2.mcp\u002Fdiscover",{"title":272,"path":273,"stem":274},"find_duplicate_keys","\u002Freference\u002Fmcp\u002Ffind_duplicate_keys","9.reference\u002F2.mcp\u002Ffind_duplicate_keys",{"title":276,"path":277,"stem":278},"find_empty_translations","\u002Freference\u002Fmcp\u002Ffind_empty_translations","9.reference\u002F2.mcp\u002Ffind_empty_translations",{"title":280,"path":281,"stem":282},"find_orphan_keys","\u002Freference\u002Fmcp\u002Ffind_orphan_keys","9.reference\u002F2.mcp\u002Ffind_orphan_keys",{"title":284,"path":285,"stem":286},"find_undefined_keys","\u002Freference\u002Fmcp\u002Ffind_undefined_keys","9.reference\u002F2.mcp\u002Ffind_undefined_keys",{"title":288,"path":289,"stem":290},"get_missing_translations","\u002Freference\u002Fmcp\u002Fget_missing_translations","9.reference\u002F2.mcp\u002Fget_missing_translations",{"title":292,"path":293,"stem":294},"get_translation_status","\u002Freference\u002Fmcp\u002Fget_translation_status","9.reference\u002F2.mcp\u002Fget_translation_status",{"title":296,"path":297,"stem":298},"get_translations","\u002Freference\u002Fmcp\u002Fget_translations","9.reference\u002F2.mcp\u002Fget_translations",{"title":300,"path":301,"stem":302},"list_namespaces","\u002Freference\u002Fmcp\u002Flist_namespaces","9.reference\u002F2.mcp\u002Flist_namespaces",{"title":304,"path":305,"stem":306},"move_translation_key","\u002Freference\u002Fmcp\u002Fmove_translation_key","9.reference\u002F2.mcp\u002Fmove_translation_key",{"title":308,"path":309,"stem":310},"remove_orphan_keys","\u002Freference\u002Fmcp\u002Fremove_orphan_keys","9.reference\u002F2.mcp\u002Fremove_orphan_keys",{"title":312,"path":313,"stem":314},"remove_translations","\u002Freference\u002Fmcp\u002Fremove_translations","9.reference\u002F2.mcp\u002Fremove_translations",{"title":316,"path":317,"stem":318},"rename_translation_key","\u002Freference\u002Fmcp\u002Frename_translation_key","9.reference\u002F2.mcp\u002Frename_translation_key",{"title":320,"path":321,"stem":322},"scaffold_locale","\u002Freference\u002Fmcp\u002Fscaffold_locale","9.reference\u002F2.mcp\u002Fscaffold_locale",{"title":324,"path":325,"stem":326},"search_translations","\u002Freference\u002Fmcp\u002Fsearch_translations","9.reference\u002F2.mcp\u002Fsearch_translations",{"title":328,"path":329,"stem":330},"translate_key","\u002Freference\u002Fmcp\u002Ftranslate_key","9.reference\u002F2.mcp\u002Ftranslate_key",{"title":332,"path":333,"stem":334},"translate_missing","\u002Freference\u002Fmcp\u002Ftranslate_missing","9.reference\u002F2.mcp\u002Ftranslate_missing",{"title":336,"path":337,"stem":338},"write_translations","\u002Freference\u002Fmcp\u002Fwrite_translations","9.reference\u002F2.mcp\u002Fwrite_translations",{"title":340,"path":341,"stem":342},"GitHub Action","\u002Freference\u002Faction","9.reference\u002F3.action",{"title":344,"path":345,"stem":346},"Programmatic API","\u002Freference\u002Fprogrammatic-api","9.reference\u002F4.programmatic-api",{"title":348,"icon":349,"path":350,"stem":351,"children":352,"page":21},"Extra Topics","i-lucide-microscope","\u002Fextra-topics","91.extra-topics",[353],{"title":354,"path":355,"stem":356},"How Detection Scores Adapters","\u002Fextra-topics\u002Fdetection-scoring","91.extra-topics\u002F1.detection-scoring",{"id":358,"title":33,"body":359,"description":456,"extension":994,"links":995,"meta":996,"navigation":529,"path":34,"seo":997,"stem":35,"__hash__":999},"docs\u002F10.eslint-plugin\u002F2.rules.md",{"type":360,"value":361,"toc":986},"minimark",[362,366,437,443,450,584,591,594,599,616,644,659,662,684,687,692,695,726,729,833,852,856,859,953,966,970,974,982],[363,364,365],"p",{},"Two rules, both about the same contract: every i18n call must leave the orphan\nscanner enough to bound which keys it can produce.",[363,367,368,369,373,374,377,378,381,382,373,385,388,389,392,393,396,397,400,401,388,404,407,408,410,411,414,415,417,418,421,422,424,425,428,429,432,433,436],{},"Both rules recognize an i18n call the way the scanner does: ",[370,371,372],"code",{},"$t",", ",[370,375,376],{},"$te"," and\n",[370,379,380],{},"$tc"," anywhere; a bare ",[370,383,384],{},"t",[370,386,387],{},"te"," or ",[370,390,391],{},"tc"," only where it resolves to a vue-i18n\nbinding — destructured from ",[370,394,395],{},"useI18n()",", imported from ",[370,398,399],{},"vue-i18n",",\n",[370,402,403],{},"@nuxtjs\u002Fi18n",[370,405,406],{},"petite-vue-i18n",", called on a ",[370,409,395],{}," composer, or\ncalled on ",[370,412,413],{},"$i18n",". A ",[370,416,384],{}," that resolves to a function parameter or an unrelated\n",[370,419,420],{},"const"," is not an i18n call, however many ",[370,423,395],{}," calls the file contains.\nLint and scan never disagree about what a call is — a rule firing on\n",[370,426,427],{},"client.t(...)"," would teach you to ignore it. ",[370,430,431],{},"\u003Ctemplate>"," expressions in\n",[370,434,435],{},".vue"," files are checked the same as script code.",[438,439,441],"h2",{"id":440},"literal-key-prefix",[370,442,440],{},[363,444,445,446,449],{},"Error in both presets. A dynamic key — a template literal with expressions, or\na ",[370,447,448],{},"+"," concatenation — must begin with a literal segment containing a dot.",[451,452,457],"pre",{"className":453,"code":454,"language":455,"meta":456,"style":456},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Fires: the key starts with a variable, so the scanner cannot\n\u002F\u002F bound what it produces.\nt(`${section}.title`)\nt(prefix + '.title')\n\n\u002F\u002F Passes: every key this call can produce lives under bookings.status.,\n\u002F\u002F and the scanner protects exactly that subtree.\nt(`bookings.status.${status}`)\nt('bookings.status.' + status)\n","ts","",[370,458,459,468,474,504,524,531,537,543,565],{"__ignoreMap":456},[460,461,464],"span",{"class":462,"line":463},"line",1,[460,465,467],{"class":466},"sHwdD","\u002F\u002F Fires: the key starts with a variable, so the scanner cannot\n",[460,469,471],{"class":462,"line":470},2,[460,472,473],{"class":466},"\u002F\u002F bound what it produces.\n",[460,475,477,480,484,488,491,494,498,501],{"class":462,"line":476},3,[460,478,384],{"class":479},"s2Zo4",[460,481,483],{"class":482},"sTEyZ","(",[460,485,487],{"class":486},"sMK4o","`${",[460,489,490],{"class":482},"section",[460,492,493],{"class":486},"}",[460,495,497],{"class":496},"sfazB",".title",[460,499,500],{"class":486},"`",[460,502,503],{"class":482},")\n",[460,505,507,509,512,514,517,519,522],{"class":462,"line":506},4,[460,508,384],{"class":479},[460,510,511],{"class":482},"(prefix ",[460,513,448],{"class":486},[460,515,516],{"class":486}," '",[460,518,497],{"class":496},[460,520,521],{"class":486},"'",[460,523,503],{"class":482},[460,525,527],{"class":462,"line":526},5,[460,528,530],{"emptyLinePlaceholder":529},true,"\n",[460,532,534],{"class":462,"line":533},6,[460,535,536],{"class":466},"\u002F\u002F Passes: every key this call can produce lives under bookings.status.,\n",[460,538,540],{"class":462,"line":539},7,[460,541,542],{"class":466},"\u002F\u002F and the scanner protects exactly that subtree.\n",[460,544,546,548,550,552,555,558,560,563],{"class":462,"line":545},8,[460,547,384],{"class":479},[460,549,483],{"class":482},[460,551,500],{"class":486},[460,553,554],{"class":496},"bookings.status.",[460,556,557],{"class":486},"${",[460,559,242],{"class":482},[460,561,562],{"class":486},"}`",[460,564,503],{"class":482},[460,566,568,570,572,574,576,578,581],{"class":462,"line":567},9,[460,569,384],{"class":479},[460,571,483],{"class":482},[460,573,521],{"class":486},[460,575,554],{"class":496},[460,577,521],{"class":486},[460,579,580],{"class":486}," +",[460,582,583],{"class":482}," status)\n",[363,585,586,587,590],{},"The mechanism this defends: the scanner turns a literal dotted prefix into a\nbounded pattern and protects only the keys under it. A key that starts with a\nvariable gives it nothing to anchor on — its options are over-protecting every\n",[370,588,589],{},"*.title"," key in the catalog or deleting live ones. This exact idiom once\nput 34 live keys in the safe-to-delete bucket; the rule makes it unwritable.",[363,592,593],{},"Plain string literals, templates without expressions, and fully-literal keys\nnever fire. When a literal prefix is impossible, look full keys up from a\nlocal map of literals instead — the next rule explains why that shape is safe.",[438,595,597],{"id":596},"runtime-key-needs-declared-namespace",[370,598,596],{},[363,600,601,602,605,606,609,610,615],{},"Warn in ",[370,603,604],{},"recommended",", error in ",[370,607,608],{},"strict"," — see\n",[611,612,614],"a",{"href":613},"\u002Feslint-plugin\u002Finstall#3-triage-then-promote","Triage, Then Promote"," for why.\nIt fires when the key is entirely runtime data:",[451,617,619],{"className":453,"code":618,"language":455,"meta":456,"style":456},"\u002F\u002F Fires: the key exists only at runtime. The scanner sees nothing here,\n\u002F\u002F so whatever keys the wire sends look orphaned.\nt(view.name_key)\n",[370,620,621,626,631],{"__ignoreMap":456},[460,622,623],{"class":462,"line":463},[460,624,625],{"class":466},"\u002F\u002F Fires: the key exists only at runtime. The scanner sees nothing here,\n",[460,627,628],{"class":462,"line":470},[460,629,630],{"class":466},"\u002F\u002F so whatever keys the wire sends look orphaned.\n",[460,632,633,635,638,641],{"class":462,"line":476},[460,634,384],{"class":479},[460,636,637],{"class":482},"(view",[460,639,640],{"class":486},".",[460,642,643],{"class":482},"name_key)\n",[363,645,646,647,650,651,654,655,658],{},"This is the shape behind a real deletion incident: a backend seeded key names\nlike ",[370,648,649],{},"views.defaults.displayApp"," into a ",[370,652,653],{},"name_key"," column, the frontend called\n",[370,656,657],{},"t(view.name_key)",", and no frontend scan could ever see which keys that call\nkeeps alive. Four live keys landed in the deletion bucket and were caught only\nby a manual cross-repo audit.",[363,660,661],{},"The rule demands two things, both checkable:",[663,664,665,673],"ol",{},[666,667,668,669,672],"li",{},"An ",[370,670,671],{},"i18n-namespace:"," comment on the call's line or the line above, naming\nthe pattern the keys draw from.",[666,674,675,676,679,680,683],{},"That exact pattern declared under ",[370,677,678],{},"orphanScan"," → ",[370,681,682],{},"ignorePatterns"," in the\nkit config — the place the scanner actually reads.",[363,685,686],{},"An annotation naming a pattern the config does not declare is reported as\ndrift, with the config path in the message: the comment only protects keys if\nthe scanner reads the same declaration. A runtime key with no kit config\nanywhere above the file is also reported — there is nowhere to declare the\nnamespace, so the scanner will report its keys as deletable.",[688,689,691],"h3",{"id":690},"the-annotation-workflow","The Annotation Workflow",[363,693,694],{},"Annotate the call:",[451,696,699],{"className":453,"code":697,"filename":698,"language":455,"meta":456,"style":456},"\u002F\u002F i18n-namespace: views.defaults.**\nconst label = t(view.name_key)\n","components\u002FViewCard.vue",[370,700,701,706],{"__ignoreMap":456},[460,702,703],{"class":462,"line":463},[460,704,705],{"class":466},"\u002F\u002F i18n-namespace: views.defaults.**\n",[460,707,708,711,714,717,720,722,724],{"class":462,"line":470},[460,709,420],{"class":710},"spNyl",[460,712,713],{"class":482}," label ",[460,715,716],{"class":486},"=",[460,718,719],{"class":479}," t",[460,721,637],{"class":482},[460,723,640],{"class":486},[460,725,643],{"class":482},[363,727,728],{},"Declare the same pattern in the config, under the layer that owns the keys:",[451,730,733],{"className":453,"code":731,"filename":732,"language":455,"meta":456,"style":456},"import { defineI18nKitConfig } from '@the-i18n-kit\u002Fcli\u002Fconfig'\n\nexport default defineI18nKitConfig({\n  orphanScan: {\n    root: { ignorePatterns: ['views.defaults.**'] },\n  },\n})\n","i18n-kit.config.ts",[370,734,735,761,765,780,792,822,827],{"__ignoreMap":456},[460,736,737,741,744,747,750,753,755,758],{"class":462,"line":463},[460,738,740],{"class":739},"s7zQu","import",[460,742,743],{"class":486}," {",[460,745,746],{"class":482}," defineI18nKitConfig",[460,748,749],{"class":486}," }",[460,751,752],{"class":739}," from",[460,754,516],{"class":486},[460,756,757],{"class":496},"@the-i18n-kit\u002Fcli\u002Fconfig",[460,759,760],{"class":486},"'\n",[460,762,763],{"class":462,"line":470},[460,764,530],{"emptyLinePlaceholder":529},[460,766,767,770,773,775,777],{"class":462,"line":476},[460,768,769],{"class":739},"export",[460,771,772],{"class":739}," default",[460,774,746],{"class":479},[460,776,483],{"class":482},[460,778,779],{"class":486},"{\n",[460,781,782,786,789],{"class":462,"line":506},[460,783,785],{"class":784},"swJcz","  orphanScan",[460,787,788],{"class":486},":",[460,790,791],{"class":486}," {\n",[460,793,794,797,799,801,804,806,809,811,814,816,819],{"class":462,"line":526},[460,795,796],{"class":784},"    root",[460,798,788],{"class":486},[460,800,743],{"class":486},[460,802,803],{"class":784}," ignorePatterns",[460,805,788],{"class":486},[460,807,808],{"class":482}," [",[460,810,521],{"class":486},[460,812,813],{"class":496},"views.defaults.**",[460,815,521],{"class":486},[460,817,818],{"class":482},"] ",[460,820,821],{"class":486},"},\n",[460,823,824],{"class":462,"line":533},[460,825,826],{"class":486},"  },\n",[460,828,829,831],{"class":462,"line":539},[460,830,493],{"class":486},[460,832,503],{"class":482},[363,834,835,836,838,839,842,843,373,845,388,848,851],{},"The rule accepts the pattern from any layer's ",[370,837,682],{}," — which layer\nit belongs under is the scanner's concern, covered in\n",[611,840,841],{"href":64},"the consumer graph",". The config is found by\nwalking up from the linted file (",[370,844,732],{},[370,846,847],{},".mjs",[370,849,850],{},".js","),\nloaded without a build step, and re-read when its mtime changes — a\ndeclaration you just added stops the report without an editor restart.",[688,853,855],{"id":854},"what-never-fires","What Never Fires",[363,857,858],{},"The leniencies are the scanner's own, restated — what the candidate net\nalready protects, the rule does not question:",[860,861,862,875],"table",{},[863,864,865],"thead",{},[866,867,868,872],"tr",{},[869,870,871],"th",{},"Shape",[869,873,874],{},"Why it is safe",[876,877,878,893,910,924,940],"tbody",{},[866,879,880,887],{},[881,882,883,886],"td",{},[370,884,885],{},"t('bookings.title')",", templates, concatenation",[881,888,889,890,892],{},"Readable; the built ones are ",[370,891,440],{},"'s turf",[866,894,895,904],{},[881,896,897,900,901],{},[370,898,899],{},"const KEY = 'bookings.title'"," … ",[370,902,903],{},"t(KEY)",[881,905,906,907,909],{},"A same-file ",[370,908,420],{}," holding a string literal",[866,911,912,919],{},[881,913,914,900,917],{},[370,915,916],{},"const KEY = `bookings.${id}`",[370,918,903],{},[881,920,906,921,923],{},[370,922,420],{}," holding a dotted-prefix template",[866,925,926,934],{},[881,927,928,900,931],{},[370,929,930],{},"const LABELS = { a: 'x.a', b: 'x.b' }",[370,932,933],{},"t(LABELS[state])",[881,935,936,937,939],{},"A lookup into a same-file ",[370,938,420],{}," map of string literals",[866,941,942,950],{},[881,943,944,373,947],{},[370,945,946],{},"te(x)",[370,948,949],{},"$te(x)",[881,951,952],{},"An existence check commits to nothing; only the translating call keeps keys alive",[363,954,955,956,958,959,388,962,965],{},"Only ",[370,957,420],{}," bindings count. A ",[370,960,961],{},"let",[370,963,964],{},"var"," can hold anything by the time\nthe call runs, so a runtime key behind one is reported. A conditional\nexpression is runtime data if either branch is.",[967,968,969],"warning",{},"Refactoring a protected shape into an unprotected one — a dotted template\ninto a lookup on data from a prop, say — is exactly when this rule fires and\nshould. Derived protection evaporates silently otherwise; the report is the\nonly signal that it did.",[438,971,973],{"id":972},"next","Next",[975,976,977],"ul",{},[666,978,979,981],{},[611,980,37],{"href":38}," — the other half of\nthe plugin: does this key exist for this app?",[983,984,985],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":456,"searchDepth":476,"depth":476,"links":987},[988,989,993],{"id":440,"depth":470,"text":440},{"id":596,"depth":470,"text":596,"children":990},[991,992],{"id":690,"depth":476,"text":691},{"id":854,"depth":476,"text":855},{"id":972,"depth":470,"text":973},"md",null,{},{"description":998,"title":33},"What literal-key-prefix and runtime-key-needs-declared-namespace fire on, what they deliberately ignore, and how the i18n-namespace annotation ties a call to the kit config.","lHVFSQUXT7j1QCK0f-2ABbK3E6gBgwJ5ZJecfbZ2OR8",[1001,1002],{"title":29,"path":30,"stem":31,"description":456,"children":-1},{"title":37,"path":38,"stem":39,"description":456,"children":-1},1787604647515]