[{"data":1,"prerenderedAt":999},["ShallowReactive",2],{"page-\u002Fblog\u002Fnuxt-content-i18n-architecture-refactor-zh-CN":3,"\u002Fblog\u002Fnuxt-content-i18n-architecture-refactor-zh-CN-surround":993},{"id":4,"title":5,"body":6,"description":12,"extension":977,"lang":545,"meta":978,"navigation":555,"path":980,"seo":981,"sitemap":982,"stem":983,"__hash__":984,"date":985,"category":986,"tags":987},"article\u002Fblog\u002Fnuxt-content-i18n-architecture-refactor\u002Findex.zh-CN.md","Nuxt Content 多语言文件管理，我换了一种组织方式",{"type":7,"value":8,"toc":974},"minimark",[9,13,16,27,30,48,51,59,62,68,71,74,80,83,86,89,95,98,101,126,129,133,140,397,403,862,865,961,964,967,970],[10,11,12],"p",{},"我的博客网站使用的是 Nuxt 的框架。由于支持了多语言，原本比较简单的问题，在多语言的前提下会变得复杂一些。比如：文件的管理。",[10,14,15],{},"Nuxt Content 与 i18n 多语言框架结合时，官方推荐的目录管理结构是：",[17,18,23],"pre",{"className":19,"code":21,"language":22},[20],"language-text","content\u002F\n  en\u002F\n    index.md\n    about.md\n    blog\u002F\n      post-1.md\n  zh-CN\u002F\n    index.md\n    about.md\n    blog\u002F\n      post-1.md\n","text",[24,25,21],"code",{"__ignoreMap":26},"",[10,28,29],{},"通过目录结构来分别管理语言的内容。这种结构的优点很明显：",[31,32,33,37],"ol",{},[34,35,36],"li",{},"结构目录清晰",[34,38,39,40,43,44,47],{},"天然的跟 i18n 的 route 生成是对应的，切换语言时，url 跟文件路径是关联的。比如 ",[24,41,42],{},"content\u002Fen\u002Fblog\u002Fpost-1.md"," 生成的 url 就会是 ",[24,45,46],{},"\u002Fen\u002Fblog\u002Fpost-1"," 。",[10,49,50],{},"但是！在我使用了半年后，这种结构有很明显的弊端：",[31,52,53,56],{},[34,54,55],{},"不同语言的文件分散到了不同的文件夹，导致我要修改某篇文章的时候，需要同时去两个文件夹下找文件",[34,57,58],{},"对于文章的基础信息，比如时间、分类、标签，没有提取成公共信息，导致修改的时候会有重复工作。有时候会导致中文改了分类，英文忘记了的情况",[10,60,61],{},"上面两点在日常内容管理时非常的不方便。所以我想改成这样的结构：",[17,63,66],{"className":64,"code":65,"language":22},[20],"content\u002Fblog\n  post-a\u002F\n    index.en.md\n    index.zh-CN.md\n    meta.json\n  post-b\u002F\n    index.en.md\n    index.zh-CN.md\n    meta.json\n",[24,67,65],{"__ignoreMap":26},[10,69,70],{},"不按照语言分类，而是按照内容进行聚合。对于一篇文章，它所有的语言文件放在一起，然后要把基础信息抽离出来做成公共部分。这样能够更方便的定位到文件，同时修改基础信息时也不会遗漏。",[10,72,73],{},"方向定好后，我就开始琢磨如何实现：",[17,75,78],{"className":76,"code":77,"language":22},[20],"“文件目录直接改问题不大，最关键的路由的处理”\n“新的结构按照现有的路由机制，会生成 \u002Fblog\u002Fpost-a\u002Findex.en 这样的路由，语言标识放到末尾了，明显不是我想要的”\n“所以关键的关键，就是要重新修改路由生成的机制”\n",[24,79,77],{"__ignoreMap":26},[10,81,82],{},"于是我开始吭哧吭哧跟 AI 聊，看看怎么修改路由机制。",[10,84,85],{},"AI 非常的认真、敬业，绞尽脑汁给我出主意：一会儿建议我根据 nuxt 框架 router 劫持做调整，一会儿又觉得应该从 i18n 路由生成机制的源头处理，过一会儿又推荐我重点调整 nuxt content 的配置。",[10,87,88],{},"经过了好几轮的修改后，AI 开始说车轱辘话，我意识到不对劲了。我现在警惕性比之前高很多了。于是我立马放弃 AI，开始自行去搜索如何自定义 url，去找 i18n 的目录管理。果不其然，有其他人遇到过一样的问题，甚至还贴心的给出了代码。但是，就是没有路由的调整。只有目录结构，以及 slug 文件的写法。",[17,90,93],{"className":91,"code":92,"language":22},[20],"pages\u002Fblog\u002F[...slug].vue 这种写法是表示页面渲染的时候 \u002Fblog 路径下的页面都会匹配到这个文件进行处理。\n",[24,94,92],{"__ignoreMap":26},[10,96,97],{},"为什么都没有路由配置的说明？只有 slug 文件的逻辑，只有 slug，slug...... slug？！",[10,99,100],{},"哦嚯，我悟了！所以根本可以不用管什么路由生成的机制。只需要做两点处理就好了：",[31,102,103,113],{},[34,104,105,106,109,110],{},"显示在页面的超链接，从 ",[24,107,108],{},"\u002Fblog\u002Fpost-a\u002Findex.en"," 替换成 ",[24,111,112],{},"\u002Fen\u002Fblog\u002Fpost-a",[34,114,115,116,119,120,122,123,125],{},"在 ",[24,117,118],{},"[...slug].vue"," 文件中，解析文件的时候反过来解析，把拿到的 ",[24,121,112],{}," url 解析为文件地址 ",[24,124,108],{}," 再去获取文件就好拉！",[10,127,128],{},"所以压根一开始我处理的方向就偏了，修改路由生成规则目前应该是没有很好的办法的。但是通过修改页面显示和内容获取的部分，同样可以做到。",[130,131,132],"h2",{"id":132},"具体的代码实现",[10,134,135,136,139],{},"前面其实漏了一点没说明，公共信息如何处理？在 ",[24,137,138],{},"content.config.ts"," 中抽离出新的一层结构定义：",[17,141,145],{"className":142,"code":143,"language":144,"meta":26,"style":26},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","collections: {\n    article: defineCollection(\n      asSitemapCollection({\n        type: \"page\",\n        source: \"blog\u002F*\u002Findex.{en,zh-CN}.md\",\n        schema: z.object({\n          \u002F\u002F xxxx\n        }),\n      } as any),\n    ),\n    \u002F\u002F 新增一个数据合集，到时候代码里通过文件路径进行匹配找到同一个文章下的公共信息\n    articleMetadata: defineCollection({\n      type: \"data\",\n      source: \"blog\u002F*\u002Fmeta.json\",\n      schema: z.object({\n        \u002F\u002F xxxxx\n      }),\n    }),\n}\n","ts",[24,146,147,163,179,191,212,229,251,258,269,286,294,300,314,331,348,366,372,381,391],{"__ignoreMap":26},[148,149,152,156,160],"span",{"class":150,"line":151},"line",1,[148,153,155],{"class":154},"sBMFI","collections",[148,157,159],{"class":158},"sMK4o",":",[148,161,162],{"class":158}," {\n",[148,164,166,169,171,175],{"class":150,"line":165},2,[148,167,168],{"class":154},"    article",[148,170,159],{"class":158},[148,172,174],{"class":173},"s2Zo4"," defineCollection",[148,176,178],{"class":177},"swJcz","(\n",[148,180,182,185,188],{"class":150,"line":181},3,[148,183,184],{"class":173},"      asSitemapCollection",[148,186,187],{"class":177},"(",[148,189,190],{"class":158},"{\n",[148,192,194,197,199,202,206,209],{"class":150,"line":193},4,[148,195,196],{"class":177},"        type",[148,198,159],{"class":158},[148,200,201],{"class":158}," \"",[148,203,205],{"class":204},"sfazB","page",[148,207,208],{"class":158},"\"",[148,210,211],{"class":158},",\n",[148,213,215,218,220,222,225,227],{"class":150,"line":214},5,[148,216,217],{"class":177},"        source",[148,219,159],{"class":158},[148,221,201],{"class":158},[148,223,224],{"class":204},"blog\u002F*\u002Findex.{en,zh-CN}.md",[148,226,208],{"class":158},[148,228,211],{"class":158},[148,230,232,235,237,241,244,247,249],{"class":150,"line":231},6,[148,233,234],{"class":177},"        schema",[148,236,159],{"class":158},[148,238,240],{"class":239},"sTEyZ"," z",[148,242,243],{"class":158},".",[148,245,246],{"class":173},"object",[148,248,187],{"class":177},[148,250,190],{"class":158},[148,252,254],{"class":150,"line":253},7,[148,255,257],{"class":256},"sHwdD","          \u002F\u002F xxxx\n",[148,259,261,264,267],{"class":150,"line":260},8,[148,262,263],{"class":158},"        }",[148,265,266],{"class":177},")",[148,268,211],{"class":158},[148,270,272,275,279,282,284],{"class":150,"line":271},9,[148,273,274],{"class":158},"      }",[148,276,278],{"class":277},"s7zQu"," as",[148,280,281],{"class":154}," any",[148,283,266],{"class":177},[148,285,211],{"class":158},[148,287,289,292],{"class":150,"line":288},10,[148,290,291],{"class":177},"    )",[148,293,211],{"class":158},[148,295,297],{"class":150,"line":296},11,[148,298,299],{"class":256},"    \u002F\u002F 新增一个数据合集，到时候代码里通过文件路径进行匹配找到同一个文章下的公共信息\n",[148,301,303,306,308,310,312],{"class":150,"line":302},12,[148,304,305],{"class":154},"    articleMetadata",[148,307,159],{"class":158},[148,309,174],{"class":173},[148,311,187],{"class":177},[148,313,190],{"class":158},[148,315,317,320,322,324,327,329],{"class":150,"line":316},13,[148,318,319],{"class":177},"      type",[148,321,159],{"class":158},[148,323,201],{"class":158},[148,325,326],{"class":204},"data",[148,328,208],{"class":158},[148,330,211],{"class":158},[148,332,334,337,339,341,344,346],{"class":150,"line":333},14,[148,335,336],{"class":177},"      source",[148,338,159],{"class":158},[148,340,201],{"class":158},[148,342,343],{"class":204},"blog\u002F*\u002Fmeta.json",[148,345,208],{"class":158},[148,347,211],{"class":158},[148,349,351,354,356,358,360,362,364],{"class":150,"line":350},15,[148,352,353],{"class":177},"      schema",[148,355,159],{"class":158},[148,357,240],{"class":239},[148,359,243],{"class":158},[148,361,246],{"class":173},[148,363,187],{"class":177},[148,365,190],{"class":158},[148,367,369],{"class":150,"line":368},16,[148,370,371],{"class":256},"        \u002F\u002F xxxxx\n",[148,373,375,377,379],{"class":150,"line":374},17,[148,376,274],{"class":158},[148,378,266],{"class":177},[148,380,211],{"class":158},[148,382,384,387,389],{"class":150,"line":383},18,[148,385,386],{"class":158},"    }",[148,388,266],{"class":177},[148,390,211],{"class":158},[148,392,394],{"class":150,"line":393},19,[148,395,396],{"class":158},"}\n",[10,398,115,399,402],{},[24,400,401],{},"pages\u002Fblog\u002F[...slug].vue"," 中，修改获取文件信息的方法，这里只列关键代码：",[17,404,406],{"className":142,"code":405,"language":144,"meta":26,"style":26},"const { data: post } = await useAsyncData(\n  `page-${normalizedPath.value}-${locale.value}`,\n  async () => {\n    const slug = currentSlug.value;  \u002F\u002F 从 url 上 \u002Fen\u002Fblog\u002Fpost-a 获取到 post-a 这个唯一标识\n    const localeValue = locale.value as \"en\" | \"zh-CN\";\n\n    if (!slug) return null;\n\n    \u002F\u002F 重新拼接成原始文件的地址，如 \u002Fblog\u002Fpost-a\u002Findex.en\n    const contentStem = buildArticleContentStem(slug, localeValue);\n    const metadataStem = buildArticleMetadataStem(slug);\n\n    const [articleMetadata, articleFile] = await Promise.all([\n      queryCollection(\"articleMetadata\")\n        .where(\"stem\", \"=\", metadataStem)\n        .first(),\n      queryCollection(\"article\").where(\"stem\", \"=\", contentStem).first(),\n    ]);\n\n    if (!articleFile) return null;\n\n    \u002F\u002F 将两边的数据融合在一起，最终提供出去渲染\n    return combineArticleData(articleMetadata || {}, articleFile, localeValue);\n  },\n);\n",[24,407,408,439,477,490,513,551,557,580,584,589,614,634,638,671,687,719,731,780,787,791,809,814,820,849,855],{"__ignoreMap":26},[148,409,410,414,417,420,422,425,428,431,434,437],{"class":150,"line":151},[148,411,413],{"class":412},"spNyl","const",[148,415,416],{"class":158}," {",[148,418,419],{"class":177}," data",[148,421,159],{"class":158},[148,423,424],{"class":239}," post ",[148,426,427],{"class":158},"}",[148,429,430],{"class":158}," =",[148,432,433],{"class":277}," await",[148,435,436],{"class":173}," useAsyncData",[148,438,178],{"class":239},[148,440,441,444,447,450,453,455,458,460,463,465,468,470,472,475],{"class":150,"line":165},[148,442,443],{"class":158},"  `",[148,445,446],{"class":204},"page-",[148,448,449],{"class":158},"${",[148,451,452],{"class":239},"normalizedPath",[148,454,243],{"class":158},[148,456,457],{"class":239},"value",[148,459,427],{"class":158},[148,461,462],{"class":204},"-",[148,464,449],{"class":158},[148,466,467],{"class":239},"locale",[148,469,243],{"class":158},[148,471,457],{"class":239},[148,473,474],{"class":158},"}`",[148,476,211],{"class":158},[148,478,479,482,485,488],{"class":150,"line":181},[148,480,481],{"class":412},"  async",[148,483,484],{"class":158}," ()",[148,486,487],{"class":412}," =>",[148,489,162],{"class":158},[148,491,492,495,498,500,503,505,507,510],{"class":150,"line":193},[148,493,494],{"class":412},"    const",[148,496,497],{"class":239}," slug",[148,499,430],{"class":158},[148,501,502],{"class":239}," currentSlug",[148,504,243],{"class":158},[148,506,457],{"class":239},[148,508,509],{"class":158},";",[148,511,512],{"class":256},"  \u002F\u002F 从 url 上 \u002Fen\u002Fblog\u002Fpost-a 获取到 post-a 这个唯一标识\n",[148,514,515,517,520,522,525,527,529,531,533,536,538,541,543,546,548],{"class":150,"line":214},[148,516,494],{"class":412},[148,518,519],{"class":239}," localeValue",[148,521,430],{"class":158},[148,523,524],{"class":239}," locale",[148,526,243],{"class":158},[148,528,457],{"class":239},[148,530,278],{"class":277},[148,532,201],{"class":158},[148,534,535],{"class":204},"en",[148,537,208],{"class":158},[148,539,540],{"class":158}," |",[148,542,201],{"class":158},[148,544,545],{"class":204},"zh-CN",[148,547,208],{"class":158},[148,549,550],{"class":158},";\n",[148,552,553],{"class":150,"line":231},[148,554,556],{"emptyLinePlaceholder":555},true,"\n",[148,558,559,562,565,568,571,574,577],{"class":150,"line":253},[148,560,561],{"class":277},"    if",[148,563,564],{"class":177}," (",[148,566,567],{"class":158},"!",[148,569,570],{"class":239},"slug",[148,572,573],{"class":177},") ",[148,575,576],{"class":277},"return",[148,578,579],{"class":158}," null;\n",[148,581,582],{"class":150,"line":260},[148,583,556],{"emptyLinePlaceholder":555},[148,585,586],{"class":150,"line":271},[148,587,588],{"class":256},"    \u002F\u002F 重新拼接成原始文件的地址，如 \u002Fblog\u002Fpost-a\u002Findex.en\n",[148,590,591,593,596,598,601,603,605,608,610,612],{"class":150,"line":288},[148,592,494],{"class":412},[148,594,595],{"class":239}," contentStem",[148,597,430],{"class":158},[148,599,600],{"class":173}," buildArticleContentStem",[148,602,187],{"class":177},[148,604,570],{"class":239},[148,606,607],{"class":158},",",[148,609,519],{"class":239},[148,611,266],{"class":177},[148,613,550],{"class":158},[148,615,616,618,621,623,626,628,630,632],{"class":150,"line":296},[148,617,494],{"class":412},[148,619,620],{"class":239}," metadataStem",[148,622,430],{"class":158},[148,624,625],{"class":173}," buildArticleMetadataStem",[148,627,187],{"class":177},[148,629,570],{"class":239},[148,631,266],{"class":177},[148,633,550],{"class":158},[148,635,636],{"class":150,"line":302},[148,637,556],{"emptyLinePlaceholder":555},[148,639,640,642,645,648,650,653,656,658,660,663,665,668],{"class":150,"line":316},[148,641,494],{"class":412},[148,643,644],{"class":158}," [",[148,646,647],{"class":239},"articleMetadata",[148,649,607],{"class":158},[148,651,652],{"class":239}," articleFile",[148,654,655],{"class":158},"]",[148,657,430],{"class":158},[148,659,433],{"class":277},[148,661,662],{"class":154}," Promise",[148,664,243],{"class":158},[148,666,667],{"class":173},"all",[148,669,670],{"class":177},"([\n",[148,672,673,676,678,680,682,684],{"class":150,"line":333},[148,674,675],{"class":173},"      queryCollection",[148,677,187],{"class":177},[148,679,208],{"class":158},[148,681,647],{"class":204},[148,683,208],{"class":158},[148,685,686],{"class":177},")\n",[148,688,689,692,695,697,699,702,704,706,708,711,713,715,717],{"class":150,"line":350},[148,690,691],{"class":158},"        .",[148,693,694],{"class":173},"where",[148,696,187],{"class":177},[148,698,208],{"class":158},[148,700,701],{"class":204},"stem",[148,703,208],{"class":158},[148,705,607],{"class":158},[148,707,201],{"class":158},[148,709,710],{"class":204},"=",[148,712,208],{"class":158},[148,714,607],{"class":158},[148,716,620],{"class":239},[148,718,686],{"class":177},[148,720,721,723,726,729],{"class":150,"line":368},[148,722,691],{"class":158},[148,724,725],{"class":173},"first",[148,727,728],{"class":177},"()",[148,730,211],{"class":158},[148,732,733,735,737,739,742,744,746,748,750,752,754,756,758,760,762,764,766,768,770,772,774,776,778],{"class":150,"line":374},[148,734,675],{"class":173},[148,736,187],{"class":177},[148,738,208],{"class":158},[148,740,741],{"class":204},"article",[148,743,208],{"class":158},[148,745,266],{"class":177},[148,747,243],{"class":158},[148,749,694],{"class":173},[148,751,187],{"class":177},[148,753,208],{"class":158},[148,755,701],{"class":204},[148,757,208],{"class":158},[148,759,607],{"class":158},[148,761,201],{"class":158},[148,763,710],{"class":204},[148,765,208],{"class":158},[148,767,607],{"class":158},[148,769,595],{"class":239},[148,771,266],{"class":177},[148,773,243],{"class":158},[148,775,725],{"class":173},[148,777,728],{"class":177},[148,779,211],{"class":158},[148,781,782,785],{"class":150,"line":383},[148,783,784],{"class":177},"    ])",[148,786,550],{"class":158},[148,788,789],{"class":150,"line":393},[148,790,556],{"emptyLinePlaceholder":555},[148,792,794,796,798,800,803,805,807],{"class":150,"line":793},20,[148,795,561],{"class":277},[148,797,564],{"class":177},[148,799,567],{"class":158},[148,801,802],{"class":239},"articleFile",[148,804,573],{"class":177},[148,806,576],{"class":277},[148,808,579],{"class":158},[148,810,812],{"class":150,"line":811},21,[148,813,556],{"emptyLinePlaceholder":555},[148,815,817],{"class":150,"line":816},22,[148,818,819],{"class":256},"    \u002F\u002F 将两边的数据融合在一起，最终提供出去渲染\n",[148,821,823,826,829,831,833,836,839,841,843,845,847],{"class":150,"line":822},23,[148,824,825],{"class":277},"    return",[148,827,828],{"class":173}," combineArticleData",[148,830,187],{"class":177},[148,832,647],{"class":239},[148,834,835],{"class":158}," ||",[148,837,838],{"class":158}," {},",[148,840,652],{"class":239},[148,842,607],{"class":158},[148,844,519],{"class":239},[148,846,266],{"class":177},[148,848,550],{"class":158},[148,850,852],{"class":150,"line":851},24,[148,853,854],{"class":158},"  },\n",[148,856,858,860],{"class":150,"line":857},25,[148,859,266],{"class":239},[148,861,550],{"class":158},[10,863,864],{},"url 唯一需要处理的，应该就是 sitemap 的生成了（如果你安装了 sitemap 模块的话）。在 nuxt.config.ts 中添加：",[17,866,868],{"className":142,"code":867,"language":144,"meta":26,"style":26},"sitemap: {\n    \u002F\u002F 排除掉不需要在 sitemap 出现的原始路径（例如带语言后缀的）\n    exclude: [\n      \"\u002Fzh-CN\u002F**\", \u002F\u002F 我默认 \u002Fblog\u002Fpost-a 就是中文，默认语言不加前缀\n      new RegExp(\".*\u002Findex.en\u002F?$\"),\n      new RegExp(\".*\u002Findex.zh-cn\u002F?$\"),\n    ],\n},\n",[24,869,870,879,884,894,909,930,949,956],{"__ignoreMap":26},[148,871,872,875,877],{"class":150,"line":151},[148,873,874],{"class":154},"sitemap",[148,876,159],{"class":158},[148,878,162],{"class":158},[148,880,881],{"class":150,"line":165},[148,882,883],{"class":256},"    \u002F\u002F 排除掉不需要在 sitemap 出现的原始路径（例如带语言后缀的）\n",[148,885,886,889,891],{"class":150,"line":181},[148,887,888],{"class":154},"    exclude",[148,890,159],{"class":158},[148,892,893],{"class":177}," [\n",[148,895,896,899,902,904,906],{"class":150,"line":193},[148,897,898],{"class":158},"      \"",[148,900,901],{"class":204},"\u002Fzh-CN\u002F**",[148,903,208],{"class":158},[148,905,607],{"class":158},[148,907,908],{"class":256}," \u002F\u002F 我默认 \u002Fblog\u002Fpost-a 就是中文，默认语言不加前缀\n",[148,910,911,914,917,919,921,924,926,928],{"class":150,"line":214},[148,912,913],{"class":158},"      new",[148,915,916],{"class":173}," RegExp",[148,918,187],{"class":177},[148,920,208],{"class":158},[148,922,923],{"class":204},".*\u002Findex.en\u002F?$",[148,925,208],{"class":158},[148,927,266],{"class":177},[148,929,211],{"class":158},[148,931,932,934,936,938,940,943,945,947],{"class":150,"line":231},[148,933,913],{"class":158},[148,935,916],{"class":173},[148,937,187],{"class":177},[148,939,208],{"class":158},[148,941,942],{"class":204},".*\u002Findex.zh-cn\u002F?$",[148,944,208],{"class":158},[148,946,266],{"class":177},[148,948,211],{"class":158},[148,950,951,954],{"class":150,"line":253},[148,952,953],{"class":177},"    ]",[148,955,211],{"class":158},[148,957,958],{"class":150,"line":260},[148,959,960],{"class":158},"},\n",[962,963],"hr",{},[10,965,966],{},"回过头看，这次重构最值得记下来的，不是那几行代码，而是那个“哦嚯”的瞬间 —— 当你在一条路上走不通的时候，不一定要硬刚，换个角度问自己：“一定要在这里解决吗？”往往答案就藏在别处。",[10,968,969],{},"这次把目录从按语言分改成按内容聚，文章管理顺手多了。如果你也在折腾 Nuxt Content + i18n，希望这篇能帮你少绕几个弯。",[971,972,973],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}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 .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 .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}",{"title":26,"searchDepth":165,"depth":165,"links":975},[976],{"id":132,"depth":165,"text":132},"md",{"artifactId":979,"lastmod":979,"backgroundImg":979,"ogImage":979,"listPreviewImg":-1},null,"\u002Fblog\u002Fnuxt-content-i18n-architecture-refactor\u002Findex.zh-cn",{"title":5,"description":12},{"loc":980},"blog\u002Fnuxt-content-i18n-architecture-refactor\u002Findex.zh-CN","PFsJ0VeUuRvAtaoEIrQVm3fdIU4jgts5Vi-Zj9HzKAA","2026-06-26","tech_and_career",[988,989,990,991,992],"troubleshooting","nuxt","i18n","architecture","refactor",[979,994],{"title":995,"path":996,"description":997,"date":998},"Cloudflare Pages 如何通过 Hyperdrive 连接到 Supabase","\u002Fblog\u002Fcloudflare-hyperdrive-to-supabase","起因还要从我正在做的第二个项目说起。","2026-06-23",1782739123196]