当前位置: 首页 > news >正文

浏览器默认语言与页面访问统计问题二三则

文章目录

  • 前言
  • 网站默认语言问题
  • 网站访问统计问题
    • Error: Empty components are self-closing
    • Error: A space is required before closing bracket
  • 总结

前言

看标题大概能猜到这是一篇杂合体的总结,是这两天处理网站遇到的小问题,怕过段时间再忘了所以总结到一起便于反过来查找问题解决方案,这个问题都是之前未曾接触过的,但遇到他们不用惧怕,只要假装自己能解决就行,这样稳扎稳打的找方案就能解决了。

网站默认语言问题

一个使用Nextjs框架编写的网站,支持中日英三种语言,如果访问主页面时未选择语言,则按照浏览器的语言来选择,这是合理的,一个人如果总用中文的浏览器,那么他在访问一个新网站时较大可能是想看中文的页面,所以我们优先选择当前浏览器的语言即可,默认跳转到指定语言的页面,选择语言的代码如下,是一个中间件 middleware.ts,问题在于默认语言为日文的浏览器,打开网页是英文的,这就得查查是因为什么了:

import { NextRequest, NextResponse } from 'next/server';
import acceptLanguage from 'accept-language';
import { fallbackLng, languages } from './app/i18n/settings';acceptLanguage.languages(languages);export const config = {// matcher: '/:lng*'matcher: ['/((?!api|_next/static|_next/image|images|svg|assets|favicon.ico|sw.js).*)']
};const cookieName = 'i18next';export function middleware(req: NextRequest) {let lng;// if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req.cookies.get(cookieName)?.value);if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language'));if (!lng) lng = fallbackLng;// Redirect if lng in path is not supportedif (!languages.some((loc) => req.nextUrl.pathname.startsWith(`/${loc}`))&& !req.nextUrl.pathname.startsWith('/_next')) {return NextResponse.redirect(new URL(`/${lng}${req.nextUrl.pathname}`, req.url));}if (req.headers.has('referer')) {const refererUrl = new URL(req.headers.get('referer') || 'zh');const lngInReferer = languages.find((l) => refererUrl.pathname.startsWith(`/${l}`));const response = NextResponse.next();if (lngInReferer) response.cookies.set(cookieName, lngInReferer);return response;}return NextResponse.next();
}

其中 matcher 是用来匹配路径的,这个配置表示,中间件会在请求的路径不包含特定字符串时触发。也就是说,路径不能包含指定的 api_next/static 等词缀。

网站语言看这一句 if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language')); 就行了,它的含义是网站可以根据 Accept-Language 请求头来检测浏览器的首选语言,并返回相应语言的内容。

而我将浏览器默认语言设置为日语时,打开网站传递的 Accept-Language 内容为 ja,en;q=0.9,zh-CN;q=0.8,zh;q=0.7

根据你提供的 Accept-Language 内容 ja,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,以下是中间件的处理过程:

acceptLanguage.get(req.headers.get('Accept-Language')) 函数会根据 Accept-Language 头部的内容来选择最适合的语言。根据我浏览器传递的内容:

  • ja(日语)有最高的优先级。
  • en(英语)优先级为 0.9。
  • zh-CN(简体中文)优先级为 0.8。
  • zh(中文)优先级为 0.7。

由于 ja 的优先级是 1(默认)并且是最优的匹配,所以 acceptLanguage.get() 会选择 ja 作为首选语言。

但是可以还取决于 languages 的值,因为 acceptLanguage 是通过 languages 完成初始化的,而我查询了项目中它的值为 export const languages = ['jp', 'en', 'zh'];,发现问题了没有?日语浏览器将 ja 作为最优先展示语言,但是备选项里没有 ja,所以最终选出的结果是 en,这也就解释了为什么日语浏览器默认打开网页时显示英文页面的现象了。

日文的缩写通常是 “ja”,而不是 “jp”

  • “ja” 是 ISO 639-1 标准中日语的语言代码。
  • “jp” 通常用来表示 日本(Japan)的国家代码,在 ISO 3166-1 标准中使用。

因此,在国际化(i18n)和多语言网站的语言代码中,日文通常使用 “ja”

只要原因后就好修改了,改成ja也好,保持jp也罢,修正逻辑按照一致的顺序处理,问题也就能解决了。

网站访问统计问题

如果是一个网站开发者遇到这种问题,应该会有一个完整的解决方案,而我这种半吊子的网页开发人员,只想尽快的解决问题,所以我的搜索方向就是怎么尽快解决这个问题。起初搜到的方案是使用 Vercel Analytics 来查看,初始有个免费额度,超过25,000 events要进行收费,因为我的网站就部署在 Vercel 上,所以这种方案应该是最融洽的,查看每月的 events 使用量估算了费用,每月要 $100 以上,纠结中。

