However, redundant resources accumulate significantly after i18n is supported in this site. Post in different language should have different content, while the resources should be the same. Below is the directory structure of source. Resource directories with (*) in different language are duplicated and can be optimized.
At first, in order to reduce the impact on how resources are referred in the previous way, I need to design how static assets are organized. Luckily, just move all duplicated resource directories to /source/images as below (directories with (*)), then few changes need to be made if resources are referred by relative path.
Then, find a way to replace path of resource refered in each post. Because resource can be referred by relative or absolute path (starts with http or https or /), if by absolute path then just use that path, otherwise find resource in a directory with the same name as the post in the /images directory. So only relative path need to be converted to /images/[prefix]/[name]/[resource], in which name means post name, resource means resource name, while prefix means path from /source/[lang] to post.
For exmaple, for post /2025/07/my-post.md regardless of language.
If resource is referred as ./image.png, resource path will be converted to /images/2025/07/my-post/image.png. In this case, prefix is 2025/07, name is my-post, resource is image.png. Notice if you use relative path, make sure it always starts with './'. If you use ../another-post/image.png, it will not be converted to /images/2025/07/another-post/image.png. If you do need to use resources belonging to another post, try to use abosulte path like /images/2025/07/another-post/image.png.
If resource is referred as /images/2025/07/my-post/image.png, since it's absolute path, resource path will not be converted.
Create a file named as hexo-filter.js in themes/arch/scripts and use following code. In callback of after_post_rende, all data including original content and parsed content and page meta information can be accessed. Get the src of all <img> and apply the above path conversion if src is relative path. That's it.
// 处理 albums 类型的 children 字段 if (type === "albums" && Array.isArray(data.children)) { data.children.forEach((child) => { if (child.cover) { child.cover = replaceRelativePath(child.cover, prefix); } }); }
// 处理 album 类型的 resources 字段 if (type === "album" && Array.isArray(data.resources)) { data.resources.forEach((resource) => { if (resource.src) { resource.src = replaceRelativePath(resource.src, prefix); } }); } return data; });
Usage
If resource is referred using <img /> by relative path in post, nothing needs to be done. For albums and album type page, since there are absolute path, some changes are made as below.
Please keep in mind that resource path is only converted when you using <img /> with relative path. Core logic as below.