[{"data":1,"prerenderedAt":1911},["ShallowReactive",2],{"blog-es-japanese-pdf-in-go":3},{"id":4,"title":5,"author":6,"body":9,"date":1872,"description":1873,"draft":1874,"extension":1875,"howTo":1876,"image":1901,"meta":1902,"navigation":334,"path":1903,"seo":1904,"stem":1905,"tags":1906,"updated":1901,"__hash__":1910},"blogEs/es/blog/007.japanese-pdf-in-go.md","PDFs en japonés con Go: la guía definitiva de 2026",{"name":7,"url":8},"gpdf team","https://gpdf.dev",{"type":10,"value":11,"toc":1858},"minimark",[12,17,43,47,50,57,64,67,71,82,125,136,142,146,149,278,281,287,293,297,307,1281,1284,1340,1349,1353,1359,1362,1365,1414,1427,1430,1455,1471,1475,1478,1486,1489,1503,1509,1591,1602,1606,1609,1618,1628,1652,1666,1669,1673,1680,1687,1694,1708,1711,1715,1740,1746,1752,1766,1776,1785,1789,1792,1807,1821,1825,1854],[13,14,16],"h2",{"id":15},"tldr","TL;DR",[18,19,20,21,25,26,29,30,33,34,38,39,42],"p",{},"Si tu PDF en Go renderiza ",[22,23,24],"code",{},"こんにちは"," como cinco cuadros de tofu, el arreglo son dos líneas de configuración, no una reescritura. Carga un TTF japonés, pasa ",[22,27,28],{},"gpdf.WithFont"," a ",[22,31,32],{},"NewDocument",", escribe en japonés. ",[35,36,37],"strong",{},"gpdf hace el subconjunto de la tabla de glifos automáticamente",", así que la salida lleva solo los caracteres que usaste — unos 30 KB, no los 5 MB de la fuente completa. Esta guía es el mapa: por qué generar PDFs en japonés con Go ha sido extrañamente difícil, las cuatro opciones reales en 2026, un ejemplo completo y funcional, los detalles internos del subconjunto de fuentes, los casos límite de escrituras mezcladas, y ",[35,40,41],{},"lo que todavía no funciona",".",[13,44,46],{"id":45},"por-qué-existe-esta-guía","Por qué existe esta guía",[18,48,49],{},"Sacar un PDF con texto japonés desde Go debería ser trabajo de cinco minutos. Para muchos equipos es día y medio.",[18,51,52,53,56],{},"La historia típica: alguien mete ",[22,54,55],{},"AddUTF8Font",", el PDF muestra rectángulos vacíos — el infame 豆腐 — y un dev senior pasa la tarde averiguando si el problema es la ruta de la fuente, el flag de subconjunto, el CMap, el flag UTF-8 o el visor de PDF. Al anochecer hay un hilo de Slack titulado \"POR QUÉ 漢字 SIGUE ROTO\" y un PR con tres funciones auxiliares de las que todos ya se arrepienten.",[18,58,59,60,63],{},"La causa raíz no es ninguna de esas cosas. ",[35,61,62],{},"La biblioteca PDF más longeva de Go se diseñó en 2002 para PHP y Latin-1",", y casi todos los tutoriales japoneses escritos desde entonces han estado luchando contra ese legado. Esta guía es la versión 2026: qué funciona de verdad cuando empiezas desde cero, y qué sigue siendo genuinamente difícil.",[18,65,66],{},"Todo el código del post funciona en gpdf v1.x a fecha de 2026-04. Los números de benchmark son de un Apple M1 con Go 1.25.",[13,68,70],{"id":69},"el-problema-del-tofu-en-90-segundos","El problema del tofu en 90 segundos",[18,72,73,74,77,78,81],{},"A PDF no le importa Unicode. Le importan los ",[35,75,76],{},"IDs de glifo"," — índices enteros a la tabla de glifos embebida de la fuente. Cuando escribes ",[22,79,80],{},"\"こんにちは\""," a un PDF, alguien tiene que:",[83,84,85,96,102,108],"ol",{},[86,87,88,91,92,95],"li",{},[35,89,90],{},"Parsear el TTF"," y encontrar el ID de glifo para cada code point (vía la subtabla ",[22,93,94],{},"cmap"," de la fuente).",[86,97,98,101],{},[35,99,100],{},"Escribir un ToUnicode CMap"," para que el visor de PDF pueda mapear glifos a texto cuando el usuario copie o busque.",[86,103,104,107],{},[35,105,106],{},"Hacer el subconjunto"," de la fuente para que el PDF no cargue los 20,000 glifos de Noto Sans JP.",[86,109,110,113,114,117,118,117,121,124],{},[35,111,112],{},"Embeber el resultado"," con las tablas ",[22,115,116],{},"name",", ",[22,119,120],{},"OS/2",[22,122,123],{},"head"," y las referencias de codificación correctamente cosidas.",[18,126,127,128,131,132,135],{},"Si falta o falla alguno, el visor no encuentra glifo para el code point y pinta un tofu. Los linajes archivados ",[22,129,130],{},"jung-kurt/gofpdf"," y ",[22,133,134],{},"go-pdf/fpdf"," añadieron todo esto como parche sobre un modelo interno de fuente de un byte — la FPDF original de 2002 solo conocía Latin-1. Por eso la configuración es frágil, por eso la salida suele embeber la fuente completa en vez del subconjunto, y por eso los modos de fallo varían según SO y visor.",[18,137,138,139,141],{},"gpdf trata CJK como caso de primera clase. El subsetter TTF está en el paquete core. El ToUnicode CMap se escribe automáticamente. No hay baile de ",[22,140,55],{}," porque no hay legado de fuente de un byte al que adaptarse.",[13,143,145],{"id":144},"las-cuatro-opciones-reales-de-2026","Las cuatro opciones reales de 2026",[18,147,148],{},"Antes de escribir código: el terreno honesto. \"Apto para japonés\" significa \"renderiza cualquier texto japonés sin crashes ni tofu, dado un TTF correcto\".",[150,151,152,177],"table",{},[153,154,155],"thead",{},[156,157,158,162,165,168,171,174],"tr",{},[159,160,161],"th",{},"Opción",[159,163,164],{},"Licencia",[159,166,167],{},"Deps",[159,169,170],{},"Ruta CJK",[159,172,173],{},"Tamaño para 300 caracteres",[159,175,176],{},"Notas",[178,179,180,205,228,253],"tbody",{},[156,181,182,188,191,194,199,202],{},[183,184,185,187],"td",{},[22,186,134],{}," (archivado 2025)",[183,189,190],{},"MIT",[183,192,193],{},"stdlib",[183,195,196,197],{},"Parche ",[22,198,55],{},[183,200,201],{},"~5 MB (fuente completa)",[183,203,204],{},"Parche sobre core Latin-1. El subconjunto es opt-in e imperfecto.",[156,206,207,212,214,216,222,225],{},[183,208,209],{},[22,210,211],{},"signintech/gopdf",[183,213,190],{},[183,215,193],{},[183,217,218,221],{},[22,219,220],{},"AddTTFFont"," + manual",[183,223,224],{},"~3 MB típico",[183,226,227],{},"Bajo nivel. Tú escribes coordenadas. Subconjunto existe pero lo manejas tú.",[156,229,230,236,239,244,247,250],{},[183,231,232,235],{},[22,233,234],{},"chromedp"," + Chromium",[183,237,238],{},"MIT + Chrome",[183,240,241],{},[35,242,243],{},"binario Chromium",[183,245,246],{},"Nativo vía navegador",[183,248,249],{},"variable",[183,251,252],{},"HTML/CSS. Necesita fuentes instaladas en el contenedor. Imagen 500 MB+.",[156,254,255,260,262,267,270,275],{},[183,256,257],{},[22,258,259],{},"gpdf",[183,261,190],{},[183,263,264],{},[35,265,266],{},"solo stdlib",[183,268,269],{},"Nativo, subconjunto automático",[183,271,272],{},[35,273,274],{},"~30 KB",[183,276,277],{},"Go puro. API builder. ToUnicode CMap escrito por ti.",[18,279,280],{},"Dos cosas que vale la pena subrayar:",[18,282,283,286],{},[35,284,285],{},"La diferencia de 160× entre \"fuente completa embebida\" y \"subconjunto automático\" no es un redondeo."," Una factura de e-commerce para el mercado japonés con diez líneas necesita quizás 120 glifos japoneses únicos. Embeber la Noto Sans JP completa (5.1 MB) en cada factura significa que tu factura de almacenamiento lleva los mismos 5 MB de datos de glifos 10 millones de veces al final del año. El subconjunto lleva solo lo que usaste.",[18,288,289,292],{},[35,290,291],{},"\"chromedp funciona\" es cierto y también es la respuesta más cara."," Si tu equipo ya tiene una flota de Chrome headless para capturas, aprovecharla para PDFs está bien. Si no, levantar uno solo para imprimir 日本語 es mucha infraestructura para un problema de 40 líneas de Go.",[13,294,296],{"id":295},"la-ruta-más-corta-que-funciona","La ruta más corta que funciona",[18,298,299,300,303,304,42],{},"Empieza con esto. Es completo — copia, guarda como ",[22,301,302],{},"main.go",", pon dos TTF al lado, ",[22,305,306],{},"go run main.go",[308,309,314],"pre",{"className":310,"code":311,"language":312,"meta":313,"style":313},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","package main\n\nimport (\n    \"log\"\n    \"os\"\n\n    \"github.com/gpdf-dev/gpdf\"\n    \"github.com/gpdf-dev/gpdf/document\"\n    \"github.com/gpdf-dev/gpdf/template\"\n)\n\nfunc main() {\n    regular, err := os.ReadFile(\"NotoSansJP-Regular.ttf\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    bold, err := os.ReadFile(\"NotoSansJP-Bold.ttf\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    doc := gpdf.NewDocument(\n        gpdf.WithPageSize(document.A4),\n        gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n        gpdf.WithFont(\"NotoSansJP\", regular),\n        gpdf.WithFont(\"NotoSansJP-Bold\", bold),\n        gpdf.WithDefaultFont(\"NotoSansJP\", 11),\n    )\n\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"請求書\", template.FontFamily(\"NotoSansJP-Bold\"), template.FontSize(22))\n            c.Text(\"2026 年 4 月 16 日\")\n        })\n    })\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(7, func(c *template.ColBuilder) {\n            c.Text(\"株式会社 ABC 御中\", template.FontSize(13))\n            c.Text(\"〒 100-0001 東京都千代田区千代田 1-1\")\n        })\n        r.Col(5, func(c *template.ColBuilder) {\n            c.Text(\"合計 ¥ 128,000\", template.FontFamily(\"NotoSansJP-Bold\"), template.AlignRight())\n            c.Text(\"支払期限: 2026-05-31\", template.AlignRight())\n        })\n    })\n\n    data, err := doc.Generate()\n    if err != nil {\n        log.Fatal(err)\n    }\n    if err := os.WriteFile(\"invoice-ja.pdf\", data, 0o644); err != nil {\n        log.Fatal(err)\n    }\n}\n","go","",[22,315,316,329,336,346,358,368,373,383,393,403,409,414,430,468,484,502,508,537,550,565,570,575,593,617,654,680,705,730,736,741,760,794,831,887,907,913,919,944,976,1009,1029,1034,1066,1112,1140,1145,1150,1155,1176,1189,1204,1209,1255,1270,1275],{"__ignoreMap":313},[317,318,321,325],"span",{"class":319,"line":320},"line",1,[317,322,324],{"class":323},"sMK4o","package",[317,326,328],{"class":327},"sBMFI"," main\n",[317,330,332],{"class":319,"line":331},2,[317,333,335],{"emptyLinePlaceholder":334},true,"\n",[317,337,339,343],{"class":319,"line":338},3,[317,340,342],{"class":341},"s7zQu","import",[317,344,345],{"class":323}," (\n",[317,347,349,352,355],{"class":319,"line":348},4,[317,350,351],{"class":323},"    \"",[317,353,354],{"class":327},"log",[317,356,357],{"class":323},"\"\n",[317,359,361,363,366],{"class":319,"line":360},5,[317,362,351],{"class":323},[317,364,365],{"class":327},"os",[317,367,357],{"class":323},[317,369,371],{"class":319,"line":370},6,[317,372,335],{"emptyLinePlaceholder":334},[317,374,376,378,381],{"class":319,"line":375},7,[317,377,351],{"class":323},[317,379,380],{"class":327},"github.com/gpdf-dev/gpdf",[317,382,357],{"class":323},[317,384,386,388,391],{"class":319,"line":385},8,[317,387,351],{"class":323},[317,389,390],{"class":327},"github.com/gpdf-dev/gpdf/document",[317,392,357],{"class":323},[317,394,396,398,401],{"class":319,"line":395},9,[317,397,351],{"class":323},[317,399,400],{"class":327},"github.com/gpdf-dev/gpdf/template",[317,402,357],{"class":323},[317,404,406],{"class":319,"line":405},10,[317,407,408],{"class":323},")\n",[317,410,412],{"class":319,"line":411},11,[317,413,335],{"emptyLinePlaceholder":334},[317,415,417,420,424,427],{"class":319,"line":416},12,[317,418,419],{"class":323},"func",[317,421,423],{"class":422},"s2Zo4"," main",[317,425,426],{"class":323},"()",[317,428,429],{"class":323}," {\n",[317,431,433,437,440,443,446,449,451,454,457,460,464,466],{"class":319,"line":432},13,[317,434,436],{"class":435},"sTEyZ","    regular",[317,438,439],{"class":323},",",[317,441,442],{"class":435}," err ",[317,444,445],{"class":323},":=",[317,447,448],{"class":435}," os",[317,450,42],{"class":323},[317,452,453],{"class":422},"ReadFile",[317,455,456],{"class":323},"(",[317,458,459],{"class":323},"\"",[317,461,463],{"class":462},"sfazB","NotoSansJP-Regular.ttf",[317,465,459],{"class":323},[317,467,408],{"class":323},[317,469,471,474,476,479,482],{"class":319,"line":470},14,[317,472,473],{"class":341},"    if",[317,475,442],{"class":435},[317,477,478],{"class":323},"!=",[317,480,481],{"class":323}," nil",[317,483,429],{"class":323},[317,485,487,490,492,495,497,500],{"class":319,"line":486},15,[317,488,489],{"class":435},"        log",[317,491,42],{"class":323},[317,493,494],{"class":422},"Fatal",[317,496,456],{"class":323},[317,498,499],{"class":435},"err",[317,501,408],{"class":323},[317,503,505],{"class":319,"line":504},16,[317,506,507],{"class":323},"    }\n",[317,509,511,514,516,518,520,522,524,526,528,530,533,535],{"class":319,"line":510},17,[317,512,513],{"class":435},"    bold",[317,515,439],{"class":323},[317,517,442],{"class":435},[317,519,445],{"class":323},[317,521,448],{"class":435},[317,523,42],{"class":323},[317,525,453],{"class":422},[317,527,456],{"class":323},[317,529,459],{"class":323},[317,531,532],{"class":462},"NotoSansJP-Bold.ttf",[317,534,459],{"class":323},[317,536,408],{"class":323},[317,538,540,542,544,546,548],{"class":319,"line":539},18,[317,541,473],{"class":341},[317,543,442],{"class":435},[317,545,478],{"class":323},[317,547,481],{"class":323},[317,549,429],{"class":323},[317,551,553,555,557,559,561,563],{"class":319,"line":552},19,[317,554,489],{"class":435},[317,556,42],{"class":323},[317,558,494],{"class":422},[317,560,456],{"class":323},[317,562,499],{"class":435},[317,564,408],{"class":323},[317,566,568],{"class":319,"line":567},20,[317,569,507],{"class":323},[317,571,573],{"class":319,"line":572},21,[317,574,335],{"emptyLinePlaceholder":334},[317,576,578,581,583,586,588,590],{"class":319,"line":577},22,[317,579,580],{"class":435},"    doc ",[317,582,445],{"class":323},[317,584,585],{"class":435}," gpdf",[317,587,42],{"class":323},[317,589,32],{"class":422},[317,591,592],{"class":323},"(\n",[317,594,596,599,601,604,606,609,611,614],{"class":319,"line":595},23,[317,597,598],{"class":435},"        gpdf",[317,600,42],{"class":323},[317,602,603],{"class":422},"WithPageSize",[317,605,456],{"class":323},[317,607,608],{"class":435},"document",[317,610,42],{"class":323},[317,612,613],{"class":435},"A4",[317,615,616],{"class":323},"),\n",[317,618,620,622,624,627,629,631,633,636,638,640,642,645,647,651],{"class":319,"line":619},24,[317,621,598],{"class":435},[317,623,42],{"class":323},[317,625,626],{"class":422},"WithMargins",[317,628,456],{"class":323},[317,630,608],{"class":435},[317,632,42],{"class":323},[317,634,635],{"class":422},"UniformEdges",[317,637,456],{"class":323},[317,639,608],{"class":435},[317,641,42],{"class":323},[317,643,644],{"class":422},"Mm",[317,646,456],{"class":323},[317,648,650],{"class":649},"sbssI","20",[317,652,653],{"class":323},"))),\n",[317,655,657,659,661,664,666,668,671,673,675,678],{"class":319,"line":656},25,[317,658,598],{"class":435},[317,660,42],{"class":323},[317,662,663],{"class":422},"WithFont",[317,665,456],{"class":323},[317,667,459],{"class":323},[317,669,670],{"class":462},"NotoSansJP",[317,672,459],{"class":323},[317,674,439],{"class":323},[317,676,677],{"class":435}," regular",[317,679,616],{"class":323},[317,681,683,685,687,689,691,693,696,698,700,703],{"class":319,"line":682},26,[317,684,598],{"class":435},[317,686,42],{"class":323},[317,688,663],{"class":422},[317,690,456],{"class":323},[317,692,459],{"class":323},[317,694,695],{"class":462},"NotoSansJP-Bold",[317,697,459],{"class":323},[317,699,439],{"class":323},[317,701,702],{"class":435}," bold",[317,704,616],{"class":323},[317,706,708,710,712,715,717,719,721,723,725,728],{"class":319,"line":707},27,[317,709,598],{"class":435},[317,711,42],{"class":323},[317,713,714],{"class":422},"WithDefaultFont",[317,716,456],{"class":323},[317,718,459],{"class":323},[317,720,670],{"class":462},[317,722,459],{"class":323},[317,724,439],{"class":323},[317,726,727],{"class":649}," 11",[317,729,616],{"class":323},[317,731,733],{"class":319,"line":732},28,[317,734,735],{"class":323},"    )\n",[317,737,739],{"class":319,"line":738},29,[317,740,335],{"emptyLinePlaceholder":334},[317,742,744,747,749,752,754,757],{"class":319,"line":743},30,[317,745,746],{"class":435},"    page ",[317,748,445],{"class":323},[317,750,751],{"class":435}," doc",[317,753,42],{"class":323},[317,755,756],{"class":422},"AddPage",[317,758,759],{"class":323},"()\n",[317,761,763,766,768,771,774,778,781,784,786,789,792],{"class":319,"line":762},31,[317,764,765],{"class":435},"    page",[317,767,42],{"class":323},[317,769,770],{"class":422},"AutoRow",[317,772,773],{"class":323},"(func(",[317,775,777],{"class":776},"sHdIc","r",[317,779,780],{"class":323}," *",[317,782,783],{"class":327},"template",[317,785,42],{"class":323},[317,787,788],{"class":327},"RowBuilder",[317,790,791],{"class":323},")",[317,793,429],{"class":323},[317,795,797,800,802,805,807,810,812,815,818,820,822,824,827,829],{"class":319,"line":796},32,[317,798,799],{"class":435},"        r",[317,801,42],{"class":323},[317,803,804],{"class":422},"Col",[317,806,456],{"class":323},[317,808,809],{"class":649},"12",[317,811,439],{"class":323},[317,813,814],{"class":323}," func(",[317,816,817],{"class":776},"c",[317,819,780],{"class":323},[317,821,783],{"class":327},[317,823,42],{"class":323},[317,825,826],{"class":327},"ColBuilder",[317,828,791],{"class":323},[317,830,429],{"class":323},[317,832,834,837,839,842,844,846,849,851,853,856,858,861,863,865,867,869,872,874,876,879,881,884],{"class":319,"line":833},33,[317,835,836],{"class":435},"            c",[317,838,42],{"class":323},[317,840,841],{"class":422},"Text",[317,843,456],{"class":323},[317,845,459],{"class":323},[317,847,848],{"class":462},"請求書",[317,850,459],{"class":323},[317,852,439],{"class":323},[317,854,855],{"class":435}," template",[317,857,42],{"class":323},[317,859,860],{"class":422},"FontFamily",[317,862,456],{"class":323},[317,864,459],{"class":323},[317,866,695],{"class":462},[317,868,459],{"class":323},[317,870,871],{"class":323},"),",[317,873,855],{"class":435},[317,875,42],{"class":323},[317,877,878],{"class":422},"FontSize",[317,880,456],{"class":323},[317,882,883],{"class":649},"22",[317,885,886],{"class":323},"))\n",[317,888,890,892,894,896,898,900,903,905],{"class":319,"line":889},34,[317,891,836],{"class":435},[317,893,42],{"class":323},[317,895,841],{"class":422},[317,897,456],{"class":323},[317,899,459],{"class":323},[317,901,902],{"class":462},"2026 年 4 月 16 日",[317,904,459],{"class":323},[317,906,408],{"class":323},[317,908,910],{"class":319,"line":909},35,[317,911,912],{"class":323},"        })\n",[317,914,916],{"class":319,"line":915},36,[317,917,918],{"class":323},"    })\n",[317,920,922,924,926,928,930,932,934,936,938,940,942],{"class":319,"line":921},37,[317,923,765],{"class":435},[317,925,42],{"class":323},[317,927,770],{"class":422},[317,929,773],{"class":323},[317,931,777],{"class":776},[317,933,780],{"class":323},[317,935,783],{"class":327},[317,937,42],{"class":323},[317,939,788],{"class":327},[317,941,791],{"class":323},[317,943,429],{"class":323},[317,945,947,949,951,953,955,958,960,962,964,966,968,970,972,974],{"class":319,"line":946},38,[317,948,799],{"class":435},[317,950,42],{"class":323},[317,952,804],{"class":422},[317,954,456],{"class":323},[317,956,957],{"class":649},"7",[317,959,439],{"class":323},[317,961,814],{"class":323},[317,963,817],{"class":776},[317,965,780],{"class":323},[317,967,783],{"class":327},[317,969,42],{"class":323},[317,971,826],{"class":327},[317,973,791],{"class":323},[317,975,429],{"class":323},[317,977,979,981,983,985,987,989,992,994,996,998,1000,1002,1004,1007],{"class":319,"line":978},39,[317,980,836],{"class":435},[317,982,42],{"class":323},[317,984,841],{"class":422},[317,986,456],{"class":323},[317,988,459],{"class":323},[317,990,991],{"class":462},"株式会社 ABC 御中",[317,993,459],{"class":323},[317,995,439],{"class":323},[317,997,855],{"class":435},[317,999,42],{"class":323},[317,1001,878],{"class":422},[317,1003,456],{"class":323},[317,1005,1006],{"class":649},"13",[317,1008,886],{"class":323},[317,1010,1012,1014,1016,1018,1020,1022,1025,1027],{"class":319,"line":1011},40,[317,1013,836],{"class":435},[317,1015,42],{"class":323},[317,1017,841],{"class":422},[317,1019,456],{"class":323},[317,1021,459],{"class":323},[317,1023,1024],{"class":462},"〒 100-0001 東京都千代田区千代田 1-1",[317,1026,459],{"class":323},[317,1028,408],{"class":323},[317,1030,1032],{"class":319,"line":1031},41,[317,1033,912],{"class":323},[317,1035,1037,1039,1041,1043,1045,1048,1050,1052,1054,1056,1058,1060,1062,1064],{"class":319,"line":1036},42,[317,1038,799],{"class":435},[317,1040,42],{"class":323},[317,1042,804],{"class":422},[317,1044,456],{"class":323},[317,1046,1047],{"class":649},"5",[317,1049,439],{"class":323},[317,1051,814],{"class":323},[317,1053,817],{"class":776},[317,1055,780],{"class":323},[317,1057,783],{"class":327},[317,1059,42],{"class":323},[317,1061,826],{"class":327},[317,1063,791],{"class":323},[317,1065,429],{"class":323},[317,1067,1069,1071,1073,1075,1077,1079,1082,1084,1086,1088,1090,1092,1094,1096,1098,1100,1102,1104,1106,1109],{"class":319,"line":1068},43,[317,1070,836],{"class":435},[317,1072,42],{"class":323},[317,1074,841],{"class":422},[317,1076,456],{"class":323},[317,1078,459],{"class":323},[317,1080,1081],{"class":462},"合計 ¥ 128,000",[317,1083,459],{"class":323},[317,1085,439],{"class":323},[317,1087,855],{"class":435},[317,1089,42],{"class":323},[317,1091,860],{"class":422},[317,1093,456],{"class":323},[317,1095,459],{"class":323},[317,1097,695],{"class":462},[317,1099,459],{"class":323},[317,1101,871],{"class":323},[317,1103,855],{"class":435},[317,1105,42],{"class":323},[317,1107,1108],{"class":422},"AlignRight",[317,1110,1111],{"class":323},"())\n",[317,1113,1115,1117,1119,1121,1123,1125,1128,1130,1132,1134,1136,1138],{"class":319,"line":1114},44,[317,1116,836],{"class":435},[317,1118,42],{"class":323},[317,1120,841],{"class":422},[317,1122,456],{"class":323},[317,1124,459],{"class":323},[317,1126,1127],{"class":462},"支払期限: 2026-05-31",[317,1129,459],{"class":323},[317,1131,439],{"class":323},[317,1133,855],{"class":435},[317,1135,42],{"class":323},[317,1137,1108],{"class":422},[317,1139,1111],{"class":323},[317,1141,1143],{"class":319,"line":1142},45,[317,1144,912],{"class":323},[317,1146,1148],{"class":319,"line":1147},46,[317,1149,918],{"class":323},[317,1151,1153],{"class":319,"line":1152},47,[317,1154,335],{"emptyLinePlaceholder":334},[317,1156,1158,1161,1163,1165,1167,1169,1171,1174],{"class":319,"line":1157},48,[317,1159,1160],{"class":435},"    data",[317,1162,439],{"class":323},[317,1164,442],{"class":435},[317,1166,445],{"class":323},[317,1168,751],{"class":435},[317,1170,42],{"class":323},[317,1172,1173],{"class":422},"Generate",[317,1175,759],{"class":323},[317,1177,1179,1181,1183,1185,1187],{"class":319,"line":1178},49,[317,1180,473],{"class":341},[317,1182,442],{"class":435},[317,1184,478],{"class":323},[317,1186,481],{"class":323},[317,1188,429],{"class":323},[317,1190,1192,1194,1196,1198,1200,1202],{"class":319,"line":1191},50,[317,1193,489],{"class":435},[317,1195,42],{"class":323},[317,1197,494],{"class":422},[317,1199,456],{"class":323},[317,1201,499],{"class":435},[317,1203,408],{"class":323},[317,1205,1207],{"class":319,"line":1206},51,[317,1208,507],{"class":323},[317,1210,1212,1214,1216,1218,1220,1222,1225,1227,1229,1232,1234,1236,1239,1241,1244,1247,1249,1251,1253],{"class":319,"line":1211},52,[317,1213,473],{"class":341},[317,1215,442],{"class":435},[317,1217,445],{"class":323},[317,1219,448],{"class":435},[317,1221,42],{"class":323},[317,1223,1224],{"class":422},"WriteFile",[317,1226,456],{"class":323},[317,1228,459],{"class":323},[317,1230,1231],{"class":462},"invoice-ja.pdf",[317,1233,459],{"class":323},[317,1235,439],{"class":323},[317,1237,1238],{"class":435}," data",[317,1240,439],{"class":323},[317,1242,1243],{"class":649}," 0o644",[317,1245,1246],{"class":323},");",[317,1248,442],{"class":435},[317,1250,478],{"class":323},[317,1252,481],{"class":323},[317,1254,429],{"class":323},[317,1256,1258,1260,1262,1264,1266,1268],{"class":319,"line":1257},53,[317,1259,489],{"class":435},[317,1261,42],{"class":323},[317,1263,494],{"class":422},[317,1265,456],{"class":323},[317,1267,499],{"class":435},[317,1269,408],{"class":323},[317,1271,1273],{"class":319,"line":1272},54,[317,1274,507],{"class":323},[317,1276,1278],{"class":319,"line":1277},55,[317,1279,1280],{"class":323},"}\n",[18,1282,1283],{},"Detalles que vale la pena notar sin narrar cada uno:",[1285,1286,1287,1305,1314,1331],"ul",{},[86,1288,1289,1297,1298,1300,1301,1304],{},[35,1290,1291,1292,1294,1295,42],{},"Sin ",[22,1293,55],{},", sin flag UTF-8, sin argumento de ruta de fuente a ",[22,1296,841],{}," ",[22,1299,28],{}," registra una familia; ",[22,1302,1303],{},"c.Text"," solo escribe Unicode. El cableado queda dentro.",[86,1306,1307,1310,1311,1313],{},[35,1308,1309],{},"La negrita es una familia aparte, no un flag."," Esto encaja con cómo se distribuyen los TTF (Noto Sans JP Regular y Noto Sans JP Bold son archivos distintos con tablas ",[22,1312,116],{}," diferentes). Las variantes Gothic/Mincho, o Source Han Sans JP Normal/Heavy, siguen el mismo patrón.",[86,1315,1316,1297,1319,131,1322,1325,1326,42],{},[35,1317,1318],{},"El layout es grid, no cursor.",[22,1320,1321],{},"r.Col(7, ...)",[22,1323,1324],{},"r.Col(5, ...)"," suman 12. Los anchos son declarativos; no calculas coordenadas x. Más en ",[1327,1328,1330],"a",{"href":1329},"/es/blog/12-column-grid","Cómo funciona la grid de 12 columnas en gpdf",[86,1332,1333,1339],{},[35,1334,1335,1338],{},[22,1336,1337],{},"AlignRight()"," es independiente del locale."," El \"¥ 128,000\" japonés se alinea a la derecha igual que un \"$1,280.00\". El contenido del texto no cambia el código de layout.",[18,1341,1342,1343,1345,1346,1348],{},"Abre el ",[22,1344,1231],{}," resultante en cualquier visor. Selecciona \"株式会社 ABC 御中\". Pega en un editor de texto. Obtienes ",[22,1347,991],{},", no un revoltijo. Eso es el ToUnicode CMap trabajando; gpdf lo escribe por defecto.",[13,1350,1352],{"id":1351},"subconjuntos-de-fuente-la-bomba-de-tamaño-oculta","Subconjuntos de fuente: la bomba de tamaño oculta",[18,1354,1355,1356,42],{},"Esta es la propiedad más importante de CJK-en-PDF que los tutoriales se saltan: ",[35,1357,1358],{},"embebido por subconjunto",[18,1360,1361],{},"Una fuente TTF es una colección de contornos de glifo más tablas de metadata. Noto Sans JP Regular trae unos 17,500 glifos y pesa 5.1 MB. Una factura típica usa entre 60 y 200 caracteres japoneses únicos. Embeber la fuente completa en cada documento es un desperdicio de un orden de magnitud.",[18,1363,1364],{},"El embebido por subconjunto guarda solo los glifos que usaste. gpdf lo hace automáticamente. Puedes verlo corriendo el ejemplo de arriba:",[308,1366,1370],{"className":1367,"code":1368,"language":1369,"meta":313,"style":313},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","$ ls -l invoice-ja.pdf\n-rw-r--r--  1 dev  staff  34892 Apr 16 10:12 invoice-ja.pdf\n","bash",[22,1371,1372,1386],{"__ignoreMap":313},[317,1373,1374,1377,1380,1383],{"class":319,"line":320},[317,1375,1376],{"class":327},"$",[317,1378,1379],{"class":462}," ls",[317,1381,1382],{"class":462}," -l",[317,1384,1385],{"class":462}," invoice-ja.pdf\n",[317,1387,1388,1391,1394,1397,1400,1403,1406,1409,1412],{"class":319,"line":331},[317,1389,1390],{"class":327},"-rw-r--r--",[317,1392,1393],{"class":649},"  1",[317,1395,1396],{"class":462}," dev",[317,1398,1399],{"class":462},"  staff",[317,1401,1402],{"class":649},"  34892",[317,1404,1405],{"class":462}," Apr",[317,1407,1408],{"class":649}," 16",[317,1410,1411],{"class":462}," 10:12",[317,1413,1385],{"class":462},[18,1415,1416,1417,131,1419,1422,1423,1426],{},"34 KB. Como comparación, el mismo documento generado con ",[22,1418,134],{},[22,1420,1421],{},"AddUTF8Font(\"NotoSansJP\", \"NotoSansJP-Regular.ttf\", true)"," — donde el tercer argumento es el flag UTF-8 — es ",[35,1424,1425],{},"4.9 MB",". Mismo input, mismo texto de salida, archivo 143× más grande. La razón es que la ruta de código de fpdf embebe la tabla completa de la fuente en vez de hacer el subconjunto al emitir.",[18,1428,1429],{},"Algunas consecuencias que vale nombrar:",[1285,1431,1432,1443,1449],{},[86,1433,1434,1435,1438,1439,1442],{},"A ",[35,1436,1437],{},"10 facturas por segundo"," (escala SaaS normal), la diferencia por subconjunto es la diferencia entre ",[35,1440,1441],{},"0.3 MB/s y 43 MB/s"," de bytes PDF salientes. Tu balanceador tiene opinión al respecto.",[86,1444,1445,1448],{},[35,1446,1447],{},"Las facturas de cold storage"," escalan linealmente con el tamaño del PDF. Cinco millones de facturas archivadas a 5 MB cada una son 25 TB. A 30 KB, son 150 GB. El pricing de object storage hace que esto sea una línea mensual de cuatro cifras frente a dos.",[86,1450,1451,1454],{},[35,1452,1453],{},"La entrega por email"," tiene límites de adjunto de 10–25 MB según proveedor. Una factura japonesa de 5 MB más cualquier otro adjunto más la codificación MIME empieza a chocar con ese techo.",[18,1456,1457,1458,117,1461,117,1464,131,1467,1470],{},"gpdf hace el subconjunto en tiempo de render. No hay flag para activarlo. Puedes ver qué glifos acabaron en la salida ejecutando la herramienta de verificación de gpdf localmente, pero la versión corta es: si usaste ",[22,1459,1460],{},"株",[22,1462,1463],{},"式",[22,1465,1466],{},"会",[22,1468,1469],{},"社",", esos cuatro glifos están en la salida y los otros 17,496 no.",[13,1472,1474],{"id":1473},"escrituras-mezcladas-kanji-kana-ascii-en-una-línea","Escrituras mezcladas: kanji + kana + ASCII en una línea",[18,1476,1477],{},"El texto japonés rara vez es solo japonés. Una línea real en un documento japonés luce así:",[308,1479,1484],{"className":1480,"code":1482,"language":1483},[1481],"language-text","API の P95 レイテンシは 50 ms 未満です。\n","text",[22,1485,1482],{"__ignoreMap":313},[18,1487,1488],{},"Cinco escrituras: romaji (ASCII Latin), katakana, hiragana, kanji (Han) y numerales. Una implementación ingenua elige la fuente equivocada para las partes ASCII y acabas con un \"API\" monoespaciado junto al japonés proporcional, lo cual se ve horrible.",[18,1490,1491,1492,1495,1496,131,1499,1502],{},"El comportamiento por defecto de gpdf es ",[35,1493,1494],{},"renderizar cada code point con la familia registrada",". Si Noto Sans JP es tu predeterminada, ",[22,1497,1498],{},"API",[22,1500,1501],{},"50 ms"," se dibujan con los glifos Latin de Noto Sans JP, que Noto provee (la mayoría de superfamilias japonesas los dan). El resultado parece una sola tipografía, porque lo es.",[18,1504,1505,1506,1508],{},"Si quieres mezclar familias deliberadamente — por ejemplo, una sans condensed para ASCII y Noto Sans JP para japonés — registra ambas y sobrescribe por llamada a ",[22,1507,1303],{},":",[308,1510,1512],{"className":310,"code":1511,"language":312,"meta":313,"style":313},"c.Text(\"API の P95 レイテンシは 50 ms 未満です。\",\n    template.FontFamily(\"NotoSansJP\"))\nc.Text(\"API latency (P95) is under 50 ms.\",\n    template.FontFamily(\"InterVariable\"))\n",[22,1513,1514,1534,1553,1572],{"__ignoreMap":313},[317,1515,1516,1518,1520,1522,1524,1526,1529,1531],{"class":319,"line":320},[317,1517,817],{"class":435},[317,1519,42],{"class":323},[317,1521,841],{"class":422},[317,1523,456],{"class":323},[317,1525,459],{"class":323},[317,1527,1528],{"class":462},"API の P95 レイテンシは 50 ms 未満です。",[317,1530,459],{"class":323},[317,1532,1533],{"class":323},",\n",[317,1535,1536,1539,1541,1543,1545,1547,1549,1551],{"class":319,"line":331},[317,1537,1538],{"class":435},"    template",[317,1540,42],{"class":323},[317,1542,860],{"class":422},[317,1544,456],{"class":323},[317,1546,459],{"class":323},[317,1548,670],{"class":462},[317,1550,459],{"class":323},[317,1552,886],{"class":323},[317,1554,1555,1557,1559,1561,1563,1565,1568,1570],{"class":319,"line":338},[317,1556,817],{"class":435},[317,1558,42],{"class":323},[317,1560,841],{"class":422},[317,1562,456],{"class":323},[317,1564,459],{"class":323},[317,1566,1567],{"class":462},"API latency (P95) is under 50 ms.",[317,1569,459],{"class":323},[317,1571,1533],{"class":323},[317,1573,1574,1576,1578,1580,1582,1584,1587,1589],{"class":319,"line":348},[317,1575,1538],{"class":435},[317,1577,42],{"class":323},[317,1579,860],{"class":422},[317,1581,456],{"class":323},[317,1583,459],{"class":323},[317,1585,1586],{"class":462},"InterVariable",[317,1588,459],{"class":323},[317,1590,886],{"class":323},[18,1592,1593,1594,1596,1597,1601],{},"Dos ",[22,1595,1303],{},", dos familias, cero lógica de detección de escritura en tu código. Si necesitas mezcla intra-línea (Inter ASCII + Noto japonés en la ",[1598,1599,1600],"em",{},"misma"," frase), eso viene en gpdf v1.2; hoy el workaround es partir en las fronteras de escritura a mano y maquetar con una fila horizontal de columnas.",[13,1603,1605],{"id":1604},"lo-que-todavía-duele","Lo que todavía duele",[18,1607,1608],{},"La historia del PDF japonés en Go está resuelta al 95%. Este es el 5%.",[18,1610,1611,1614,1615,42],{},[35,1612,1613],{},"La escritura vertical (縦書き) todavía no está."," gpdf renderiza solo texto horizontal en v1.x. La maquetación japonesa tradicional — columnas de derecha a izquierda, caracteres de arriba abajo, con la rotación apropiada de glifos y reposicionamiento de puntuación — es un cambio profundo del motor de layout, no un ajuste de renderizado. El issue abierto tiene una propuesta de diseño; aterrizará cuando aterrice. Por ahora, si necesitas 縦書き para libros o correspondencia formal, genera con una herramienta que lo soporte (Word, InDesign o un pipeline pandoc + LuaLaTeX) y embebe el PDF resultante con ",[22,1616,1617],{},"gpdf.Merge",[18,1619,1620,1623,1624,1627],{},[35,1621,1622],{},"Las anotaciones ruby (振り仮名) solo tienen workaround."," No hay primitiva ",[22,1625,1626],{},"c.Ruby(\"漢字\", \"かんじ\")",". Si necesitas ruby para contenido infantil o libros de texto de idiomas, el workaround es una columna de dos filas: texto kana pequeño arriba, kanji normal abajo, alineados. Funciona, pero es manual y el kerning fino en las fronteras de furigana requiere cuidado.",[18,1629,1630,1633,1634,117,1637,117,1640,1643,1644,1646,1647,1651],{},[35,1631,1632],{},"Fallbacks complejos entre múltiples fuentes CJK."," Si un usuario envía texto que mezcla kanji japonés con caracteres solo chinos (las formas difieren — ",[22,1635,1636],{},"直",[22,1638,1639],{},"骨",[22,1641,1642],{},"角"," se renderizan sutilmente distintos en CN vs JP), necesitas partir manualmente y usar dos familias. gpdf no hace auto-fallback entre familias dentro de una sola llamada a ",[22,1645,1303],{},". En la práctica muy pocos documentos lo necesitan; si el tuyo sí, ver ",[1327,1648,1650],{"href":1649},"/es/blog/","PDFs multi-idioma: mezclando JP/CN/KR/EN"," (B-070 pendiente).",[18,1653,1654,1657,1658,1661,1662,1665],{},[35,1655,1656],{},"Cumplimiento estricto PDF/A-2b con japonés."," gpdf produce salida PDF/A vía ",[22,1659,1660],{},"gpdf.WithPDFA",", pero los requisitos estrictos sobre metadata de glifos embebidos, el span ",[22,1663,1664],{},"ActualText"," en cada run CJK, y los árboles de estructura etiquetados aún se están afinando para el caso CJK. Si exportas para archivado de largo plazo bajo la 電子帳簿保存法 japonesa, valida con una herramienta de terceros (veraPDF es gratis) antes de hacer commit.",[18,1667,1668],{},"Ninguno es bloqueante para los casos comunes: facturas, reportes, estados, recibos, certificados. Vale la pena nombrarlos porque alguien que lee esto está a punto de chocar con uno en producción, y \"está en el roadmap\" es menos útil que \"aquí está el workaround\".",[13,1670,1672],{"id":1671},"una-palabra-sobre-cumplimiento","Una palabra sobre cumplimiento",[18,1674,1675,1676,1679],{},"Un pedazo de contexto de ecosistema que suele callarse: ",[35,1677,1678],{},"generar PDFs japoneses en 2026 no es solo un problema tipográfico."," Dos cambios regulatorios lo empujan hacia la conversación de cumplimiento.",[18,1681,1682,1683,1686],{},"El ",[35,1684,1685],{},"régimen 適格請求書 (factura cualificada)"," bajo la reforma del impuesto al consumo exige que las facturas incluyan campos específicos (número de negocio registrado, tasa impositiva aplicable, desglose) y que se retengan de forma a prueba de manipulaciones. Los PDF son el formato por defecto, y \"a prueba de manipulaciones\" mapea a las firmas digitales PDF — PAdES-B-LT en el caso estricto.",[18,1688,1689,1690,1693],{},"La ",[35,1691,1692],{},"電子帳簿保存法 (ley de almacenamiento electrónico de libros)",", revisada en 2024, extendió los mandatos de retención para incluir facturas almacenadas en forma electrónica. Los PDFs archivados deben cumplir ciertos requisitos de integridad. PDF/A-2b o PDF/A-3b son el formato objetivo de facto.",[18,1695,1696,1697,1700,1701,1704,1705,1707],{},"Ambos requisitos se apoyan en ",[35,1698,1699],{},"características PDF nativas"," — firmas, validación a largo plazo, metadata PDF/A embebida. HTML-a-PDF vía navegador headless no cumple limpiamente ninguno: la salida PDF de Chromium no es PDF/A-compliant y no puede embeber firmas digitales en un solo paso. Un stack Go nativo (gpdf + ",[22,1702,1703],{},"gpdf/signature"," para PAdES + ",[22,1706,1660],{},") hace toda la cadena en un pipeline sin salir del proceso.",[18,1709,1710],{},"Esto es un aviso para futuros posts más que una inmersión profunda — firma y PDF/A merecen cada uno su propio artículo hero (son B-067 y B-068 en el backlog). Pero si hoy eliges un stack PDF japonés y el cumplimiento está en tu radar, elige un stack que pueda hacer firmas y PDF/A de forma nativa. El impuesto de migración de \"funciona hoy\" a \"pasa la auditoría\" es real.",[13,1712,1714],{"id":1713},"faq","FAQ",[18,1716,1717,1720,1721,1724,1725,1728,1729,1732,1733,1736,1737,42],{},[35,1718,1719],{},"¿Hace falta instalar fuentes en el servidor o en el contenedor?","\nNo. gpdf lee bytes TTF; no pasa por la caché de fuentes del sistema. ",[22,1722,1723],{},"os.ReadFile(\"NotoSansJP-Regular.ttf\")"," o ",[22,1726,1727],{},"//go:embed NotoSansJP-Regular.ttf"," funciona idénticamente en macOS, Linux y Windows, dentro de un contenedor distroless y en AWS Lambda. Sin ",[22,1730,1731],{},"fontconfig",", sin ",[22,1734,1735],{},"fc-cache -fv",". Esa es una de las razones por las que gpdf funciona en imágenes ",[22,1738,1739],{},"FROM scratch",[18,1741,1742,1745],{},[35,1743,1744],{},"Noto Sans JP vs Source Han Sans JP — ¿importa?","\nSon la misma familia de fuente bajo dos nombres. Adobe publica Source Han Sans JP; Google la reempaqueta como Noto Sans JP. La cobertura de glifos es idéntica. Elige la distribución de licencia que pase tu revisión legal; ambas son SIL Open Font License. Para documentación neutra usamos Noto Sans JP por defecto porque los nombres de archivo son más fáciles de recordar.",[18,1747,1748,1751],{},[35,1749,1750],{},"¿Qué hay de 游ゴシック (Yu Gothic) o Hiragino?","\nSon fuentes propietarias incluidas con el SO. Puedes usarlas si tu target de deploy las licencia (Windows Server incluye Yu Gothic; macOS incluye Hiragino), pero necesitarás obtener el TTF y confirmar los términos de redistribución para tu build de contenedor. Para deploys abiertos, quédate con Noto Sans JP o IPAex Gothic (ambas de redistribución libre).",[18,1753,1754,1761,1762,1765],{},[35,1755,1756,1757,1760],{},"El PDF renderiza pero ",[22,1758,1759],{},"Ctrl+F"," no encuentra nada. ¿Por qué?","\nCasi siempre un problema de ToUnicode CMap. gpdf lo escribe automáticamente, así que si lo ves con gpdf, abre un issue con el nombre del visor. Si lo ves con gofpdf, el arreglo es activar el flag UTF-8 ",[1598,1763,1764],{},"y"," asegurarse de que el visor soporta fuentes CID — las versiones viejas de Preview.app en macOS tienen issues conocidos. Testea con Adobe Reader o Chrome como control.",[18,1767,1768,1771,1772,1775],{},[35,1769,1770],{},"¿Cómo añado un carácter JIS X 0213 que no está en la fuente?","\nNo puedes — no hay glifo que dibujar. La respuesta práctica es \"usa una fuente que cubra JIS X 0213\". Noto Sans JP cubre el BMP completo más JIS X 0213 Nivel 1. Para variantes históricas raras, Hanazono Mincho (花園明朝) es el fallback de último recurso. Si un code point no está en ninguna fuente, gpdf emite el carácter de reemplazo Unicode (U+FFFD) en vez de un tofu silencioso — así verás ",[22,1773,1774],{},"�"," en la salida y sabrás que hay que investigar.",[18,1777,1778,1781,1782,1784],{},[35,1779,1780],{},"¿Hay coste de performance entre CJK y ASCII?","\nPequeño. El benchmark de gpdf para \"factura CJK compleja\" es 133 µs por documento en Apple M1, vs 108 µs para una tabla ASCII 4×10. Eso es ~23% de overhead, casi todo por el trabajo más grande de lookup de glifos y subconjunto. Como referencia, ",[22,1783,134],{}," en el mismo benchmark CJK es 254 µs, y Maroto v2 es 10.4 ms. El renderizado japonés no es el cuello de botella en tu servicio.",[13,1786,1788],{"id":1787},"prueba-gpdf","Prueba gpdf",[18,1790,1791],{},"gpdf es una biblioteca Go para generar PDFs. MIT, cero dependencias externas, CJK nativo.",[308,1793,1795],{"className":1367,"code":1794,"language":1369,"meta":313,"style":313},"go get github.com/gpdf-dev/gpdf\n",[22,1796,1797],{"__ignoreMap":313},[317,1798,1799,1801,1804],{"class":319,"line":320},[317,1800,312],{"class":327},[317,1802,1803],{"class":462}," get",[317,1805,1806],{"class":462}," github.com/gpdf-dev/gpdf\n",[18,1808,1809,1815,1816],{},[1327,1810,1814],{"href":1811,"rel":1812},"https://github.com/gpdf-dev/gpdf",[1813],"nofollow","⭐ Star en GitHub"," · ",[1327,1817,1820],{"href":1818,"rel":1819},"https://gpdf.dev/es/docs/quickstart",[1813],"Lee la documentación",[13,1822,1824],{"id":1823},"lecturas-siguientes","Lecturas siguientes",[1285,1826,1827,1834,1841,1847],{},[86,1828,1829,1833],{},[1327,1830,1832],{"href":1831},"/es/blog/embed-japanese-font","¿Cómo embebo una fuente japonesa en gpdf?"," — la receta de tres líneas sin el contexto",[86,1835,1836,1840],{},[1327,1837,1839],{"href":1838},"/es/blog/noto-sans-jp-with-gpdf","¿Cómo uso Noto Sans JP con gpdf?"," — configuración de pesos Regular / Bold / Medium",[86,1842,1843,1846],{},[1327,1844,1845],{"href":1329},"¿Cómo funciona la grid de 12 columnas en gpdf?"," — el idioma de layout que reemplaza empujar el cursor",[86,1848,1849,1853],{},[1327,1850,1852],{"href":1851},"/es/blog/go-pdf-fpdf-archived","go-pdf/fpdf también está archivado. El stack Go PDF moderno."," — el panorama más amplio de 2026",[1855,1856,1857],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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 .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 .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--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);}",{"title":313,"searchDepth":331,"depth":331,"links":1859},[1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871],{"id":15,"depth":331,"text":16},{"id":45,"depth":331,"text":46},{"id":69,"depth":331,"text":70},{"id":144,"depth":331,"text":145},{"id":295,"depth":331,"text":296},{"id":1351,"depth":331,"text":1352},{"id":1473,"depth":331,"text":1474},{"id":1604,"depth":331,"text":1605},{"id":1671,"depth":331,"text":1672},{"id":1713,"depth":331,"text":1714},{"id":1787,"depth":331,"text":1788},{"id":1823,"depth":331,"text":1824},"2026-04-16","Cómo generar PDFs en japonés con Go en 2026 — fuentes, subconjuntos TrueType, kanji/kana/ASCII mezclados, y por qué no hacen falta CGO ni Chromium.",false,"md",{"name":1877,"totalTime":1878,"tools":1879,"steps":1882},"Generar un PDF en japonés con Go con subconjuntos TrueType nativos","PT20M",[1880,1881],"Go 1.22+","NotoSansJP-Regular.ttf y NotoSansJP-Bold.ttf (o cualquier par TTF con soporte CJK)",[1883,1886,1889,1892,1895,1898],{"name":1884,"text":1885},"Instalar gpdf y descargar las fuentes","Ejecuta go get github.com/gpdf-dev/gpdf. Descarga Noto Sans JP Regular y Bold desde Google Fonts y coloca los TTF junto a main.go. Sin CGO, sin configuración de fuentes del sistema.",{"name":1887,"text":1888},"Cargar los bytes TTF al iniciar","Lee ambos TTF con os.ReadFile en buffers []byte. //go:embed funciona si quieres compilar las fuentes dentro del binario.",{"name":1890,"text":1891},"Registrar las fuentes al construir el documento","Pasa gpdf.WithFont(\"NotoSansJP\", regular) y gpdf.WithFont(\"NotoSansJP-Bold\", bold) a gpdf.NewDocument. El nombre de familia es un identificador arbitrario — es el handle que usarás después.",{"name":1893,"text":1894},"Poner la fuente japonesa como predeterminada","Añade gpdf.WithDefaultFont(\"NotoSansJP\", 11). Cada c.Text usará la fuente japonesa sin opción FontFamily explícita.",{"name":1896,"text":1897},"Construir el árbol del documento con c.Text","Dentro de un bloque page.AutoRow, llama a r.Col(span, fn) y c.Text(\"こんにちは、世界。\"). Negrita y tamaño son opciones de template, no métodos separados.",{"name":1899,"text":1900},"Generar e inspeccionar la salida","Llama a doc.Generate() para obtener []byte, escribe a disco con os.WriteFile. Abre el PDF, selecciona el texto, pégalo en un editor — el ToUnicode CMap garantiza que copiar y pegar funcione.",null,{},"/es/blog/japanese-pdf-in-go",{"title":5,"description":1873},"es/blog/007.japanese-pdf-in-go",[1907,1908,1909],"tutorial","cjk","troubleshooting","Khci7UwVKuajP4ksUqSNRnDAlbP9FcfNS9Vdxihwlus",1776529274261]