存档

‘日常’ 分类的存档

老款 Mac 升级记录

2025年6月7日 没有评论

我那个2011年的老 Macbook Pro停留在 High Sierra(10.13.6)再也无法获得更新,这是我的第一台水果电脑,当年学习iOS开发可是出了不少力,所以对这个电脑很有感情的。

在吃灰了好多年后,昨天有突发奇想就给开机了,这一开机后,就想着怎么给升级系统,如果升级后XCode 可以支持我的 iPhone 8 就更好了。

经过一番搜索,发现了一个叫做 macOS Catalina Patcher 的开源工具可以帮忙实现升级到 Catalina(10.15.7),这就不错了,升了2个版本的系统。

下载完成并解压缩后,打开这个工具,你可以看到一个选项窗口,询问你新的Catalina系统,如果你已经有系统副本,可以选择 Browse for a Copy。如果没有,就点击 Download 来下载一个,大概有8G左右。对于衣服自己洗来说,当然是直接下载比较直接了。下载略微需要点时间,不过感觉还好。

接下来,选择安装方法,我直接安装到系统盘,已经是老mac了,大概率也不会有问题。当然你还可以选择第二个选项,准备一个16GB 的 U 盘来安装。第三个是光盘安装,现在光盘和光驱已经很少见了。

后面就是无脑下一步了,下载完成后,点击安装。安装过程中,你会看到一些提示和选项。按照提示一步步操作就行。这里就不说细节了,因为已经忘记了。

接下来就是设置新系统了,电脑会自动重启几次。最后算是升级成功了吧。

说下我的感觉:

  1. 升级后电脑的发热量没有明显的变化,但是系统响应变慢了点。
  2. WiFi 无线会抽风断网,不知道是否和这个有关系。
  3. 原本 /Code 文件夹,给挪到桌面了,说是不兼容,估计因为是放根目录的原因。
  4. 升级后终于可以安装 .net8 和 Jetbrains 全家桶了,就是慢。

感谢观看。

分类: 日常 标签:

react-i18next 进阶用法

2025年4月14日 没有评论

在过去的 React 和 React Native 项目里,对于多语言处理,使用的是 react-i18next 来处理的。今天给大家分享下这个库的一些进阶用法和注意事项。

其实一开始的时候,我自己是有点困惑的,react-i18next 和 i18next 是什么关系?为什么项目要安装这2个库,而不是一个?而且为什么在代码里如何从 i18next 里导入某些变量会出现非预期的结果。所以这里也给小伙伴解释下,react-18next 是对 i18next 的 react 版本封装。换句话来说,一般情况下,大家直接使用 react-i18next 库就可以了。

安装很简单:

npm install react-i18next i18next --save

进阶一、兼容性问题