然后就搜到了 Google Analytics,介绍里说它完全免费,应用广泛,但是最近评价却不好,一方面是指责它收集隐私信息,另一方面是说它被很多浏览器插件屏蔽,导致无法准确统计,在抵制它的同时很多人都推荐使用了 Umami

Umami 是一个开源的简单、隐私友好的网站分析工具。它提供了类似于 Google Analytics 的功能,但更加专注于数据隐私,且无需依赖第三方 cookies。这使得 Umami 成为那些希望追踪用户活动但又需要遵守严格隐私法律(如 GDPR 或 CCPA)的个人和企业的理想选择。

Umami 是完全开源的(使用 MIT 许可证),代码可以在 GitHub 上找到并自行部署。客户端脚本文件仅约 2 KB,加载速度快,不会影响网页性能。时查看访问者活动,例如当前在线人数、浏览器、设备、地域等信息。

后端:Node.js 和 PostgreSQL。前端:基于 React 构建。部署:支持 Docker,配置简单。技术栈提起来挺简单,但是像我这么懒的人现在还不打算配置一遍,自己配置还要买服务器和数据库,因为我查到它有一个 Umami Cloud

Umami CloudUmami 的云托管服务,提供了一个简单、隐私友好的网站分析工具的在线版本。它允许用户通过 Umami 提供的 Web 界面,无需自行托管和管理服务器即可使用该分析工具。相比自己搭建 Umami,使用 Umami Cloud 可以节省大量的部署和维护成本,适合不想处理服务器配置的用户。

用户无需担心部署和维护服务器,Umami Cloud 提供了一个即开即用的服务,只需要注册并配置网站即可开始使用。与自托管的 Umami 一样,Umami Cloud 注重用户隐私,不收集个人可识别信息。它也不依赖 cookies 或第三方追踪,因此完全符合 GDPR 和其他隐私法规。

用户只需要将提供的 JavaScript 跟踪代码插入到网站页面,不需要任何后端代码,适合非技术用户。Umami Cloud 提供了不同的定价套餐,包括免费和付费版本。免费版本适合小型网站或个人使用,付费版本提供更多的功能和数据存储选项。

看起来数据大了还是得付钱,免费版本限制 100K events per month,Up to 3 websites,6 month data retention,对于我的网站来说还是不够用,但付费的价格相比Vercel算是降了不少,所以我把它的 跟踪代码 胡乱的集成到了我项目的 <head>...</head>中,进而引发了后面的问题

<script defer src="https://cloud.umami.is/script.js" data-website-id="YOUR_WEBSITE_ID"></script>

Error: Empty components are self-closing

这个错误的完整显示如下:

Failed to compile.
30:13  Error: Empty components are self-closing  react/self-closing-comp
info  - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rulesELIFECYCLE  Command failed with exit code 1.
Error: Command "pnpm run build" exited with 1

我的代码开始写成了这样:

export default function RootLayout({children,params: { lng },
}: {children: React.ReactNode;params: { lng: LanguageType };
}) {return (<html lang={lng} className={myFont.variable}><head><script defer src="https://cloud.umami.is/script.js" data-website-id="YOUR_WEBSITE_ID"></script></head><body className="relative font-my">{children}</body></html>);
}

看着ChatGPT的解释我陷入了沉思,不过后来我明白了它的意思,这个错误是由于 ESLint 中的 react/self-closing-comp 规则引起的,该规则要求空的组件标签必须是自闭合的。

解决方法是检查报错所在的代码(通常是在第 30 行第 13 列),很可能是你有一个空的元素,例如:

<div></div>

它应该改成自闭合的写法:

<div />

所以我把代码改成了这样 <head><script defer src="https://cloud.umami.is/script.js" data-website-id="YOUR_WEBSITE_ID"/></head>,去掉了 </script> 然后就报了下面这个错。

Error: A space is required before closing bracket

完整错误如下:

Failed to compile.
30:120  Error: A space is required before closing bracket  react/jsx-tag-spacing
info  - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rulesELIFECYCLE  Command failed with exit code 1.
Error: Command "pnpm run build" exited with 1

这次我还是没反应过来,经过ChatGPT解释发现,之前就已经给出准备的例子了,这个新的错误是由 ESLint 的 react/jsx-tag-spacing 规则引起的,它要求在自闭合标签的闭合括号前留一个空格。所以最终改成下面这样就没问题了

<head><script defer src="https://cloud.umami.is/script.js" data-website-id="YOUR_WEBSITE_ID" /></head>

真是一个空格也不能错啊~

