[{"data":1,"prerenderedAt":1748},["ShallowReactive",2],{"article-laravel-i18n-json-dump":3},{"id":4,"title":5,"body":6,"category":1734,"createdAt":1736,"description":5,"extension":1737,"index":1738,"meta":1739,"navigation":293,"path":1740,"publish":293,"seo":1741,"series":1738,"seriesTitle":1738,"stem":1742,"tag":1743,"thumbnail":1746,"updatedAt":1738,"__hash__":1747},"articles\u002Farticles\u002Flaravel-i18n-json-dump.md","Laravelで多言語用のJSONを出力するコマンドを作る",{"type":7,"value":8,"toc":1722},"minimark",[9,26,68,75,90,103,108,111,117,200,207,210,220,223,226,233,236,240,250,258,261,264,267,273,280,511,518,524,527,530,537,700,727,730,733,831,852,856,890,905,908,923,937,940,943,1271,1274,1287,1295,1300,1303,1510,1708,1715,1718],[10,11,12,13,17,18,21,22,25],"p",{},"こんにちはjunです。個人開発で多言語対応のLaravelアプリを作っています。多言語では各種言語の単語・文章のマッピング（辞書）をする配列・JSONを作成し、レンダリング時にメソッドを使用して文字を表示します。Laravelでは",[14,15,16],"code",{},"resources\u002Flang"," 配下に",[14,19,20],{},"en","、",[14,23,24],{},"ja","のようなディレクトリを作成し、その中に言語のマッピングをします。大体は以下のような配列を作ります。",[27,28,34],"pre",{"className":29,"code":30,"filename":31,"language":32,"meta":33,"style":33},"language-php shiki shiki-themes material-theme-ocean","\u003C?php\nreturn [\n    'login'=>'ログイン',\n    'logout'=>'ログアウト'\n]\n\n","resources\u002Flang\u002Fja\u002Fwords.php","php","",[14,35,36,44,50,56,62],{"__ignoreMap":33},[37,38,41],"span",{"class":39,"line":40},"line",1,[37,42,43],{},"\u003C?php\n",[37,45,47],{"class":39,"line":46},2,[37,48,49],{},"return [\n",[37,51,53],{"class":39,"line":52},3,[37,54,55],{},"    'login'=>'ログイン',\n",[37,57,59],{"class":39,"line":58},4,[37,60,61],{},"    'logout'=>'ログアウト'\n",[37,63,65],{"class":39,"line":64},5,[37,66,67],{},"]\n",[10,69,70,71,74],{},"そしてビューファイルなどで",[14,72,73],{},"__('words.login')","のように使用します。",[76,77,81,82,85,86,89],"div",{"className":78},[79,80],"alert","alert-info","\n多言語のメソッドが",[14,83,84],{},"__","みたいな名称である理由としては、使いまくるので簡単な名称になっています。Vueとかでは",[14,87,88],{},"$t()","みたいなものを使用します。\n",[10,91,92,93,95,96,21,99,102],{},"上記のようなPHPファイルを作成してもできますが、",[14,94,16],{}," 直下に",[14,97,98],{},"en.json",[14,100,101],{},"ja.json","のようなJSONファイルを作成しても、多言語メソッドで呼び出せます。",[104,105,107],"h2",{"id":106},"jsonの弱点","JSONの弱点",[10,109,110],{},"JSONで作るメリットはマッピングのデータを他のアプリでも利用できることです。例えば、Vue・ReactではVuei18n、react-i18nextなどを使用します。同じように多言語メソッドを使用します。その際のマッピングデータとしてJSONを使用します。であればJSONファイルを作っておくことで、Vueや外部へマッピングデータを提供しやすくなります。",[10,112,113,114,116],{},"ただしJSONで作成するとLaravel側で",[14,115,73],{},"のような呼び出しができません。この時JSONは以下のようになっています。",[27,118,122],{"className":119,"code":120,"language":121,"meta":33,"style":33},"language-json shiki shiki-themes material-theme-ocean","{\n    \"words\":{\n        \"login\":\"ログイン\",\n        \"logout\":\"ログアウト\"\n    }\n}\n","json",[14,123,124,130,145,170,189,194],{"__ignoreMap":33},[37,125,126],{"class":39,"line":40},[37,127,129],{"class":128},"sAklC","{\n",[37,131,132,135,139,142],{"class":39,"line":46},[37,133,134],{"class":128},"    \"",[37,136,138],{"class":137},"sJ14y","words",[37,140,141],{"class":128},"\"",[37,143,144],{"class":128},":{\n",[37,146,147,150,154,156,159,161,165,167],{"class":39,"line":52},[37,148,149],{"class":128},"        \"",[37,151,153],{"class":152},"s5Dmg","login",[37,155,141],{"class":128},[37,157,158],{"class":128},":",[37,160,141],{"class":128},[37,162,164],{"class":163},"sfyAc","ログイン",[37,166,141],{"class":128},[37,168,169],{"class":128},",\n",[37,171,172,174,177,179,181,183,186],{"class":39,"line":58},[37,173,149],{"class":128},[37,175,176],{"class":152},"logout",[37,178,141],{"class":128},[37,180,158],{"class":128},[37,182,141],{"class":128},[37,184,185],{"class":163},"ログアウト",[37,187,188],{"class":128},"\"\n",[37,190,191],{"class":39,"line":64},[37,192,193],{"class":128},"    }\n",[37,195,197],{"class":39,"line":196},6,[37,198,199],{"class":128},"}\n",[10,201,202,203,206],{},"すべて一次元にしてしまうと後で混乱してしまうので、カスケードさせておくと良いです。Vuei18nでは",[14,204,205],{},"$t('words.login')","で呼び出せますが、なぜかLaravelではJSONのカスケード配下のキーを呼び出すことができません。",[10,208,209],{},"そのため",[211,212,213,217],"ul",{},[214,215,216],"li",{},"Laravel以外のアプリへの提供→JSON",[214,218,219],{},"Laravelの多言語対応→PHP",[10,221,222],{},"という２重管理でそれぞれ設定しないといけなくなり、非効率的です。",[104,224,225],{"id":225},"解決方法",[10,227,228,229,232],{},"解決方法としてはPHPで作成した配列をJSONにダンプすることです。そうすることでPHPファイルとJSONの言語ファイルを作成することができます。そこで今回の記事ではPHPの言語ファイルをカスケードさせたJSONに出力するような",[14,230,231],{},"artisan","コマンドを作ってみたいと思います。",[104,234,235],{"id":235},"コマンドの実装",[237,238,239],"h3",{"id":239},"対応する言語ディレクトリ",[10,241,242,243,17,245,21,247,249],{},"まずはLaravelの言語ファイルのドキュメントの通り、",[14,244,16],{},[14,246,20],{},[14,248,24],{},"のようなディレクトリを作成しておきましょう。今回は英語と日本語にしておきます。",[27,251,256],{"className":252,"code":254,"language":255},[253],"language-text","resources\n├── lang\n│   ├── en\n│   │   ├── auth.php\n│   │   ├── words.php\n│   │   └── exceptions.php\n│   └── ja\n│       ├── auth.php\n│       ├── words.php\n│       └── exceptions.php\n...\n","text",[14,257,254],{"__ignoreMap":33},[10,259,260],{},"そしてそのディレクトリごとにphpファイルを分けます。とりあえずこのようにしておきます。",[237,262,263],{"id":263},"コマンドのファイルを作成",[10,265,266],{},"それではカスタムのコマンドを作成しましょう。",[27,268,271],{"className":269,"code":270,"language":255},[253],"php artisan make:command Dumplang\n",[14,272,270],{"__ignoreMap":33},[10,274,275,276,279],{},"コマンドもartisanで作成できます。",[14,277,278],{},"app\u002FConsole\u002FCommands","というディレクトリが作成され、そこにファイルが作成されます。",[27,281,283],{"className":29,"code":282,"language":32,"meta":33,"style":33},"\u003C?php\n\nnamespace App\\Console\\Commands;\n\nuse Illuminate\\Console\\Command;\n\nclass Dumblang extends Command\n{\n    \u002F**\n     * The name and signature of the console command.\n     *\n     * @var string\n     *\u002F\n    protected $signature = 'lang:dump';\n\n    \u002F**\n     * The console command description.\n     *\n     * @var string\n     *\u002F\n    protected $description = 'Convert each php lang files to JSON files.';\n\n    \u002F**\n     * Create a new command instance.\n     *\n     * @return void\n     *\u002F\n    public function __construct()\n    {\n        parent::__construct();\n    }\n\n    \u002F**\n     * Execute the console command.\n     *\n     * @return int\n     *\u002F\n    public function handle()\n    {\n        \n    }\n}\n",[14,284,285,289,295,300,304,309,313,319,324,330,336,342,348,354,360,365,370,376,381,386,391,397,402,407,413,418,424,429,435,441,447,452,457,462,468,473,479,484,490,495,501,506],{"__ignoreMap":33},[37,286,287],{"class":39,"line":40},[37,288,43],{},[37,290,291],{"class":39,"line":46},[37,292,294],{"emptyLinePlaceholder":293},true,"\n",[37,296,297],{"class":39,"line":52},[37,298,299],{},"namespace App\\Console\\Commands;\n",[37,301,302],{"class":39,"line":58},[37,303,294],{"emptyLinePlaceholder":293},[37,305,306],{"class":39,"line":64},[37,307,308],{},"use Illuminate\\Console\\Command;\n",[37,310,311],{"class":39,"line":196},[37,312,294],{"emptyLinePlaceholder":293},[37,314,316],{"class":39,"line":315},7,[37,317,318],{},"class Dumblang extends Command\n",[37,320,322],{"class":39,"line":321},8,[37,323,129],{},[37,325,327],{"class":39,"line":326},9,[37,328,329],{},"    \u002F**\n",[37,331,333],{"class":39,"line":332},10,[37,334,335],{},"     * The name and signature of the console command.\n",[37,337,339],{"class":39,"line":338},11,[37,340,341],{},"     *\n",[37,343,345],{"class":39,"line":344},12,[37,346,347],{},"     * @var string\n",[37,349,351],{"class":39,"line":350},13,[37,352,353],{},"     *\u002F\n",[37,355,357],{"class":39,"line":356},14,[37,358,359],{},"    protected $signature = 'lang:dump';\n",[37,361,363],{"class":39,"line":362},15,[37,364,294],{"emptyLinePlaceholder":293},[37,366,368],{"class":39,"line":367},16,[37,369,329],{},[37,371,373],{"class":39,"line":372},17,[37,374,375],{},"     * The console command description.\n",[37,377,379],{"class":39,"line":378},18,[37,380,341],{},[37,382,384],{"class":39,"line":383},19,[37,385,347],{},[37,387,389],{"class":39,"line":388},20,[37,390,353],{},[37,392,394],{"class":39,"line":393},21,[37,395,396],{},"    protected $description = 'Convert each php lang files to JSON files.';\n",[37,398,400],{"class":39,"line":399},22,[37,401,294],{"emptyLinePlaceholder":293},[37,403,405],{"class":39,"line":404},23,[37,406,329],{},[37,408,410],{"class":39,"line":409},24,[37,411,412],{},"     * Create a new command instance.\n",[37,414,416],{"class":39,"line":415},25,[37,417,341],{},[37,419,421],{"class":39,"line":420},26,[37,422,423],{},"     * @return void\n",[37,425,427],{"class":39,"line":426},27,[37,428,353],{},[37,430,432],{"class":39,"line":431},28,[37,433,434],{},"    public function __construct()\n",[37,436,438],{"class":39,"line":437},29,[37,439,440],{},"    {\n",[37,442,444],{"class":39,"line":443},30,[37,445,446],{},"        parent::__construct();\n",[37,448,450],{"class":39,"line":449},31,[37,451,193],{},[37,453,455],{"class":39,"line":454},32,[37,456,294],{"emptyLinePlaceholder":293},[37,458,460],{"class":39,"line":459},33,[37,461,329],{},[37,463,465],{"class":39,"line":464},34,[37,466,467],{},"     * Execute the console command.\n",[37,469,471],{"class":39,"line":470},35,[37,472,341],{},[37,474,476],{"class":39,"line":475},36,[37,477,478],{},"     * @return int\n",[37,480,482],{"class":39,"line":481},37,[37,483,353],{},[37,485,487],{"class":39,"line":486},38,[37,488,489],{},"    public function handle()\n",[37,491,493],{"class":39,"line":492},39,[37,494,440],{},[37,496,498],{"class":39,"line":497},40,[37,499,500],{},"        \n",[37,502,504],{"class":39,"line":503},41,[37,505,193],{},[37,507,509],{"class":39,"line":508},42,[37,510,199],{},[10,512,513,514,517],{},"まずは上記のように、シグネチャと説明を記述します。シグネチャでは",[14,515,516],{},"lang:dump"," とすると",[27,519,522],{"className":520,"code":521,"language":255},[253],"php artisan lang:dump\n",[14,523,521],{"__ignoreMap":33},[10,525,526],{},"と入力するとこのコマンドを実行できます。",[237,528,529],{"id":529},"言語ディレクトリからファイルを読み込む",[10,531,532,533,536],{},"コマンドの内容は",[14,534,535],{},"handle()","に記述します。全体は以下の通りです。",[27,538,540],{"className":29,"code":539,"language":32,"meta":33,"style":33},"use Illuminate\\Support\\Facades\\File;\nuse Illuminate\\Support\\Facades\\Lang;\n\npublic function handle()\n{\n    $suports = [\"ja\",\"en\"];\n    \n    foreach($suports as $lng){\n        $langdir = resource_path('lang\u002F'.$lng);\n        if(is_dir($langdir)){\n            $files = scandir($langdir);\n            if($files === false) continue;\n\n            $files = array_filter($files,function($f){\n                return strpos($f,'.php') !== false;\n            });\n\n            $trans = [];\n            foreach($files as $f){\n                $content_key = str_replace('.php','',$f);\n                $content = include resource_path(\"lang\u002F$lng\u002F$f\");\n                $trans[$content_key] = $content;\n            }\n\n            $json = json_encode($trans,JSON_UNESCAPED_UNICODE);\n            File::put(resource_path('lang\u002F'.$lng.'.json'),$json);\n            File::put(base_path('nuxt\u002Flang\u002F'.$lng.'.json'),$json);\n        }else{\n            print(\"Lang directory for ${$lng} dose not exisits\");\n        }\n    }\n    return Command::SUCCESS;\n}\n",[14,541,542,547,552,556,561,565,570,575,580,585,590,595,600,604,609,614,619,623,628,633,638,643,648,653,657,662,667,672,677,682,687,691,696],{"__ignoreMap":33},[37,543,544],{"class":39,"line":40},[37,545,546],{},"use Illuminate\\Support\\Facades\\File;\n",[37,548,549],{"class":39,"line":46},[37,550,551],{},"use Illuminate\\Support\\Facades\\Lang;\n",[37,553,554],{"class":39,"line":52},[37,555,294],{"emptyLinePlaceholder":293},[37,557,558],{"class":39,"line":58},[37,559,560],{},"public function handle()\n",[37,562,563],{"class":39,"line":64},[37,564,129],{},[37,566,567],{"class":39,"line":196},[37,568,569],{},"    $suports = [\"ja\",\"en\"];\n",[37,571,572],{"class":39,"line":315},[37,573,574],{},"    \n",[37,576,577],{"class":39,"line":321},[37,578,579],{},"    foreach($suports as $lng){\n",[37,581,582],{"class":39,"line":326},[37,583,584],{},"        $langdir = resource_path('lang\u002F'.$lng);\n",[37,586,587],{"class":39,"line":332},[37,588,589],{},"        if(is_dir($langdir)){\n",[37,591,592],{"class":39,"line":338},[37,593,594],{},"            $files = scandir($langdir);\n",[37,596,597],{"class":39,"line":344},[37,598,599],{},"            if($files === false) continue;\n",[37,601,602],{"class":39,"line":350},[37,603,294],{"emptyLinePlaceholder":293},[37,605,606],{"class":39,"line":356},[37,607,608],{},"            $files = array_filter($files,function($f){\n",[37,610,611],{"class":39,"line":362},[37,612,613],{},"                return strpos($f,'.php') !== false;\n",[37,615,616],{"class":39,"line":367},[37,617,618],{},"            });\n",[37,620,621],{"class":39,"line":372},[37,622,294],{"emptyLinePlaceholder":293},[37,624,625],{"class":39,"line":378},[37,626,627],{},"            $trans = [];\n",[37,629,630],{"class":39,"line":383},[37,631,632],{},"            foreach($files as $f){\n",[37,634,635],{"class":39,"line":388},[37,636,637],{},"                $content_key = str_replace('.php','',$f);\n",[37,639,640],{"class":39,"line":393},[37,641,642],{},"                $content = include resource_path(\"lang\u002F$lng\u002F$f\");\n",[37,644,645],{"class":39,"line":399},[37,646,647],{},"                $trans[$content_key] = $content;\n",[37,649,650],{"class":39,"line":404},[37,651,652],{},"            }\n",[37,654,655],{"class":39,"line":409},[37,656,294],{"emptyLinePlaceholder":293},[37,658,659],{"class":39,"line":415},[37,660,661],{},"            $json = json_encode($trans,JSON_UNESCAPED_UNICODE);\n",[37,663,664],{"class":39,"line":420},[37,665,666],{},"            File::put(resource_path('lang\u002F'.$lng.'.json'),$json);\n",[37,668,669],{"class":39,"line":426},[37,670,671],{},"            File::put(base_path('nuxt\u002Flang\u002F'.$lng.'.json'),$json);\n",[37,673,674],{"class":39,"line":431},[37,675,676],{},"        }else{\n",[37,678,679],{"class":39,"line":437},[37,680,681],{},"            print(\"Lang directory for ${$lng} dose not exisits\");\n",[37,683,684],{"class":39,"line":443},[37,685,686],{},"        }\n",[37,688,689],{"class":39,"line":449},[37,690,193],{},[37,692,693],{"class":39,"line":454},[37,694,695],{},"    return Command::SUCCESS;\n",[37,697,698],{"class":39,"line":459},[37,699,199],{},[27,701,703],{"className":29,"code":702,"language":32,"meta":33,"style":33},"$suports = [\"ja\",\"en\"];\n\nforeach($suports as $lng){\n\n}\n",[14,704,705,710,714,719,723],{"__ignoreMap":33},[37,706,707],{"class":39,"line":40},[37,708,709],{},"$suports = [\"ja\",\"en\"];\n",[37,711,712],{"class":39,"line":46},[37,713,294],{"emptyLinePlaceholder":293},[37,715,716],{"class":39,"line":52},[37,717,718],{},"foreach($suports as $lng){\n",[37,720,721],{"class":39,"line":58},[37,722,294],{"emptyLinePlaceholder":293},[37,724,725],{"class":39,"line":64},[37,726,199],{},[10,728,729],{},"まずは取得予定の言語の配列を用意します。それを再帰的に処理します。",[10,731,732],{},"元となる言語ディレクトリからファイルの一覧を取得します。",[27,734,736],{"className":29,"code":735,"language":32,"meta":33,"style":33},"foreach($suports as $lng){\n    $langdir = resource_path('lang\u002F'.$lng);\n    if(is_dir($langdir)){\n        $files = scandir($langdir);\n        if($files === false) continue;\n\n        $files = array_filter($files,function($f){\n            return strpos($f,'.php') !== false;\n        });\n\n        $trans = [];\n        foreach($files as $f){\n            $content_key = str_replace('.php','',$f);\n            $content = include resource_path(\"lang\u002F$lng\u002F$f\");\n            $trans[$content_key] = $content;\n        }\n\n        \u002F\u002F ....\n    }\n}\n",[14,737,738,742,747,752,757,762,766,771,776,781,785,790,795,800,805,810,814,818,823,827],{"__ignoreMap":33},[37,739,740],{"class":39,"line":40},[37,741,718],{},[37,743,744],{"class":39,"line":46},[37,745,746],{},"    $langdir = resource_path('lang\u002F'.$lng);\n",[37,748,749],{"class":39,"line":52},[37,750,751],{},"    if(is_dir($langdir)){\n",[37,753,754],{"class":39,"line":58},[37,755,756],{},"        $files = scandir($langdir);\n",[37,758,759],{"class":39,"line":64},[37,760,761],{},"        if($files === false) continue;\n",[37,763,764],{"class":39,"line":196},[37,765,294],{"emptyLinePlaceholder":293},[37,767,768],{"class":39,"line":315},[37,769,770],{},"        $files = array_filter($files,function($f){\n",[37,772,773],{"class":39,"line":321},[37,774,775],{},"            return strpos($f,'.php') !== false;\n",[37,777,778],{"class":39,"line":326},[37,779,780],{},"        });\n",[37,782,783],{"class":39,"line":332},[37,784,294],{"emptyLinePlaceholder":293},[37,786,787],{"class":39,"line":338},[37,788,789],{},"        $trans = [];\n",[37,791,792],{"class":39,"line":344},[37,793,794],{},"        foreach($files as $f){\n",[37,796,797],{"class":39,"line":350},[37,798,799],{},"            $content_key = str_replace('.php','',$f);\n",[37,801,802],{"class":39,"line":356},[37,803,804],{},"            $content = include resource_path(\"lang\u002F$lng\u002F$f\");\n",[37,806,807],{"class":39,"line":362},[37,808,809],{},"            $trans[$content_key] = $content;\n",[37,811,812],{"class":39,"line":367},[37,813,686],{},[37,815,816],{"class":39,"line":372},[37,817,294],{"emptyLinePlaceholder":293},[37,819,820],{"class":39,"line":378},[37,821,822],{},"        \u002F\u002F ....\n",[37,824,825],{"class":39,"line":383},[37,826,193],{},[37,828,829],{"class":39,"line":388},[37,830,199],{},[10,832,833,836,837,840,841,843,844,847,848,851],{},[14,834,835],{},"resource_path('lang\u002F'.$lng)","で先程の言語ディレクトリのパスを取得し、",[14,838,839],{},"scandir()","を用いて内部のファイルを配列で取得します。",[14,842,839],{},"はphp以外のファイルや",[14,845,846],{},".","みたいなSELinuxが勝手に作る謎ファイルも読み取ってしまうので、",[14,849,850],{},"array_filter()","を用いてフィルターします。",[237,853,855],{"id":854},"一つの配列に打ち込んでjson化する","一つの配列に打ち込んでJSON化する",[27,857,859],{"className":29,"code":858,"language":32,"meta":33,"style":33},"$trans = [];\nforeach($files as $f){\n    $content_key = str_replace('.php','',$f);\n    $content = include resource_path(\"lang\u002F$lng\u002F$f\");\n    $trans[$content_key] = $content;\n}\n",[14,860,861,866,871,876,881,886],{"__ignoreMap":33},[37,862,863],{"class":39,"line":40},[37,864,865],{},"$trans = [];\n",[37,867,868],{"class":39,"line":46},[37,869,870],{},"foreach($files as $f){\n",[37,872,873],{"class":39,"line":52},[37,874,875],{},"    $content_key = str_replace('.php','',$f);\n",[37,877,878],{"class":39,"line":58},[37,879,880],{},"    $content = include resource_path(\"lang\u002F$lng\u002F$f\");\n",[37,882,883],{"class":39,"line":64},[37,884,885],{},"    $trans[$content_key] = $content;\n",[37,887,888],{"class":39,"line":196},[37,889,199],{},[10,891,892,893,896,897,900,901,904],{},"JSONではphpファイル名を一次キーとして利用したいので ",[14,894,895],{},"str_replace('.php','',$f)","でファイル名を取得します。",[14,898,899],{},"include resource_path(\"lang\u002F$lng\u002F$f\")","でphpファイルの記述を取得ます。そしてJSONにする配列に、ファイル名をキーとして打ち込みます。",[14,902,903],{},"$trans[$content_key] = $content;"," それをスキャンした言語PHPファイル全てに行います。",[237,906,907],{"id":907},"ファイルを出力",[27,909,911],{"className":29,"code":910,"language":32,"meta":33,"style":33},"$json = json_encode($trans,JSON_UNESCAPED_UNICODE);\nFile::put(resource_path('lang\u002F'.$lng.'.json'),$json);\n",[14,912,913,918],{"__ignoreMap":33},[37,914,915],{"class":39,"line":40},[37,916,917],{},"$json = json_encode($trans,JSON_UNESCAPED_UNICODE);\n",[37,919,920],{"class":39,"line":46},[37,921,922],{},"File::put(resource_path('lang\u002F'.$lng.'.json'),$json);\n",[10,924,925,926,929,930,932,933,936],{},"そして１つにまとめた配列を",[14,927,928],{},"json_encode","をしておき、それを",[14,931,16],{}," 配下します。その際には",[14,934,935],{},"言語名.json","となるようにしておきます。",[104,938,939],{"id":939},"全容と実行",[10,941,942],{},"コードは以下の通りです。",[27,944,946],{"className":29,"code":945,"language":32,"meta":33,"style":33},"\u003C?php\n\nnamespace App\\Console\\Commands;\n\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support\\Facades\\File;\nuse Illuminate\\Support\\Facades\\Lang;\n\nclass Dumblang extends Command\n{\n    \u002F**\n     * The name and signature of the console command.\n     *\n     * @var string\n     *\u002F\n    protected $signature = 'lang:dump';\n\n    \u002F**\n     * The console command description.\n     *\n     * @var string\n     *\u002F\n    protected $description = 'Convert each php lang files to JSON files.';\n\n    \u002F**\n     * Create a new command instance.\n     *\n     * @return void\n     *\u002F\n    public function __construct()\n    {\n        parent::__construct();\n    }\n\n    \u002F**\n     * Execute the console command.\n     *\n     * @return int\n     *\u002F\n    public function handle()\n    {\n        $suports = config('app.support_langs');\n        \n        foreach($suports as $lng){\n            $langdir = resource_path('lang\u002F'.$lng);\n            if(is_dir($langdir)){\n                $files = scandir($langdir);\n                if($files === false) continue;\n\n                $files = array_filter($files,function($f){\n                    return strpos($f,'.php') !== false;\n                });\n\n                $trans = [];\n                foreach($files as $f){\n                    $content_key = str_replace('.php','',$f);\n                    $content = include resource_path(\"lang\u002F$lng\u002F$f\");\n                    $trans[$content_key] = $content;\n                }\n\n                $json = json_encode($trans,JSON_UNESCAPED_UNICODE);\n                File::put(resource_path('lang\u002F'.$lng.'.json'),$json);\n            }else{\n                print(\"Lang directory for ${$lng} dose not exisits\");\n            }\n        }\n        return Command::SUCCESS;\n    }\n}\n",[14,947,948,952,956,960,964,968,972,976,980,984,988,992,996,1000,1004,1008,1012,1016,1020,1024,1028,1032,1036,1040,1044,1048,1052,1056,1060,1064,1068,1072,1076,1080,1084,1088,1092,1096,1100,1104,1108,1112,1117,1122,1128,1134,1140,1146,1152,1157,1163,1169,1175,1180,1186,1192,1198,1204,1210,1216,1221,1227,1233,1239,1245,1250,1255,1261,1266],{"__ignoreMap":33},[37,949,950],{"class":39,"line":40},[37,951,43],{},[37,953,954],{"class":39,"line":46},[37,955,294],{"emptyLinePlaceholder":293},[37,957,958],{"class":39,"line":52},[37,959,299],{},[37,961,962],{"class":39,"line":58},[37,963,294],{"emptyLinePlaceholder":293},[37,965,966],{"class":39,"line":64},[37,967,308],{},[37,969,970],{"class":39,"line":196},[37,971,546],{},[37,973,974],{"class":39,"line":315},[37,975,551],{},[37,977,978],{"class":39,"line":321},[37,979,294],{"emptyLinePlaceholder":293},[37,981,982],{"class":39,"line":326},[37,983,318],{},[37,985,986],{"class":39,"line":332},[37,987,129],{},[37,989,990],{"class":39,"line":338},[37,991,329],{},[37,993,994],{"class":39,"line":344},[37,995,335],{},[37,997,998],{"class":39,"line":350},[37,999,341],{},[37,1001,1002],{"class":39,"line":356},[37,1003,347],{},[37,1005,1006],{"class":39,"line":362},[37,1007,353],{},[37,1009,1010],{"class":39,"line":367},[37,1011,359],{},[37,1013,1014],{"class":39,"line":372},[37,1015,294],{"emptyLinePlaceholder":293},[37,1017,1018],{"class":39,"line":378},[37,1019,329],{},[37,1021,1022],{"class":39,"line":383},[37,1023,375],{},[37,1025,1026],{"class":39,"line":388},[37,1027,341],{},[37,1029,1030],{"class":39,"line":393},[37,1031,347],{},[37,1033,1034],{"class":39,"line":399},[37,1035,353],{},[37,1037,1038],{"class":39,"line":404},[37,1039,396],{},[37,1041,1042],{"class":39,"line":409},[37,1043,294],{"emptyLinePlaceholder":293},[37,1045,1046],{"class":39,"line":415},[37,1047,329],{},[37,1049,1050],{"class":39,"line":420},[37,1051,412],{},[37,1053,1054],{"class":39,"line":426},[37,1055,341],{},[37,1057,1058],{"class":39,"line":431},[37,1059,423],{},[37,1061,1062],{"class":39,"line":437},[37,1063,353],{},[37,1065,1066],{"class":39,"line":443},[37,1067,434],{},[37,1069,1070],{"class":39,"line":449},[37,1071,440],{},[37,1073,1074],{"class":39,"line":454},[37,1075,446],{},[37,1077,1078],{"class":39,"line":459},[37,1079,193],{},[37,1081,1082],{"class":39,"line":464},[37,1083,294],{"emptyLinePlaceholder":293},[37,1085,1086],{"class":39,"line":470},[37,1087,329],{},[37,1089,1090],{"class":39,"line":475},[37,1091,467],{},[37,1093,1094],{"class":39,"line":481},[37,1095,341],{},[37,1097,1098],{"class":39,"line":486},[37,1099,478],{},[37,1101,1102],{"class":39,"line":492},[37,1103,353],{},[37,1105,1106],{"class":39,"line":497},[37,1107,489],{},[37,1109,1110],{"class":39,"line":503},[37,1111,440],{},[37,1113,1114],{"class":39,"line":508},[37,1115,1116],{},"        $suports = config('app.support_langs');\n",[37,1118,1120],{"class":39,"line":1119},43,[37,1121,500],{},[37,1123,1125],{"class":39,"line":1124},44,[37,1126,1127],{},"        foreach($suports as $lng){\n",[37,1129,1131],{"class":39,"line":1130},45,[37,1132,1133],{},"            $langdir = resource_path('lang\u002F'.$lng);\n",[37,1135,1137],{"class":39,"line":1136},46,[37,1138,1139],{},"            if(is_dir($langdir)){\n",[37,1141,1143],{"class":39,"line":1142},47,[37,1144,1145],{},"                $files = scandir($langdir);\n",[37,1147,1149],{"class":39,"line":1148},48,[37,1150,1151],{},"                if($files === false) continue;\n",[37,1153,1155],{"class":39,"line":1154},49,[37,1156,294],{"emptyLinePlaceholder":293},[37,1158,1160],{"class":39,"line":1159},50,[37,1161,1162],{},"                $files = array_filter($files,function($f){\n",[37,1164,1166],{"class":39,"line":1165},51,[37,1167,1168],{},"                    return strpos($f,'.php') !== false;\n",[37,1170,1172],{"class":39,"line":1171},52,[37,1173,1174],{},"                });\n",[37,1176,1178],{"class":39,"line":1177},53,[37,1179,294],{"emptyLinePlaceholder":293},[37,1181,1183],{"class":39,"line":1182},54,[37,1184,1185],{},"                $trans = [];\n",[37,1187,1189],{"class":39,"line":1188},55,[37,1190,1191],{},"                foreach($files as $f){\n",[37,1193,1195],{"class":39,"line":1194},56,[37,1196,1197],{},"                    $content_key = str_replace('.php','',$f);\n",[37,1199,1201],{"class":39,"line":1200},57,[37,1202,1203],{},"                    $content = include resource_path(\"lang\u002F$lng\u002F$f\");\n",[37,1205,1207],{"class":39,"line":1206},58,[37,1208,1209],{},"                    $trans[$content_key] = $content;\n",[37,1211,1213],{"class":39,"line":1212},59,[37,1214,1215],{},"                }\n",[37,1217,1219],{"class":39,"line":1218},60,[37,1220,294],{"emptyLinePlaceholder":293},[37,1222,1224],{"class":39,"line":1223},61,[37,1225,1226],{},"                $json = json_encode($trans,JSON_UNESCAPED_UNICODE);\n",[37,1228,1230],{"class":39,"line":1229},62,[37,1231,1232],{},"                File::put(resource_path('lang\u002F'.$lng.'.json'),$json);\n",[37,1234,1236],{"class":39,"line":1235},63,[37,1237,1238],{},"            }else{\n",[37,1240,1242],{"class":39,"line":1241},64,[37,1243,1244],{},"                print(\"Lang directory for ${$lng} dose not exisits\");\n",[37,1246,1248],{"class":39,"line":1247},65,[37,1249,652],{},[37,1251,1253],{"class":39,"line":1252},66,[37,1254,686],{},[37,1256,1258],{"class":39,"line":1257},67,[37,1259,1260],{},"        return Command::SUCCESS;\n",[37,1262,1264],{"class":39,"line":1263},68,[37,1265,193],{},[37,1267,1269],{"class":39,"line":1268},69,[37,1270,199],{},[10,1272,1273],{},"ちょっと気をつける点としては",[211,1275,1276,1282],{},[214,1277,1278,1281],{},[14,1279,1280],{},"is_dir($langdir)"," で言語ディレクトリの存在チェック",[214,1283,1284,1286],{},[14,1285,839],{}," で取得したファイルをフィルタする",[10,1288,1289,1290,21,1292,1294],{},"実行してみると",[14,1291,101],{},[14,1293,98],{},"というのが作成され、みてみると",[27,1296,1298],{"className":1297,"code":254,"language":255},[253],[14,1299,254],{"__ignoreMap":33},[10,1301,1302],{},"↓",[27,1304,1306],{"className":119,"code":1305,"filename":101,"language":121,"meta":33,"style":33},"{\n    \"auth\":{\n        \"login\":\"ログイン\",\n        \"logout\":\"ログアウト\",\n    },\n    \"words\":{\n        \"save\":\"保存\",\n        \"update\":\"更新\"\n    },\n    \"exceptions\":{\n        \"401\":\"ログインしてください。\",\n        \"model\":{\n            \"403\":\"このデータにアクセスできません。\",\n            \"404\":\"対応するデータが見つかりません。\"\n        }\n    }\n}\n",[14,1307,1308,1312,1323,1341,1359,1364,1374,1394,1412,1416,1427,1447,1458,1480,1498,1502,1506],{"__ignoreMap":33},[37,1309,1310],{"class":39,"line":40},[37,1311,129],{"class":128},[37,1313,1314,1316,1319,1321],{"class":39,"line":46},[37,1315,134],{"class":128},[37,1317,1318],{"class":137},"auth",[37,1320,141],{"class":128},[37,1322,144],{"class":128},[37,1324,1325,1327,1329,1331,1333,1335,1337,1339],{"class":39,"line":52},[37,1326,149],{"class":128},[37,1328,153],{"class":152},[37,1330,141],{"class":128},[37,1332,158],{"class":128},[37,1334,141],{"class":128},[37,1336,164],{"class":163},[37,1338,141],{"class":128},[37,1340,169],{"class":128},[37,1342,1343,1345,1347,1349,1351,1353,1355,1357],{"class":39,"line":58},[37,1344,149],{"class":128},[37,1346,176],{"class":152},[37,1348,141],{"class":128},[37,1350,158],{"class":128},[37,1352,141],{"class":128},[37,1354,185],{"class":163},[37,1356,141],{"class":128},[37,1358,169],{"class":128},[37,1360,1361],{"class":39,"line":64},[37,1362,1363],{"class":128},"    },\n",[37,1365,1366,1368,1370,1372],{"class":39,"line":196},[37,1367,134],{"class":128},[37,1369,138],{"class":137},[37,1371,141],{"class":128},[37,1373,144],{"class":128},[37,1375,1376,1378,1381,1383,1385,1387,1390,1392],{"class":39,"line":315},[37,1377,149],{"class":128},[37,1379,1380],{"class":152},"save",[37,1382,141],{"class":128},[37,1384,158],{"class":128},[37,1386,141],{"class":128},[37,1388,1389],{"class":163},"保存",[37,1391,141],{"class":128},[37,1393,169],{"class":128},[37,1395,1396,1398,1401,1403,1405,1407,1410],{"class":39,"line":321},[37,1397,149],{"class":128},[37,1399,1400],{"class":152},"update",[37,1402,141],{"class":128},[37,1404,158],{"class":128},[37,1406,141],{"class":128},[37,1408,1409],{"class":163},"更新",[37,1411,188],{"class":128},[37,1413,1414],{"class":39,"line":326},[37,1415,1363],{"class":128},[37,1417,1418,1420,1423,1425],{"class":39,"line":332},[37,1419,134],{"class":128},[37,1421,1422],{"class":137},"exceptions",[37,1424,141],{"class":128},[37,1426,144],{"class":128},[37,1428,1429,1431,1434,1436,1438,1440,1443,1445],{"class":39,"line":338},[37,1430,149],{"class":128},[37,1432,1433],{"class":152},"401",[37,1435,141],{"class":128},[37,1437,158],{"class":128},[37,1439,141],{"class":128},[37,1441,1442],{"class":163},"ログインしてください。",[37,1444,141],{"class":128},[37,1446,169],{"class":128},[37,1448,1449,1451,1454,1456],{"class":39,"line":344},[37,1450,149],{"class":128},[37,1452,1453],{"class":152},"model",[37,1455,141],{"class":128},[37,1457,144],{"class":128},[37,1459,1460,1463,1467,1469,1471,1473,1476,1478],{"class":39,"line":350},[37,1461,1462],{"class":128},"            \"",[37,1464,1466],{"class":1465},"sx098","403",[37,1468,141],{"class":128},[37,1470,158],{"class":128},[37,1472,141],{"class":128},[37,1474,1475],{"class":163},"このデータにアクセスできません。",[37,1477,141],{"class":128},[37,1479,169],{"class":128},[37,1481,1482,1484,1487,1489,1491,1493,1496],{"class":39,"line":356},[37,1483,1462],{"class":128},[37,1485,1486],{"class":1465},"404",[37,1488,141],{"class":128},[37,1490,158],{"class":128},[37,1492,141],{"class":128},[37,1494,1495],{"class":163},"対応するデータが見つかりません。",[37,1497,188],{"class":128},[37,1499,1500],{"class":39,"line":362},[37,1501,686],{"class":128},[37,1503,1504],{"class":39,"line":367},[37,1505,193],{"class":128},[37,1507,1508],{"class":39,"line":372},[37,1509,199],{"class":128},[27,1511,1513],{"className":119,"code":1512,"filename":98,"language":121,"meta":33,"style":33},"{\n    \"auth\":{\n        \"login\":\"Login\",\n        \"logout\":\"Logout\",\n    },\n    \"words\":{\n        \"save\":\"Saving\",\n        \"update\":\"Updating\"\n    },\n    \"exceptions\":{\n        \"401\":\"Please login.\",\n        \"model\":{\n            \"403\":\"You can not access to this data.\",\n            \"404\":\"The data you request is not found.\"\n        }\n    }\n}\n",[14,1514,1515,1519,1529,1548,1567,1571,1581,1600,1617,1621,1631,1650,1660,1679,1696,1700,1704],{"__ignoreMap":33},[37,1516,1517],{"class":39,"line":40},[37,1518,129],{"class":128},[37,1520,1521,1523,1525,1527],{"class":39,"line":46},[37,1522,134],{"class":128},[37,1524,1318],{"class":137},[37,1526,141],{"class":128},[37,1528,144],{"class":128},[37,1530,1531,1533,1535,1537,1539,1541,1544,1546],{"class":39,"line":52},[37,1532,149],{"class":128},[37,1534,153],{"class":152},[37,1536,141],{"class":128},[37,1538,158],{"class":128},[37,1540,141],{"class":128},[37,1542,1543],{"class":163},"Login",[37,1545,141],{"class":128},[37,1547,169],{"class":128},[37,1549,1550,1552,1554,1556,1558,1560,1563,1565],{"class":39,"line":58},[37,1551,149],{"class":128},[37,1553,176],{"class":152},[37,1555,141],{"class":128},[37,1557,158],{"class":128},[37,1559,141],{"class":128},[37,1561,1562],{"class":163},"Logout",[37,1564,141],{"class":128},[37,1566,169],{"class":128},[37,1568,1569],{"class":39,"line":64},[37,1570,1363],{"class":128},[37,1572,1573,1575,1577,1579],{"class":39,"line":196},[37,1574,134],{"class":128},[37,1576,138],{"class":137},[37,1578,141],{"class":128},[37,1580,144],{"class":128},[37,1582,1583,1585,1587,1589,1591,1593,1596,1598],{"class":39,"line":315},[37,1584,149],{"class":128},[37,1586,1380],{"class":152},[37,1588,141],{"class":128},[37,1590,158],{"class":128},[37,1592,141],{"class":128},[37,1594,1595],{"class":163},"Saving",[37,1597,141],{"class":128},[37,1599,169],{"class":128},[37,1601,1602,1604,1606,1608,1610,1612,1615],{"class":39,"line":321},[37,1603,149],{"class":128},[37,1605,1400],{"class":152},[37,1607,141],{"class":128},[37,1609,158],{"class":128},[37,1611,141],{"class":128},[37,1613,1614],{"class":163},"Updating",[37,1616,188],{"class":128},[37,1618,1619],{"class":39,"line":326},[37,1620,1363],{"class":128},[37,1622,1623,1625,1627,1629],{"class":39,"line":332},[37,1624,134],{"class":128},[37,1626,1422],{"class":137},[37,1628,141],{"class":128},[37,1630,144],{"class":128},[37,1632,1633,1635,1637,1639,1641,1643,1646,1648],{"class":39,"line":338},[37,1634,149],{"class":128},[37,1636,1433],{"class":152},[37,1638,141],{"class":128},[37,1640,158],{"class":128},[37,1642,141],{"class":128},[37,1644,1645],{"class":163},"Please login.",[37,1647,141],{"class":128},[37,1649,169],{"class":128},[37,1651,1652,1654,1656,1658],{"class":39,"line":344},[37,1653,149],{"class":128},[37,1655,1453],{"class":152},[37,1657,141],{"class":128},[37,1659,144],{"class":128},[37,1661,1662,1664,1666,1668,1670,1672,1675,1677],{"class":39,"line":350},[37,1663,1462],{"class":128},[37,1665,1466],{"class":1465},[37,1667,141],{"class":128},[37,1669,158],{"class":128},[37,1671,141],{"class":128},[37,1673,1674],{"class":163},"You can not access to this data.",[37,1676,141],{"class":128},[37,1678,169],{"class":128},[37,1680,1681,1683,1685,1687,1689,1691,1694],{"class":39,"line":356},[37,1682,1462],{"class":128},[37,1684,1486],{"class":1465},[37,1686,141],{"class":128},[37,1688,158],{"class":128},[37,1690,141],{"class":128},[37,1692,1693],{"class":163},"The data you request is not found.",[37,1695,188],{"class":128},[37,1697,1698],{"class":39,"line":362},[37,1699,686],{"class":128},[37,1701,1702],{"class":39,"line":367},[37,1703,193],{"class":128},[37,1705,1706],{"class":39,"line":372},[37,1707,199],{"class":128},[10,1709,1710,1711,1714],{},"これでPHPファイルだけでJSONの言語ファイルも作成して、フロントでのVueの言語ファイルなどに提供することができるようになります。動的にこのJSONファイルは生成するので、バージョン管理をするときは",[14,1712,1713],{},".gitignore","で指定しておくといいです。そしてデプロイや更新時にはこのコマンドを打ち忘れないようにしましょう。",[10,1716,1717],{},"ちなみにですが、実際にやっていることは特定のディレクトリのPHPファイルの内容を取得して、それをJSONにして生成したファイルを置いているだけなので素のPHP、pythonやrubyとか他の言語でも行けると思いますよ。",[1719,1720,1721],"style",{},"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 pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .s5Dmg, html code.shiki .s5Dmg{--shiki-default:#FFCB6B}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}",{"title":33,"searchDepth":52,"depth":52,"links":1723},[1724,1725,1726,1733],{"id":106,"depth":46,"text":107},{"id":225,"depth":46,"text":225},{"id":235,"depth":46,"text":235,"children":1727},[1728,1729,1730,1731,1732],{"id":239,"depth":52,"text":239},{"id":263,"depth":52,"text":263},{"id":529,"depth":52,"text":529},{"id":854,"depth":52,"text":855},{"id":907,"depth":52,"text":907},{"id":939,"depth":46,"text":939},[1735],"ministack","2022-05-22","md",null,{},"\u002Farticles\u002Flaravel-i18n-json-dump",{"title":5,"description":5},"articles\u002Flaravel-i18n-json-dump",[32,1744,1745],"laravel","js","_common\u002Flaravel.png","tdUMQGHoIH7SI9TXJlID3MGccNOOjq6udWMjq_HTqC0",1780987143020]