如果你的代码在运行时出现了下面的错误:
i18next::pluralResolver:
Your environment seems not to be Intl API compatible,
use an Intl.PluralRules polyfill.
Will fallback to the compatibilityJSON v3 format handling.
那么按照官方的说明(https://www.i18next.com/how-to/faq#why-are-my-plural-keys-not-working),表示当前环境不兼容 Intl API。

解决方法:

npm install intl-pluralrules --save

然后在多语言的初始化文件里导入:

import 'intl-pluralrules'

这取决于你的 项目结构,可能就在 index.js 里,我们的项目就是在 i18n.ts 文件里。

这个问题,在我们的 React Native 项目里有碰到过。

进阶二,传字段

例如有下面的 json 文件:

{
    "error": {
        "required": "{{field}}必填",
        "invalid": "无效的{{field}}"
    }
}

那么使用时,就是这样使用的:t(‘error.required’, { field: t(‘Email’) })

进阶三,自定义多语言层级分隔符

默认情况下,代码里使用 . 来表示层级,例如 error.required,当然也可以使用下面的配置来更改为使用 “/”:

i18n.use(initReactI18next).init({
  // ...
  keySeparator: '/'
})

那么前面的调用就成了 t(‘error/required’, { field: t(‘Email’) }),我是觉得这个一般情况下是不必无苦硬吃的,可能在特殊场合需要使用。大家看看就可以。

进阶四,自动单复数

i18next 对于自动单复数有预定的约定,只需要在 key 后面添加 “_other” 即可,当然前提是对应的语言描述有复数的用法哈。

{
"hours": "{{ count }} hour",
 "hours_other": "{{ count }} hours",
}

t('hours', { count: 5 }) 
// 5 hours

对于 0 来说,实际来看,会使用复数的翻译,例如 0 hours。如果需要为 0 来单独定义的话,可以添加 “_zero”,例如:

"hours_zero": "Now"

需要提醒的是,如果这里内置的 _zero、_other 和你的多语言冲突了,还是有这个可能的,那么可以修改使用自定义分隔符,例如下面这样:

// i18n.ts
i18n.use(initReactI18next).init({
  ...  // 其它配置   
  pluralSeparator: '__', // 双下划线
})

具体使用:

{
    "days": "{{count}} day",
    "days__other": "{{count}} days",
}

进阶五,Trans 组件

这里直接借用网上的一个示例,假如要显示下面的文字“你好 {userName},你有 {count} 条未读消息。点击查看。”,并且还需要支持点击操作。

在以前的写法中,我们需要将这句话单独的拆开,使用不同的组件包装起来,例如 count 希望是一个
红色的字体之类的,还要放到不同的多语言 key 里。太费劲了。

使用 Trans 组件,可以这么写,大家琢磨琢磨,是不是简单很多。

// en.json
{
    "userMessagesUnread": "Hello <1>{{userName}}</1>, you have {{count}} unread message. <5>Click to view</5>.",
    "userMessagesUnread_other": "Hello <1>{{userName}}</1>, you have {{count}} unread messages.  <5>Click to view</5>."
}

<Trans
    defaults={t('userMessagesUnread')}
    values={{ count, userName }}
    parent={Text}
    components={{
        1: <Text style={{ fontWeight: '500' }} />,
        5: <Text style={{ color: '#4682A9' }} onPress={() => {}} />
    }}
/>

可以看到,通过使用 components 属性,借助索引可以将指定位置的元素给替换包装起来。那么有人就问了,为什么这里是数字1和5,而不是其它的呢?

Trans 组件将上面的文本转换为下面的结构:

[
  'Hello ',
  { children: [{ user_name: 'Admin' }] },
  ', you have ',
  { count: 10 },
  ' unread messages. ',
  { children: ['Click to view'] },
  '.'
]

这么来看,是不是基于 0 的索引位置就出来啦。

更多内容,可以参考官方文档说明。

分类: 日常 标签: ,

NAS 上使用 Let’s encrypt 动态 DNS 续期 SSL 证书

2025年2月2日 没有评论

背景是我在 NAS 上部署了 immich 来存放照片,基于方便使用和安全考虑,使用 https 可能更合适。熟悉 immich 的小伙伴可能知道,这个应用需要使用反向代理来支持 SSL,虽然对于不能直接支持感觉不可思议, 但是这也不是太大的问题,开个 nginx 镜像也就实现了反向代理,关键是如何支持 SSL 证书。

现在家庭使用的基本上都是动态 IP,想要正确解析域名到实际 IP 就比较麻烦,好在 NAS 上支持动态 DNS 的解析,衣服自己洗使用的是 DNSPod,所以从里面导出一个 api key,放到 NAS 里就可以了,因为只需要很简单地无脑下一步,所以这里就不展开描述了。

但是,接下来我有碰到一个问题,由于对于家庭 IP 地址来说,80 和 443 端口一般是被运营商给禁止了的,所以 DNS 校验的方式就走不通,退而求其次看域名解析,而 certbot 又不支持 DNSPod 的,搜索了一番,网上有现成的,于是做了一个 docker 镜像,在 NAS 上部署。

第一步:克隆仓库

git@github.com:chenlongqiang/docker-certbot-dnspod.git

第二步:构建镜像

cd docker-certbot-dnspod
docker build -t certbot-dnspod .

请注意,上面命令最后还有一个英文的句号哟。

第三步:更新 dnspod.ini 配置,可以在 https://console.dnspod.cn/account/token/token 进行 DNSPod Token 秘钥创建。

第四部:部署镜像

# 申请新证书,执行后会进行命令行交互,填写完信息后将在 certs 目录下生成申请成功的证书
docker run -it --rm -v ./conf/dnspod.ini:/data/certbot/dnspod.ini -v ./certs:/etc/letsencrypt certbot-dnspod -d your_domain.com -d "*.your_domain.com"

# 续期 certs 目录下的证书
docker run -it --rm -v ./conf/dnspod.ini:/data/certbot/dnspod.ini -v ./certs:/etc/letsencrypt certbot-dnspod renew

请注意,如果不需要一次性,那么可以不添加 –rm 参数。同时请修改 dnspod.ini 的路径为你的实际路径。

经过验证,确实可以获取到 Let’s encrypt 生成的证书,然后更新到 nginx 的路径里。

不过,一个 https 的地址还带端口号,看着就怪怪的。

分类: 日常 标签:

解决 error listen EACCES: permission denied 0.0.0.0:8081

2025年1月9日 没有评论

今天发现电脑在重启后,打开 NodeJS 项目后无法运行,提示 8081 端口被占用了。一开始以为是某个 node 非正常占用导致,关闭所有相关的软件并确认没有node 进程存在后,再次运行项目,发现还是提示端口被占用。

按照我先前整理的《查找端口被占用的程序,执行 netstat -ano | findstr 8081,发现找不到占用端口的进程。

看来要狂暴一下了。

经过一番搜索,网上有一个观点是端口被 WSL 占用了,大意是微软在使用 reservation/exclusion 机制来进行动态端口分配时,分配的端口号有的比较低,所以导致和其它软件冲突。

运行下面的命令:

netsh int ipv4 show excludedportrange protocol=tcp

发现 8081 端口在范围里面。

运行下面的命令:

netsh int ipv4 show dynamicport tcp

可以看到系统赋予的起始端口号确实比较低。

解决方法,就是重新设置动态端口的区间范围,例如运行下面的命令:

netsh int ipv4 set dynamic tcp start=49152 num=16384

非常重要的是,需要重启电脑。

重启后可以重新运行命令来确认下:

netsh int ipv4 show excludedportrange protocol=tcp

最后提醒大家的是,运行上面的命令时,最合适地是使用管理员权限来运行。

分类: 日常 标签:

限制 mysql 的内存占用

2024年12月5日 没有评论

最近发现站点经常无法打开,以往都是直接重启服务器,偷懒省事。后来无意间在控制台登录,发现原来是 mysql 的内存占用过大,导致 out of memory,被系统杀掉了进程。

按道理来说,一个小破站,真的需要那么大的内存占用么,而且这么多年来大部分时间都没有问题,也不清楚具体是从什么时候开始有这个问题了。

按照网上的教程,结合服务器上的配置。

cd /etc/mysql/mysql.conf.d

修改 mysqld.cnf 这个文件,添加或者更新一条配置

innodb_buffer_pool_size = 100M

大家结合自己的实际情况来修改吧,这个默认值看起来是 128M。

网上还有更新下面的配置,我没有设置,先跑跑看。

# 设置最大连接数
max_connections = 100
# 设置线程缓存大小
thread_cache_size = 16M
# 设置每个连接最大的查询缓存大小
query_cache_size = 64M

不要忘记 sudo service mysql restart

分类: Server, 日常 标签:

推荐使用 RustDesk

2024年11月25日 1 条评论

先前一直用的是 TeamViewer 来作为远程访问工具,在过去的几年里,远程看 bug,确实方便了很多。后面因为不可描述的原因不能再续费了,而 TeamViewer 免费版本除了限制商业使用外,又限制了登录的机器数量,直接无法使用,只好转而看看其它替补版本。

像出现了很久的向日葵,还有后面的 ToDesk,AnyDesk,一直都有在关注中,但是这些吧,怎么说呢,在某些方面不是很贴切自己的使用需求。观察了很长时间,最后还是选择了 RustDesk。

RustDesk,首先是免费开源,而且支持自部署,就非常有吸引力了。同其它远程工具一样,官方有提供免费的连接,网速不见得总是可以满足要求。再加上前段时间国内一些**们利用这个工具来诈骗的恶意行为,导致限制的更加严格,所以使用自有服务器来中转流量就非常有必要了。

软件使用起来非常简单,和其他软件大同小异,输入对方的数字编号和对应的密码,就可以使用了。默认情况下,软件是以非管理员权限运行的,同时也禁止远程修改配置。对于自己个人使用,可以选择安装以系统服务的方式运行,这样就进一步去掉了限制。

因为某种原因,只能以非安装的方式运行,但是在远程机器锁屏后,就无法登录,哪怕 RustDesk 是以管理员权限启动的。

检索了一下,可以通过修改组策略的方式来解决:

1,运行 gpedit.msc 打开组策略管理器
2,计算机配置->Windows设置->安全设置->本地策略->安全选项->用户帐户控制:提示提示时切换到安全桌面,选择关闭这个选项就可以了。

衣服自己洗这里没有验证这个改动会有什么后果,字面看起来应该是一个全局的影响,大概率其它远程工具也会受到影响,不过个人使用无所谓了。

验证了一下,在非安装的方式的场景下,锁屏后可以正常地远程登录了。大家记得开启隐私模式喔,不然远程电脑的屏幕是会实时显示操作的,略微有些尴尬。

即使已经登录了,如果打开文件传输功能,还是需要再次输入密码,这个不是太方便,不如 TeamViewer,吐槽一下。

分类: 日常 标签:

安卓手机无法被电脑发现的一种解决方法

2024年10月9日 没有评论

最近发现安卓手机在通过 USB 数据线连上了电脑后,发现只有充电,但是电脑无法识别到设备,这就很影响 USB 调试程序。

一直没有搞清楚怎么回事,都是反复尝试,或者重启手机,有的时候还是有效果的,反正平日一直都是插上去不拔的,而且也不是总有这个问题,概率性的。于是在将就用着。

只是今天发现无论如何都无法识别到手机,确认系统的开发者模式和调试模式都有打开,而且手机上也反复提示请检查数据线。要知道这可是原装的数据线,怎么可能有问题。

无意间随手把鼠标的无线接头和这个数据线互换了下位置,发现鼠标没有作用了。顿感不妙,感情是这个USB接口有问题?

问题是我的电脑就只有这2个USB接口,其它的是 type-C 接口,以后还要用个 type-C 和 USB 的转接头,想想都尴尬的慌。

过了几个小时,还是不死心,于是就网上各种搜索,但是很多帖子都没有太大的意义,我同时也很确定驱动是没有问题的。

但是有几个帖子提到了电源管理的问题,本来是不信想放弃的,寻思着如果这个没有效果就不再尝试了。

打开设备管理器,找到 “USB Root Hub”节点,选择“属性”->“电源管理”,取消“允许计算机关闭此设备以节约电源”

衣服自己洗这里需要提醒各位的是,在设备管理器里可能存在多个相同的节点,所以要准确找到那个 USB 接口对应的设备。我为了找到这个设备,第一次禁用的就是无线鼠标的那个USB接口,鼠标马上就不能用了,只好重启了一次电脑。

取消勾选后,手机就正常弹出USB调试授权提示了,也不会有数据线不匹配的提示了。

再复盘回忆,衣服自己洗突然想起来,应该是去办公室开会,然后电池没有电了,电源管理软件自动跳转了系统设置,导致这个 USB 接口只输出少量电量。这也是手机总提示数据线不匹配的问题,而鼠标接口没有问题,是因为在开会时,一直有用鼠标,所以这个设备节点不会主动调整。而前面提及的概率性的,是因为去会议室开会,如果没有带电源线而恰好电量不足时才会有这个问题。

前后都对的上,我真是个大聪明。

分类: Android, 日常 标签:

火绒怎么关闭证书劫持

2024年9月7日 没有评论

由于某些原因,安装了火绒6.0,但是在某一天无意间发现自己的网站SSL证书颁发者居然是火绒,导致无法判断自己的证书过期时间等。网上搜索了下,貌似卡巴斯基也提供了类似的机制。

对于普通的用户来说,这个功能算是不错,但对自己的网站来说,显得有点画蛇添足了。

于是检索如何恢复原状,最后发现是火绒提供的 web 扫描导致的。

关闭方式:病毒防护-》Web扫描-》设置-》加密连接扫描,把这个选项给关闭就可以了。

如果大家不想关闭,可以把排除的网站添加到设置页面下方的那个“网站列表”里。

分类: 一句话, 日常 标签:

Ollama 使用第三方模型

2024年8月1日 1 条评论

llama3 确实不错,但是大家都说其对中文支持的不够好,所以网上有人基于 llama3 进行了微调,并提供了下载地址:https://huggingface.co/zhouzr/Llama3-8B-Chinese-Chat-GGUF/tree/main

大家根据自己的机器性能按需下载,比如 q4_k_m 什么的,简单地讲,体积越大对硬件的要求越高。

再下载回来后,要如何导入,以前不是太了解,而且官网又是英文的说明。

幸运地是,有找到一个中文示例。

首先,我们可以打开命令行,看看官方的 llama3,输入命令

ollama show --modelfile llama3

屏幕上会打印一堆的信息,我们给拷贝出关键的数据如下:

FROM C:\Users\Administrator\.ollama\models\blobs\sha256-00e1317cbf74d901080d7100f57580ba8dd8de57203072dc6f668324ba545f29
TEMPLATE "{{ if .System }}<|start_header_id|>system<|end_header_id|>

{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>

{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>

{{ .Response }}<|eot_id|>"
PARAMETER stop <|start_header_id|>
PARAMETER stop <|end_header_id|>
PARAMETER stop <|eot_id|>
PARAMETER stop <|reserved_special_token

需要提醒的是,第一行里需要修改为你下载的模型的实际路径,不要搞忘记了。然后保存这个 modelfile。

第二步呢,就是把这个 modelfile 给导入到 ollama 里,运行下面的命令:

ollama create llama3-Chinese:8B -f Modelfile

还是一样的,修改上面的模型名字,以及保存的 modelfile 实际路径。

不出意外的话,就会显示成功字样。

第三步,我们来再次确认下,是否导入成功了。输入下面的命令:

ollama list

如果看到了刚才的模型名称,就表示 OK 了。

正所谓“会者不难”,一看就非常简单。

唯一不太爽的就是,这些模型都太占磁盘空间了。期待 P 级存储早日白菜价。

分类: AI, 日常 标签:

Error launching installer 的一种解决方法

2024年6月5日 没有评论

对于电脑上的图片预览工具,看了这么多,还是 Google 家的 Picasa 是最好用的,可惜的是停止开发了。幸运的是,有好心人提供了 Picasa 3.9.136.9 提取版,移除了图片管理等无关的功能,只保留了图片预览。

所以这么多年来,这个工具一直很好用。

最近在一个测试机器上安装时,软件报告 Error launching installer 错误。从提示来看,这个提取版使用的是 NSIS 来打包的。

一开始,以为是语言包的问题,为系统添加了中文语言包后,发现无效。

接着寻思,是不是因为时间过于久远,需要 C++ 运行时,然后吧啦吧啦一顿安装,发现还是无效。

后来在网上无意间发现有个帖子说,出现这个错误,可能需要重启电脑。突然想起来,确实在几天前安装了某个软件,当时提示要重启系统,直接给忽略了。

果然,重启系统后,Picasa 提取版可以顺利安装了。

[2024/9/20] 补充

今天在安装了 tiny11 的新机器上又碰到了这个问题,重启后发现没有效果。经过搜索,网上的说法还是和语言有关系,安装包不能包含 unicode 类型的字符,稳妥的做法是:1、将安装包重命名,只包含英文字母。2、将安装包移动到纯字母的路径下后再运行。

虽然界面看起来怪怪的,但是终于可以安装了。

分类: 一句话, 日常 标签: