Self-hosted service
ZingLix/immich-geodata-cn avatar
ZingLix/immich-geodata-cn

immich-geodata-cn: Chinese place names for Immich reverse geocoding

为 Immich 提供中文反向地理编码支持,将照片拍摄地点转换为熟悉的中文名称,并支持通过中文地名搜索照片

770 stars59 forksPythonGPL-3.0

At a glance

What is it?
This project replaces the place names Immich attaches to your photos with Chinese administrative names, normalised to province, city, county and town level. The data is a set of downloadable files that you mount into the container, and the file you pick decides both the detail and the speed of the lookup.
Who is it for?
immich-geodata-cn is worth adopting if you run Immich on a photo library shot in China and want readable place names plus Chinese place search, and if you are comfortable editing a docker-compose volumes block and re-running the metadata extraction job once. It is the wrong choice for a library that is mostly outside China, since overseas coverage is experimental and currently limited to Japan, and it is unsuitable if you cannot touch your container configuration.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: every photo lands in an English place name

Immich can attach a location to a photo by reverse geocoding the coordinates it finds in the image metadata, and the default result tends to be an English place name, sometimes an obscure one that does not match the name a Chinese speaker would use. That is the gap this project fills. It publishes a geodata set that localises the addresses for China, including Hong Kong, Macao and Taiwan, and it normalises the result rather than passing the raw geocoder string through.

The normalisation is the part that separates it from a simple translation pass. The documentation states that addresses are standardised through the AMap and Nominatim APIs into four administrative levels, first through fourth, so the output reads as a hierarchy the user recognises rather than a village or an untranslated romanisation. The specific level of granularity is selectable, which means the same dataset can back a country and province view or a town level view. The project describes its overseas support as experimental, with Japan currently included.

The file suffix picks the administrative level, not the language

Distribution is a set of zip archives, and the naming convention is where the configuration lives. Each suffix encodes which administrative levels are present. Using Suzhou in Jiangsu province as the worked example from the documentation, the base archive and the second level archive both stop at the city, a third level archive adds the county, a fourth level archive adds the town, and combined archives exist for pairs and for all three of the deeper levels. Every archive also has a _full variant.

The _full variants carry more data. The documentation says they perform better at boundary positions, where a coordinate falls close to the edge of a region and the wrong match is easy, at the cost of slower encoding. That is a genuine trade-off rather than a free upgrade, and for a large library the lookup speed argument usually matters more than boundary accuracy. The plain archives are the sensible starting point, and the deeper archives are worth switching to only if you have seen misattributed locations.

Two release channels with different failure behaviour

The project publishes on two channels, and the difference matters operationally. The auto-release channel is updated more frequently and is the recommended one, but because the underlying data source can change, an update occasionally produces a file that does not work. The documentation tells you to fall back to the manual release channel and open an issue if that happens. The manual channel is described as relatively stable and is offered as the backup option.

So the faster channel is also the riskier one, and that shape will look familiar to anyone who has automated a data feed. There is no checksum guidance or rollback procedure in the documentation, which means the practical safety net is keeping the previous archive on disk. The manual releases are named by date, with release-2026-08-10, release-2026-06-28 and release-2026-06-03 among the listed ones, and the repository states that it pulls fresh geographic data on a weekly basis and publishes a new version automatically.

Mounting the archives into the Immich server container

Installation is a download and a volume mount. You fetch two archives from the release page, geodata.zip and i18n-iso-countries.zip, and extract them. The second archive supplies the country name translations that the server reads from the i18n-iso-countries package, so both need to be in place before the mount.

For the official immich-app/immich-server image, the volume paths differ depending on the Immich version you are on, which is the single most likely source of a failed install.

yaml
# immich version >= 1.136.0
volumes:
  - ./geodata:/build/geodata
  - ./i18n-iso-countries/langs:/usr/src/app/server/node_modules/i18n-iso-countries/langs

Older releases put the countries languages one directory higher, and the geodata path stays the same.

yaml
volumes:
  - ./geodata:/build/geodata
  - ./i18n-iso-countries/langs:/usr/src/app/node_modules/i18n-iso-countries/langs

The i18n-iso-countries path moves when Immich restructures its application directory, so a mount that worked on one version can silently stop applying after an Immich upgrade.

Third party images put the data in a different place

Not every deployment runs the official image. The documentation gives the equivalent mount for the imagegenius/immich image, contributed by a user in a discussion thread, and the geodata destination is entirely different because that image uses a different internal layout.

yaml
volumes:
  - ./geodata:/app/immich/data/geodata
  - ./i18n-iso-countries/langs:/app/immich/server/node_modules/i18n-iso-countries/langs

