如何在Django中实现JSON文件存储的静态地理数据的多语言翻译
问题核心原因
Django的makemessages命令仅会扫描代码中的字符串字面量作为待翻译词条,动态从JSON文件读取的变量内容不会被识别,因此你之前的写法里只有硬编码的--- Select a Country ---可以正常翻译。
下面是两种可直接落地的实现方案:
方案1:预生成翻译词条列表(推荐,无需修改原有JSON结构)
核心逻辑是提前把所有需要翻译的地名提取为静态字面量列表,让makemessages可以正常扫描,运行时的原有读取逻辑完全不用改。
操作步骤:
- 写一个自动提取脚本
extract_geo_names.py,批量导出JSON中所有需要翻译的地名:
import json def extract_names(): # 替换为你的JSON文件路径 with open('myproj/static/data/countries_states_cities.json', 'r', encoding='utf-8') as f: all_data = json.load(f) # 用set去重 trans_names = set() for country in all_data: trans_names.add(country['name']) # 需要翻译省份、城市的话把下面注释打开 # for state in country.get('states', []): # trans_names.add(state['name']) # for city in state.get('cities', []): # trans_names.add(city['name']) # 生成供makemessages扫描的py文件 with open('myproj/geo_translations.py', 'w', encoding='utf-8') as f: f.write('from django.utils.translation import gettext_lazy as _\n\n') f.write('# 仅用于扫描待翻译词条,不会被业务代码直接调用\n') f.write('GEO_TRANSLATIONS = [\n') for name in sorted(trans_names): escaped_name = name.replace('"', '\\"') f.write(f' _("{escaped_name}"),\n') f.write(']\n') if __name__ == '__main__': extract_names()
- 运行该脚本,会在项目根目录生成
geo_translations.py文件。 - 执行
django-admin makemessages -l fr命令,工具会自动扫描该文件中的所有地名,加入.po翻译文件,正常完成翻译后执行compilemessages编译即可。 - 你原来
forms.py中的代码不需要做任何修改,运行时_(x['name'])会自动匹配已编译的翻译结果。
方案2:JSON内置多语言字段(适合多语言数据更新频繁的场景)
如果你不想维护Django的gettext翻译体系,可以直接给JSON增加多语言字段,运行时根据当前激活语言直接取值:
- 修改JSON结构,给需要翻译的字段增加多语言版本:
{ "id": 1, "name": "Afghanistan", "name_trans": { "fr": "Afghanistan", "zh-hans": "阿富汗", "es": "Afganistán" }, // 其他原有字段保持不变 }
- 修改
forms.py中的读取逻辑:
from django.utils.translation import gettext_lazy as _ from django.utils import translation def get_country(): filepath = 'myproj/static/data/countries_states_cities.json' all_data = readJson(filepath) # 获取当前激活的语言 current_lang = translation.get_language() all_countries = [('----', _("--- Select a Country ---"))] for x in all_data: # 找不到对应语言的翻译就回退到英文原名 country_name = x['name_trans'].get(current_lang, x['name']) all_countries.append((x['name'], country_name)) return all_countries
这种方案不需要执行makemessages和compilemessages命令,多语言数据直接维护在JSON中,适合有现成多语言地名数据集的场景。
注意事项
- 采用方案1时,每次更新JSON中的地名后,都需要重新运行提取脚本、再执行
makemessages更新翻译词条。 - 地名翻译量大的话,可以直接找现成的ISO标准国家/省市多语言数据集,批量导入到po文件或者JSON的多语言字段中,无需手动逐条翻译。
内容的提问来源于stack exchange,提问作者ionecum
相关产品推荐
相关产品推荐