总结

  • 网站的默认语言可以根据浏览器的设置语言来初始化,获取代码简化为 acceptLanguage.get(req.headers.get('Accept-Language'));
  • 网页统计可以使用 Vercel AnalyticsGoogle Analytics 或者 Umami
  • Vercel Analytics 与 Vercel 兼容性好,毕竟出自同一家班底,配合会比较顺畅,应该还会有自家产品的关联优化
  • Google Analytics 依赖 cookies,可能涉及隐私问题,数据存储在 Google 的服务器,由 Google 管理,功能全面,适合复杂需求
  • Umami 完全隐私友好,无 cookies,核心功能足够,但比 Google Analytics 少,可以用户自行托管,完全掌控

==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

他日若是同淋雪,也算此生共白头。在两个人维系的关系中,一方的忍耐退让并不会让另一方生出善意,反而会导致对方以为之前的所有都是理所应当,进而变本加厉。总会有两个人不在一个频道上,你给她讲理,她跟你讲情,你跟她讲情,她跟你讲法,你跟她讲法,他跟你讲理,反正你永远对不了~

相关文章:

浏览器默认语言与页面访问统计问题二三则

文章目录 前言网站默认语言问题网站访问统计问题Error: Empty components are self-closingError: A space is required before closing bracket 总结 前言 看标题大概能猜到这是一篇杂合体的总结&#xff0c;是这两天处理网站遇到的小问题&#xff0c;怕过段时间再忘了所以总…...

用Python绘制一只懒羊羊

目录 一、准备工作 二、Turtle库简介 三、绘制懒羊羊的步骤 1. 导入Turtle库并设置画布 2. 绘制头部 3. 绘制眼睛 4. 绘制嘴巴 5. 绘制身体 6. 绘制四肢 7. 完成绘制 五、运行代码与结果展示 六、总结 在这个趣味盎然的技术实践中,我们将使用Python和Turtle图形…...

虹科分享 | 汽车NVH小课堂之听音辨故障

随着车主开始关注汽车抖动异响问题&#xff0c;如何根据故障现象快速诊断异响来源&#xff0c;成了汽修人的必修课。 一个比较常用的方法就是靠“听”——“听音辨故障”。那今天&#xff0c;虹科Pico也整理了几个不同类型的异响声音&#xff0c;一起来听听看你能答对几个吧 汽…...

论文速读|SigLIP:Sigmoid Loss for Language Image Pre-Training.ICCV23

论文地址&#xff1a;https://arxiv.org/abs/2303.15343v4 代码地址&#xff1a;https://github.com/google-research/big_vision bib引用&#xff1a; misc{zhai2023sigmoidlosslanguageimage,title{Sigmoid Loss for Language Image Pre-Training}, author{Xiaohua Zhai and…...

深度学习笔记——循环神经网络之LSTM

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍面试过程中可能遇到的循环神经网络LSTM知识点。 文章目录 文本特征提取的方法1. 基础方法1.1 词袋模型&#xff08;Bag of Words, BOW&#xff09;工作…...

算法整理:2-opt求解旅行商(Python代码)

文章目录 算法思想算法步骤代码1纯函数代码2纯函数数据可视化 算法思想 通过交换边进行寻优。 算法步骤 把初始解作为当前解 通过交换边生成新解 如果新解优于历史最优解&#xff0c;则更新当前解为新解 重复2&#xff0c;3&#xff0c;直到当前解交换了所有的边均不能改…...

状态模式

在软件开发过程中&#xff0c;我们经常会遇到这样的情况&#xff1a;一个对象的行为会随着其内部状态的改变而发生变化。例如&#xff0c;一个手机在不同状态下&#xff08;开机、关机、静音等&#xff09;对相同的操作&#xff08;如来电&#xff09;会有不同的反应。传统的解…...

RoHS 简介

RoHS&#xff08;Restriction of Hazardous Substances Directive&#xff0c;限制有害物质指令&#xff09;是欧盟制定的一项环保法规&#xff0c;旨在限制电气和电子设备中某些有害物质的使用&#xff0c;以减少这些产品对环境和人体健康的危害。 RoHS限制的有害物质及其限量…...

【Vim Masterclass 笔记26】S11L46:Vim 插件的安装、使用与日常管理

文章目录 Section 11&#xff1a;Vim PluginsS11L46 Managing Vim Plugins1 第三方插件管理工具2 安装插件使用的搜索引擎3 Vim 插件的安装方法4 存放 Vim 插件包的路径格式5 示例一&#xff1a;插件 NERDTree 的安装6 示例二&#xff1a;插件 ctrlp.vim 的安装7 示例三&#x…...

深度学习原理与Pytorch实战

深度学习原理与Pytorch实战 第2版 强化学习人工智能神经网络书籍 python动手学深度学习框架书 TransformerBERT图神经网络&#xff1a; 技术讲解 编辑推荐 1.基于PyTorch新版本&#xff0c;涵盖深度学习基础知识和前沿技术&#xff0c;由浅入深&#xff0c;通俗易懂&#xf…...