This is the clearest sign that the project sits outside Immich's own configuration surface. There is no setting in the Immich interface for a localised geodata path. The integration is a bind mount into container internals, and the documentation notes that you can substitute the target folder to match your own deployment. The consequence is that an Immich upgrade, an image change, or a switch from the official image to a third party one can invalidate the mount without any error inside Immich itself, so the mount belongs in version control next to your compose file.

The import log and the date file decide when data reloads

After the volumes are in place, the server is restarted with docker compose down && docker compose up. The documentation gives a specific check for success: the startup log should show a line like 10000 geodata records imported, and that line is the signal that the geodata was picked up.

If the line does not appear, the documented fallback is to edit the date in geodata/geodata-date.txt and set it to the current time. The reason is that Immich only reloads the data when the file date is newer than the last load it performed, so a fresh download with an older timestamp can be ignored even though the files changed. That behaviour is easy to misread as a broken mount. It is worth knowing that the date file is part of the archive, not something the project patches for you after an upgrade.

One related constraint: the project instructs you to restart Immich after replacing the archives, because the data is read at startup rather than watched for changes.

Updating the data on a schedule without manual downloads

Updating by hand is a download, a replace and a restart. The project provides a script in the geodata directory that does the download and replacement, and it takes the archive name you want as its argument, for example geodata_admin_2. The script is fetched directly from the repository.

bash
curl -o update.sh https://raw.githubusercontent.com/ZingLix/immich-geodata-cn/refs/heads/main/geodata/update.sh

Running it replaces the data in place.

bash
bash update.sh geodata_admin_2

The script does not restart the server, and the documentation says to add a restart command at the end of it, optionally combined with a scheduled job. A weekly Saturday morning entry is given as the pattern.

bash
5 5 * * 6 bash /immich_data/geodata/update.sh && docker restart immich_server

This is the part of the setup that quietly changes your system over time. A cron job that pulls a new archive from a source the project warns can occasionally break is a different risk profile from a manual refresh, so the first update should be run by hand and inspected before it is scheduled.

Generating your own data instead of downloading it

The alternative to downloading an archive is generating the dataset, and the repository keeps the generation inputs in the geodata directory for anyone who wants to customise them. The Python dependencies give a fairly direct picture of the pipeline: opencc and zhconv for Chinese conversion, requests and ratelimit for calling the upstream APIs, and eviltransform for coordinate system handling. The documentation points at the geodata directory for details on how the data is produced and how to customise it, and the pipeline also relies on the AMap and Nominatim APIs for the administrative standardisation that produces the four level hierarchy.

Running your own pipeline is the option for someone who needs a specific granularity, a specific set of regions, or a data source the official archives do not cover. It also means owning the failure modes, since the API calls, the rate limits and the coordinate handling become your operational surface rather than the maintainer's. The published archives remain the right default for anyone who just wants Chinese place names.

On licensing, the project is distributed under GPL. That matters for redistribution of the data or of derived builds, so read the LICENSE file before shipping a modified copy in a product, and note that the project asks for sponsorship rather than charging, stating a commitment to keep it free to use.

Editorial conclusion

immich-geodata-cn is worth adopting if you run Immich on a photo library shot in China and want readable place names plus Chinese place search, and if you are comfortable editing a docker-compose volumes block and re-running the metadata extraction job once. It is the wrong choice for a library that is mostly outside China, since overseas coverage is experimental and currently limited to Japan, and it is unsuitable if you cannot touch your container configuration. Before you switch to the auto-release channel, verify that the archives you download still import, and check the mount paths for your image, because the i18n-iso-countries path differs between Immich versions before and after 1.136.0.

Frequently asked questions

How do I install immich-geodata-cn into my Immich server?

Download geodata.zip and i18n-iso-countries.zip from the release page, extract them, and add the two volume mounts for your Immich version to the docker-compose file, then restart Immich with docker compose down && docker compose up. A startup log line such as 10000 geodata records imported confirms the data was loaded.

What is the difference between geodata.zip and the admin level archives?

The suffix selects which administrative levels the data contains, from city level up to town level, and combined archives exist for specific pairs of levels. Every archive also has a _full variant with more data, which the documentation says improves boundary detection at the cost of slower encoding.

How often does the Immich geodata in immich-geodata-cn change?

The repository states that it pulls the latest geographic data on a weekly basis and publishes updated versions automatically. The auto-release channel updates more often but can occasionally produce a file that does not work, while the manual release channel is the more stable fallback.

Do existing photos get Chinese place names after installing immich-geodata-cn?

Yes, but only once, and only for the first install. The documentation says to run the metadata extraction job for all photos in the system administration area, and that later photos do not need the same step because the new data applies to them automatically.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. README
  4. Releases
  5. ZingLix/immich-geodata-cn on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/zinglix-immich-geodata-cn.svg)](https://hysenlabs.com/projects/zinglix-immich-geodata-cn)

Was this useful?