分享使用谷歌翻译Laravel文档的过程

先放完成后的链接地址 Laravel 12.x
之前社区有大佬已分享过一个文档地址 laravel.wiki
但是这个地址最近访问的时候又开始变慢了,当想访问文档却迟迟打不开的时候急死个人,github上又没有源码,所以就想着自己看看能不能弄一个
最理想的状态是使用一个可以翻译markdown文档的AI,直接调用接口后就能完成翻译,最好还是免费的。实在找不到这个,导致我只能手动获取翻译好的laravel官网的文档网站,相当于直接抓取网站。
一 第一步先让浏览器可以使用谷歌翻译,根据这个 GoogleTranslateIpCheck
开源项目获取到 谷歌翻译的ip地址,在hosts文件中添加下指向,这样浏览器就能使用谷歌翻译了

到这一步其实我只要访问laravel的官网然后自动翻译成中文(翻译效果还行吧,能看懂就行了)就行了。但是ip地址很快可能就失效了,需要重新重复第一步获取ip地址。然后我就想着这不已经有翻译好的文档了吗,我直接复制html不就行了。

二 抓取翻译好的页面 总共96个页面 全部手动抓取 + 几个静态js 样式文件,都是泪啊。

三 处理抓取好的页面,比如有些标签需要删除,有些翻译过度需要复原,使用脚步遍历文件全部统一处理一遍。其中有2个处理比较麻烦,1.代码块已经渲染所以要清除掉已经渲染的代码块。2.搜索内容返回的链接还是laravel官网的,需要修改js替换掉laravel官网的链接。

因为只抓取了12.x的版本,其它版本的链接默认都是12.x
效果的话和官网没有太大差别,只有细微的差别

以下是php 代码示例
路由

Route::get('docs/{version}/{name?}', function($version,$name = 'index'){
        $file = public_path("docs/12.x/{$name}.html");
        $file = file_exists($file) ? $file : public_path("docs/12.x/index.html");
        return  file_get_contents($file);
    })->where('version', '[^\/]+')->where('name', '.*');

处理代码块

public function parseCodeBlock($content)
    {
        //js会自动生成relative code-block-wrapper的标签和复制button,因为是复制html导致这些标签多余了。这里直接去除,而不是修改js脚本

        //将classname包含copyBtn的button标签删除
        $content = preg_replace('/<button[^>]*class="[^"]*copyBtn[^"]*"[^>]*>.*?<\/button>/is', '', $content);
        //将classname等于relative code-block-wrapper的div标签去除
        $content = preg_replace('/<div[^>]*class="relative code-block-wrapper"[^>]*>/is', '', $content);
        $content = preg_replace('/<\/code><\/pre><\/div>/is', '</code></pre>', $content);
        return $content;
    }

遍历处理所有文件

        set_time_limit(0);
        //将文档html中的域名都清除
        $folder = public_path('docs/12.x');
        $files = scandir($folder);
        $count = 0;
        $name = request('name');
        foreach($files as $file)
        {
            if($file == '.' || $file == '..' || !str_ends_with($file,'.html')) continue;
            if($name && strpos($file, $name) === false) continue;
            $path = $folder.'/'.$file;
            $this->parse($path);
            $count++;
        }

处理单个文件

public function parse($path)
    {
        $fileinfo = pathinfo($path);
        $filename = $fileinfo['filename'];
        $content = file_get_contents($path);
        $singles_names = ['helpers','collections'];
        if(method_exists($this, $filename) && in_array($filename, $singles_names))
        {
            //指定处理单个文件
            $content = $this->$filename($content);
        }

        $content = preg_replace('/https:\/\/laravel.com/', '', $content);

        //将包含tags.js的script标签删除
        $content = preg_replace('/<script[^>]*src="[^"]*tags\.js"[^>]*><\/script>/', '', $content);
        //将包含www.gstatic.com的link标签删除
        $content = preg_replace('/<link[^>]*href="[^"]*www\.gstatic\.com[^"]*"[^>]*>/', '', $content);
        //将包含frontend的link标签删除
        $content = preg_replace('/<link[^>]*href="[^"]*frontend[^"]*"[^>]*>/', '', $content);
        //将包含configuration的link标签删除
        $content = preg_replace('/<link[^>]*href="[^"]*configuration[^"]*"[^>]*>/', '', $content);
        //将包含fetchpriority的link标签删除
        $content = preg_replace('/<link[^>]*fetchpriority="[^"]*"[^>]*>/', '', $content);
        //将id为goog-gt-tt的div标签删除包括div里面的内容
        $content = preg_replace('/<div[^>]*id="goog-gt-tt"[^>]*>.*?<\/div><\/div><\/div>/is', '', $content);
        //将class为text-sand-dark-10的div标签删除
        $content = preg_replace('/<div[^>]*class="text-sand-dark-10"[^>]*>.*?<!-- HubSpot -->/is', '', $content);
        //$content = preg_replace('/<script[^>]*>.*?rudderanalytics.*?<\/script>/is', '', $content);
        //将链接为https://laracon.us的a标签删除
        $content = preg_replace('/<a[^>]*href="https:\/\/laracon\.us"[^>]*>.*?<\/a>/is', '', $content);
        //将href中包含favicon的link标签删除
        $content = preg_replace('/<link[^>]*href="[^"]*favicon[^"]*"[^>]*>/', '', $content);
        //将data-active="true"删除
        $content = preg_replace('/data-active="true"/', '', $content);
        $search = [
            '套餐'=>'Packages',
            '立面'=>'Facades',
            '语境'=>'Context',
            '活动'=>'Events',
            '播种'=>'Seeding',
            '嘲讽'=>'Mocking',
            '收银员'=>'Cashiers',
            '桨'=>'Paddles',
            '黄昏'=>'Dusk',
            '使者'=>'Envoy',
            '强化'=>'Fortify',
            '家园'=>'Homestead',
            '地平线'=>'Horizon',
            '混合'=>'Mix',
            '辛烷'=>'Octane',
            '护照'=>'Passport',
            '三角旗'=>'Pennant',
            '品脱'=>'Pint',
            '预知'=>'Precognition',
            '提示'=>'Prompts',
            '脉冲'=>'Pulse',
            '混响'=>'Reverb',
            '帆'=>'Sail',
            '圣殿'=>'Sanctum',
            '侦察'=>'Scout',
            '社交名媛'=>'Socialite',
            '望远镜'=> 'Telescope',
            '代客泊车'=> 'Valet',
            '助手'=>'Helpers',
            '合同'=>'Contracts',
            '流程'=>'Processes',
            '收藏'=>'Collections',
            '工厂'=>'Factories',
            '回应'=>'响应',
            '资源捆绑'=>'Asset Bundling',
            '会议'=>'Sessions',
            '害虫'=>'Pest',
            '睡觉'=>'Sleep',
            '彩票'=>'Lottery',
            '管道'=>'Pipeline'
        ];
        $content = str_replace(array_keys($search), array_values($search), $content);
        $content = $this->parseCodeBlock($content);

        file_put_contents($path, $content);
        return;
    }

都看到这了再发下我使用的admin后台,大佬们可以的话帮忙点个star,以下是链接地址
DeAdmin

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 2

laravel.wiki 我访问感觉不慢呀 基本上每天我都会打开

1天前 评论
echoyl (楼主) 21小时前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!