ELK环境搭建

文章目录 1.ElasticSearch安装1.安装的版本选择1.SpringBoot版本&#xff1a;2.4.2 找到依赖的spring-data-elasticsearch的版本2.spring-data-elasticsearch版本&#xff1a;4.1.3 找到依赖的elasticsearch版本3.elasticsearch版本&#xff1a;7.9.3 2.安装1.官方文档2.下载压…...

基于Springboot + vue实现的民俗网

“前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff1a;人工智能学习网站” &#x1f496;学习知识需费心&#xff0c; &#x1f4d5;整理归纳更费神。 &#x1f389;源码免费人人喜…...

第24篇 基于ARM A9处理器用汇编语言实现中断<六>

Q&#xff1a;怎样设计ARM处理器汇编语言程序使用定时器中断实现实时时钟&#xff1f; A&#xff1a;此前我们曾使用轮询定时器I/O的方式实现实时时钟&#xff0c;而在本实验中将采用定时器中断的方式。新增第三个中断源A9 Private Timer&#xff0c;对该定时器进行配置&#…...

【数据结构】_不带头非循环单向链表

目录 1. 链表的概念及结构 2. 链表的分类 3. 单链表的实现 3.1 SList.h头文件 3.2 SList.c源文件 3.3 Test_SList.c测试文件 关于线性表&#xff0c;已介绍顺序表&#xff0c;详见下文&#xff1a; 【数据结构】_顺序表-CSDN博客 本文介绍链表&#xff1b; 基于顺序表…...

golang 使用双向链表作为container/heap的载体

MyHeap&#xff1a;container/heap的数据载体&#xff0c;需要实现以下方法&#xff1a; Len&#xff1a;堆中数据个数 Less&#xff1a;第i个元素 是否必 第j个元素 值小 Swap&#xff1a;交换第i个元素和 第j个元素 Push&#xff1a;向堆中追加元素 Pop&#xff1a;从堆…...

C#集合操作优化:高效实现批量添加与删除

在C#中&#xff0c;对集合进行批量操作&#xff08;如批量添加或删除元素&#xff09;通常涉及使用集合类型提供的方法和特性&#xff0c;以及可能的循环或LINQ查询来高效地处理大量数据。以下是一些常见的方法和技巧&#xff1a; 批量添加元素 使用集合的AddRange方法&#x…...

142.WEB渗透测试-信息收集-小程序、app(13)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;141.WEB渗透测试-信息收集-小程序、app&#xff08;12&#xff09; 软件用法&#xff0c…...

24.日常算法

1. 数组中两元素的最大乘积 题目来源 给你一个整数数组 nums&#xff0c;请你选择数组的两个不同下标 i 和 j&#xff0c;使 (nums[i]-1)*(nums[j]-1) 取得最大值。请你计算并返回该式的最大值。 示例 1&#xff1a; 输入&#xff1a;nums [3,4,5,2] 输出&#xff1a;12 解释…...

分布式理解

分布式 如何理解分布式 狭义的分布是指&#xff0c;指多台PC在地理位置上分布在不同的地方。 分布式系统 分布式系**统&#xff1a;**多个能独立运行的计算机&#xff08;称为结点&#xff09;组成。各个结点利用计算机网络进行信息传递&#xff0c;从而实现共同的“目标或者任…...

wordpress调用指定ID页面的链接

在WordPress中&#xff0c;如果你想调用一个指定ID的页面链接&#xff0c;可以使用以下几种方法&#xff1a; 方法一&#xff1a;使用页面ID 你可以直接使用页面的ID来生成链接。例如&#xff0c;如果你想链接到ID为123的页面&#xff0c;可以使用以下代码&#xff1a; <…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)

旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据&#xff01;该数据集源自2025年4月发表于《地理学报》的论文成果…...

CTF show 数学不及格

拿到题目先查一下壳&#xff0c;看一下信息 发现是一个ELF文件&#xff0c;64位的 ​ 用IDA Pro 64 打开这个文件 ​ 然后点击F5进行伪代码转换 可以看到有五个if判断&#xff0c;第一个argc ! 5这个判断并没有起太大作用&#xff0c;主要是下面四个if判断 ​ 根据题目…...

比特币:固若金汤的数字堡垒与它的四道防线

第一道防线&#xff1a;机密信函——无法破解的哈希加密 将每一笔比特币交易比作一封在堡垒内部传递的机密信函。 解释“哈希”&#xff08;Hashing&#xff09;就是一种军事级的加密术&#xff08;SHA-256&#xff09;&#xff0c;能将信函内容&#xff08;交易细节&#xf…...